summaryrefslogtreecommitdiffstats
path: root/src/v8/0004-Introduce-a-QML-compilation-mode.patch
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-10-11 15:06:25 +1000
committerQt by Nokia <qt-info@nokia.com>2011-10-19 20:48:25 +0200
commit7dc5973bf12919d2d35230844beabe558d4faa00 (patch)
tree88d6128a911d2ec3b9a72d8e45d56fc2b250c714 /src/v8/0004-Introduce-a-QML-compilation-mode.patch
parent4dc25c1f2995a5e02da47f0f6f3522af9eb6f78c (diff)
Update V8
Change-Id: I7a9da7dbb2116a441788407d60ed10155cded941 Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Diffstat (limited to 'src/v8/0004-Introduce-a-QML-compilation-mode.patch')
-rw-r--r--src/v8/0004-Introduce-a-QML-compilation-mode.patch1871
1 files changed, 1871 insertions, 0 deletions
diff --git a/src/v8/0004-Introduce-a-QML-compilation-mode.patch b/src/v8/0004-Introduce-a-QML-compilation-mode.patch
new file mode 100644
index 0000000000..4b79d94e68
--- /dev/null
+++ b/src/v8/0004-Introduce-a-QML-compilation-mode.patch
@@ -0,0 +1,1871 @@
+From 27ef7b7b37255a9965fe31fb7597720f57ed5154 Mon Sep 17 00:00:00 2001
+From: Aaron Kennedy <aaron.kennedy@nokia.com>
+Date: Wed, 5 Oct 2011 13:01:30 +1000
+Subject: [PATCH 04/11] Introduce a QML compilation mode
+
+In QML mode, there is a second global object - known as the QML
+global object. During property resolution, if a property is not
+present on the JS global object, it is resolve on the QML global
+object.
+
+This global object behavior is only enabled if a script is being
+compiled in QML mode. The object to use as the QML global object
+is passed as a parameter to the Script::Run() method. Any function
+closures etc. created during the run will retain a reference to this
+object, so different objects can be passed in different script
+runs.
+---
+ include/v8.h | 19 ++++++++--
+ src/api.cc | 52 ++++++++++++++++++++++++-----
+ src/arm/code-stubs-arm.cc | 4 ++
+ src/arm/full-codegen-arm.cc | 28 +++++++++-------
+ src/arm/lithium-arm.cc | 2 +-
+ src/arm/lithium-arm.h | 6 +++-
+ src/arm/lithium-codegen-arm.cc | 7 ++--
+ src/arm/macro-assembler-arm.h | 5 +++
+ src/ast-inl.h | 5 +++
+ src/ast.h | 1 +
+ src/code-stubs.h | 2 +-
+ src/compiler.cc | 15 +++++++-
+ src/compiler.h | 16 +++++++--
+ src/contexts.cc | 35 +++++++++++++++++++
+ src/contexts.h | 4 ++
+ src/execution.cc | 31 ++++++++++++++---
+ src/execution.h | 8 ++++
+ src/full-codegen.cc | 3 +-
+ src/full-codegen.h | 1 +
+ src/heap.cc | 4 ++
+ src/hydrogen-instructions.h | 8 ++++-
+ src/hydrogen.cc | 2 +
+ src/ia32/code-stubs-ia32.cc | 5 +++
+ src/ia32/full-codegen-ia32.cc | 28 +++++++++-------
+ src/ia32/lithium-codegen-ia32.cc | 7 ++--
+ src/ia32/lithium-ia32.cc | 2 +-
+ src/ia32/lithium-ia32.h | 6 +++-
+ src/ia32/macro-assembler-ia32.h | 3 ++
+ src/objects-inl.h | 2 +
+ src/objects.h | 4 ++
+ src/parser.cc | 27 +++++++++++++--
+ src/parser.h | 4 ++-
+ src/prettyprinter.cc | 3 ++
+ src/runtime.cc | 68 +++++++++++++++++++++++++-------------
+ src/runtime.h | 8 ++--
+ src/scopes.cc | 61 ++++++++++++++++++++++++++++++++++
+ src/scopes.h | 8 ++++
+ src/variables.cc | 3 +-
+ src/variables.h | 5 +++
+ src/x64/code-stubs-x64.cc | 4 ++
+ src/x64/full-codegen-x64.cc | 28 +++++++++-------
+ src/x64/lithium-codegen-x64.cc | 7 ++--
+ src/x64/lithium-x64.cc | 2 +-
+ src/x64/lithium-x64.h | 6 +++
+ src/x64/macro-assembler-x64.h | 5 +++
+ 45 files changed, 445 insertions(+), 109 deletions(-)
+
+diff --git a/include/v8.h b/include/v8.h
+index 3ef4dd6..193e2fe 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -587,6 +587,11 @@ class ScriptOrigin {
+ */
+ class V8EXPORT Script {
+ public:
++ enum CompileFlags {
++ Default = 0x00,
++ QmlMode = 0x01
++ };
++
+ /**
+ * Compiles the specified script (context-independent).
+ *
+@@ -605,7 +610,8 @@ class V8EXPORT Script {
+ static Local<Script> New(Handle<String> source,
+ ScriptOrigin* origin = NULL,
+ ScriptData* pre_data = NULL,
+- Handle<String> script_data = Handle<String>());
++ Handle<String> script_data = Handle<String>(),
++ CompileFlags = Default);
+
+ /**
+ * Compiles the specified script using the specified file name
+@@ -618,7 +624,8 @@ class V8EXPORT Script {
+ * will use the currently entered context).
+ */
+ static Local<Script> New(Handle<String> source,
+- Handle<Value> file_name);
++ Handle<Value> file_name,
++ CompileFlags = Default);
+
+ /**
+ * Compiles the specified script (bound to current context).
+@@ -639,7 +646,8 @@ class V8EXPORT Script {
+ static Local<Script> Compile(Handle<String> source,
+ ScriptOrigin* origin = NULL,
+ ScriptData* pre_data = NULL,
+- Handle<String> script_data = Handle<String>());
++ Handle<String> script_data = Handle<String>(),
++ CompileFlags = Default);
+
+ /**
+ * Compiles the specified script using the specified file name
+@@ -656,7 +664,8 @@ class V8EXPORT Script {
+ */
+ static Local<Script> Compile(Handle<String> source,
+ Handle<Value> file_name,
+- Handle<String> script_data = Handle<String>());
++ Handle<String> script_data = Handle<String>(),
++ CompileFlags = Default);
+
+ /**
+ * Runs the script returning the resulting value. If the script is
+@@ -666,6 +675,7 @@ class V8EXPORT Script {
+ * compiled.
+ */
+ Local<Value> Run();
++ Local<Value> Run(Handle<Object> qml);
+
+ /**
+ * Returns the script id value.
+@@ -3506,6 +3516,7 @@ class V8EXPORT Context {
+ * JavaScript frames an empty handle is returned.
+ */
+ static Local<Context> GetCalling();
++ static Local<Object> GetCallingQmlGlobal();
+
+ /**
+ * Sets the security token for the context. To access an object in
+diff --git a/src/api.cc b/src/api.cc
+index 85f0d4b..fd718c8 100644
+--- a/src/api.cc
++++ b/src/api.cc
+@@ -1514,7 +1514,8 @@ ScriptData* ScriptData::New(const char* data, int length) {
+ Local<Script> Script::New(v8::Handle<String> source,
+ v8::ScriptOrigin* origin,
+ v8::ScriptData* pre_data,
+- v8::Handle<String> script_data) {
++ v8::Handle<String> script_data,
++ v8::Script::CompileFlags compile_flags) {
+ i::Isolate* isolate = i::Isolate::Current();
+ ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>());
+ LOG_API(isolate, "Script::New");
+@@ -1551,7 +1552,8 @@ Local<Script> Script::New(v8::Handle<String> source,
+ NULL,
+ pre_data_impl,
+ Utils::OpenHandle(*script_data),
+- i::NOT_NATIVES_CODE);
++ i::NOT_NATIVES_CODE,
++ compile_flags);
+ has_pending_exception = result.is_null();
+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
+ return Local<Script>(ToApi<Script>(result));
+@@ -1559,21 +1561,23 @@ Local<Script> Script::New(v8::Handle<String> source,
+
+
+ Local<Script> Script::New(v8::Handle<String> source,
+- v8::Handle<Value> file_name) {
++ v8::Handle<Value> file_name,
++ v8::Script::CompileFlags compile_flags) {
+ ScriptOrigin origin(file_name);
+- return New(source, &origin);
++ return New(source, &origin, 0, Handle<String>(), compile_flags);
+ }
+
+
+ Local<Script> Script::Compile(v8::Handle<String> source,
+ v8::ScriptOrigin* origin,
+ v8::ScriptData* pre_data,
+- v8::Handle<String> script_data) {
++ v8::Handle<String> script_data,
++ v8::Script::CompileFlags compile_flags) {
+ i::Isolate* isolate = i::Isolate::Current();
+ ON_BAILOUT(isolate, "v8::Script::Compile()", return Local<Script>());
+ LOG_API(isolate, "Script::Compile");
+ ENTER_V8(isolate);
+- Local<Script> generic = New(source, origin, pre_data, script_data);
++ Local<Script> generic = New(source, origin, pre_data, script_data, compile_flags);
+ if (generic.IsEmpty())
+ return generic;
+ i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
+@@ -1589,13 +1593,18 @@ Local<Script> Script::Compile(v8::Handle<String> source,
+
+ Local<Script> Script::Compile(v8::Handle<String> source,
+ v8::Handle<Value> file_name,
+- v8::Handle<String> script_data) {
++ v8::Handle<String> script_data,
++ v8::Script::CompileFlags compile_flags) {
+ ScriptOrigin origin(file_name);
+- return Compile(source, &origin, 0, script_data);
++ return Compile(source, &origin, 0, script_data, compile_flags);
+ }
+
+
+ Local<Value> Script::Run() {
++ return Run(Handle<Object>());
++}
++
++Local<Value> Script::Run(Handle<Object> qml) {
+ i::Isolate* isolate = i::Isolate::Current();
+ ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>());
+ LOG_API(isolate, "Script::Run");
+@@ -1614,10 +1623,11 @@ Local<Value> Script::Run() {
+ fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate);
+ }
+ EXCEPTION_PREAMBLE(isolate);
++ i::Handle<i::Object> qmlglobal = Utils::OpenHandle(*qml);
+ i::Handle<i::Object> receiver(
+ isolate->context()->global_proxy(), isolate);
+ i::Handle<i::Object> result =
+- i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
++ i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception, false, qmlglobal);
+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
+ raw_result = *result;
+ }
+@@ -4328,6 +4338,30 @@ v8::Local<v8::Context> Context::GetCalling() {
+ }
+
+
++v8::Local<v8::Object> Context::GetCallingQmlGlobal() {
++ i::Isolate* isolate = i::Isolate::Current();
++ if (IsDeadCheck(isolate, "v8::Context::GetCallingQmlGlobal()")) {
++ return Local<Object>();
++ }
++
++ i::Context *context = isolate->context();
++ if (!context->qml_global()->IsUndefined()) {
++ i::Handle<i::Object> qmlglobal(context->qml_global());
++ return Utils::ToLocal(i::Handle<i::JSObject>::cast(qmlglobal));
++ }
++
++ i::JavaScriptFrameIterator it;
++ if (it.done()) return Local<Object>();
++ context = i::Context::cast(it.frame()->context());
++ if (!context->qml_global()->IsUndefined()) {
++ i::Handle<i::Object> qmlglobal(context->qml_global());
++ return Utils::ToLocal(i::Handle<i::JSObject>::cast(qmlglobal));
++ } else {
++ return Local<Object>();
++ }
++}
++
++
+ v8::Local<v8::Object> Context::Global() {
+ if (IsDeadCheck(i::Isolate::Current(), "v8::Context::Global()")) {
+ return Local<v8::Object>();
+diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
+index 17dfbd7..00ac676 100644
+--- a/src/arm/code-stubs-arm.cc
++++ b/src/arm/code-stubs-arm.cc
+@@ -172,6 +172,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
+ __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ str(r1, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX)));
+
++ // Copy the qml global object from the surrounding context.
++ __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
++ __ str(r1, MemOperand(r0, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
++
+ // Initialize the rest of the slots to undefined.
+ __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
+ for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
+diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
+index 2ee1594..a1841f2 100644
+--- a/src/arm/full-codegen-arm.cc
++++ b/src/arm/full-codegen-arm.cc
+@@ -182,12 +182,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
+
+ // Possibly allocate a local context.
+ int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment cmnt(masm_, "[ Allocate local context");
+ // Argument to NewContext is the function, which is in r1.
+ __ push(r1);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewFunctionContext, 1);
+@@ -1168,9 +1169,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
+ __ bind(&fast);
+ }
+
+- __ ldr(r0, GlobalObjectOperand());
++ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ __ mov(r2, Operand(var->name()));
+- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || var->is_qml_global())
+ ? RelocInfo::CODE_TARGET
+ : RelocInfo::CODE_TARGET_CONTEXT;
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+@@ -1246,10 +1247,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
+ Comment cmnt(masm_, "Global variable");
+ // Use inline caching. Variable name is passed in r2 and the global
+ // object (receiver) in r0.
+- __ ldr(r0, GlobalObjectOperand());
++ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ __ mov(r2, Operand(var->name()));
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+- __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
++ __ Call(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
+ context()->Plug(r0);
+ break;
+ }
+@@ -1840,7 +1841,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
+ if (var->IsUnallocated()) {
+ // Global var, const, or let.
+ __ mov(r2, Operand(var->name()));
+- __ ldr(r1, GlobalObjectOperand());
++ __ ldr(r1, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ Handle<Code> ic = is_strict_mode()
+ ? isolate()->builtins()->StoreIC_Initialize_Strict()
+ : isolate()->builtins()->StoreIC_Initialize();
+@@ -2141,10 +2142,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+ }
+ __ mov(r1, Operand(Smi::FromInt(strict_mode)));
+ __ push(r1);
++ // Push the qml mode flag.
++ __ mov(r1, Operand(Smi::FromInt(is_qml_mode())));
++ __ push(r1);
+
+ __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
+ ? Runtime::kResolvePossiblyDirectEvalNoLookup
+- : Runtime::kResolvePossiblyDirectEval, 4);
++ : Runtime::kResolvePossiblyDirectEval, 5);
+ }
+
+
+@@ -2217,9 +2221,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
+ context()->DropAndPlug(1, r0);
+ } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
+ // Push global object as receiver for the call IC.
+- __ ldr(r0, GlobalObjectOperand());
++ __ ldr(r0, proxy->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ __ push(r0);
+- EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
++ EmitCallWithIC(expr, proxy->name(), proxy->var()->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
+ } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
+ // Call to a lookup slot (dynamically introduced variable).
+ Label slow, done;
+@@ -3630,7 +3634,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
+ // but "delete this" is allowed.
+ ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
+ if (var->IsUnallocated()) {
+- __ ldr(r2, GlobalObjectOperand());
++ __ ldr(r2, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+ __ mov(r1, Operand(var->name()));
+ __ mov(r0, Operand(Smi::FromInt(kNonStrictMode)));
+ __ Push(r2, r1, r0);
+@@ -3916,7 +3920,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
+ VariableProxy* proxy = expr->AsVariableProxy();
+ if (proxy != NULL && proxy->var()->IsUnallocated()) {
+ Comment cmnt(masm_, "Global variable");
+- __ ldr(r0, GlobalObjectOperand());
++ __ ldr(r0, proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+ __ mov(r2, Operand(proxy->name()));
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+ // Use a regular load, not a contextual load, to avoid a reference
+diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
+index 8495939..00582ea 100644
+--- a/src/arm/lithium-arm.cc
++++ b/src/arm/lithium-arm.cc
+@@ -1122,7 +1122,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
+
+ LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
+ LOperand* context = UseRegisterAtStart(instr->value());
+- return DefineAsRegister(new LGlobalObject(context));
++ return DefineAsRegister(new LGlobalObject(context, instr->qml_global()));
+ }
+
+
+diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
+index 73c7e45..49cdccc 100644
+--- a/src/arm/lithium-arm.h
++++ b/src/arm/lithium-arm.h
+@@ -1301,13 +1301,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> {
+
+ class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+- explicit LGlobalObject(LOperand* context) {
++ explicit LGlobalObject(LOperand* context, bool qml_global) {
+ inputs_[0] = context;
++ qml_global_ = qml_global;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
+
+ LOperand* context() { return InputAt(0); }
++ bool qml_global() { return qml_global_; }
++ private:
++ bool qml_global_;
+ };
+
+
+diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
+index f6750a2..63c8463 100644
+--- a/src/arm/lithium-codegen-arm.cc
++++ b/src/arm/lithium-codegen-arm.cc
+@@ -190,12 +190,13 @@ bool LCodeGen::GeneratePrologue() {
+
+ // Possibly allocate a local context.
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment(";;; Allocate local context");
+ // Argument to NewContext is the function, which is in r1.
+ __ push(r1);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewFunctionContext, 1);
+@@ -2798,7 +2799,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
+
+ void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+ Register result = ToRegister(instr->result());
+- __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX));
++ __ ldr(result, ContextOperand(cp, instr->qml_global()?Context::QML_GLOBAL_INDEX:Context::GLOBAL_INDEX));
+ }
+
+
+diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
+index d42ccec..9adeb36 100644
+--- a/src/arm/macro-assembler-arm.h
++++ b/src/arm/macro-assembler-arm.h
+@@ -1260,6 +1260,11 @@ static inline MemOperand GlobalObjectOperand() {
+ }
+
+
++static inline MemOperand QmlGlobalObjectOperand() {
++ return ContextOperand(cp, Context::QML_GLOBAL_INDEX);
++}
++
++
+ #ifdef GENERATED_CODE_COVERAGE
+ #define CODE_COVERAGE_STRINGIFY(x) #x
+ #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
+diff --git a/src/ast-inl.h b/src/ast-inl.h
+index 731ad2f..15702cf 100644
+--- a/src/ast-inl.h
++++ b/src/ast-inl.h
+@@ -116,6 +116,11 @@ bool FunctionLiteral::strict_mode() const {
+ }
+
+
++bool FunctionLiteral::qml_mode() const {
++ return scope()->is_qml_mode();
++}
++
++
+ } } // namespace v8::internal
+
+ #endif // V8_AST_INL_H_
+diff --git a/src/ast.h b/src/ast.h
+index 00cfd7f..319d090 100644
+--- a/src/ast.h
++++ b/src/ast.h
+@@ -1658,6 +1658,7 @@ class FunctionLiteral: public Expression {
+ bool is_expression() const { return is_expression_; }
+ bool is_anonymous() const { return is_anonymous_; }
+ bool strict_mode() const;
++ bool qml_mode() const;
+
+ int materialized_literal_count() { return materialized_literal_count_; }
+ int expected_property_count() { return expected_property_count_; }
+diff --git a/src/code-stubs.h b/src/code-stubs.h
+index 9d4baf4..b7cac89 100644
+--- a/src/code-stubs.h
++++ b/src/code-stubs.h
+@@ -323,7 +323,7 @@ class FastNewContextStub : public CodeStub {
+ static const int kMaximumSlots = 64;
+
+ explicit FastNewContextStub(int slots) : slots_(slots) {
+- ASSERT(slots_ > 0 && slots <= kMaximumSlots);
++ ASSERT(slots_ >= 0 && slots <= kMaximumSlots);
+ }
+
+ void Generate(MacroAssembler* masm);
+diff --git a/src/compiler.cc b/src/compiler.cc
+index 5a86b4e..596df4a 100644
+--- a/src/compiler.cc
++++ b/src/compiler.cc
+@@ -450,7 +450,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
+ v8::Extension* extension,
+ ScriptDataImpl* input_pre_data,
+ Handle<Object> script_data,
+- NativesFlag natives) {
++ NativesFlag natives,
++ v8::Script::CompileFlags compile_flags) {
+ Isolate* isolate = source->GetIsolate();
+ int source_length = source->length();
+ isolate->counters()->total_load_size()->Increment(source_length);
+@@ -517,6 +518,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
+ info.MarkAsGlobal();
+ info.SetExtension(extension);
+ info.SetPreParseData(pre_data);
++ if (compile_flags & v8::Script::QmlMode) info.MarkAsQmlMode();
+ if (natives == NATIVES_CODE) {
+ info.MarkAsAllowingNativesSyntax();
+ }
+@@ -539,7 +541,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
+ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
+ Handle<Context> context,
+ bool is_global,
+- StrictModeFlag strict_mode) {
++ StrictModeFlag strict_mode,
++ bool qml_mode) {
+ Isolate* isolate = source->GetIsolate();
+ int source_length = source->length();
+ isolate->counters()->total_eval_size()->Increment(source_length);
+@@ -563,6 +566,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
+ CompilationInfo info(script);
+ info.MarkAsEval();
+ if (is_global) info.MarkAsGlobal();
++ if (qml_mode) info.MarkAsQmlMode();
+ if (strict_mode == kStrictMode) info.MarkAsStrictMode();
+ info.SetCallingContext(context);
+ result = MakeFunctionInfo(&info);
+@@ -607,6 +611,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
+ info->MarkAsStrictMode();
+ }
+
++ // After parsing we know function's qml mode. Remember it.
++ if (info->function()->qml_mode()) {
++ shared->set_qml_mode(true);
++ info->MarkAsQmlMode();
++ }
++
+ // Compile the code.
+ if (!MakeCode(info)) {
+ if (!isolate->has_pending_exception()) {
+@@ -752,6 +762,7 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
+ *lit->this_property_assignments());
+ function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
+ function_info->set_strict_mode(lit->strict_mode());
++ function_info->set_qml_mode(lit->qml_mode());
+ function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
+ function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
+ }
+diff --git a/src/compiler.h b/src/compiler.h
+index 09aa23d..8eacb71 100644
+--- a/src/compiler.h
++++ b/src/compiler.h
+@@ -54,6 +54,7 @@ class CompilationInfo BASE_EMBEDDED {
+ bool is_global() const { return IsGlobal::decode(flags_); }
+ bool is_strict_mode() const { return IsStrictMode::decode(flags_); }
+ bool is_in_loop() const { return IsInLoop::decode(flags_); }
++ bool is_qml_mode() const { return IsQmlMode::decode(flags_); }
+ FunctionLiteral* function() const { return function_; }
+ Scope* scope() const { return scope_; }
+ Handle<Code> code() const { return code_; }
+@@ -83,6 +84,9 @@ class CompilationInfo BASE_EMBEDDED {
+ ASSERT(is_lazy());
+ flags_ |= IsInLoop::encode(true);
+ }
++ void MarkAsQmlMode() {
++ flags_ |= IsQmlMode::encode(true);
++ }
+ void MarkAsAllowingNativesSyntax() {
+ flags_ |= IsNativesSyntaxAllowed::encode(true);
+ }
+@@ -180,6 +184,9 @@ class CompilationInfo BASE_EMBEDDED {
+ if (!shared_info_.is_null() && shared_info_->strict_mode()) {
+ MarkAsStrictMode();
+ }
++ if (!shared_info_.is_null() && shared_info_->qml_mode()) {
++ MarkAsQmlMode();
++ }
+ }
+
+ void SetMode(Mode mode) {
+@@ -203,7 +210,8 @@ class CompilationInfo BASE_EMBEDDED {
+ class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {};
+ // Is this a function from our natives.
+ class IsNative: public BitField<bool, 6, 1> {};
+-
++ // Qml mode
++ class IsQmlMode: public BitField<bool, 7, 1> {};
+
+ unsigned flags_;
+
+@@ -269,13 +277,15 @@ class Compiler : public AllStatic {
+ v8::Extension* extension,
+ ScriptDataImpl* pre_data,
+ Handle<Object> script_data,
+- NativesFlag is_natives_code);
++ NativesFlag is_natives_code,
++ v8::Script::CompileFlags = v8::Script::Default);
+
+ // Compile a String source within a context for Eval.
+ static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
+ Handle<Context> context,
+ bool is_global,
+- StrictModeFlag strict_mode);
++ StrictModeFlag strict_mode,
++ bool qml_mode);
+
+ // Compile from function info (used for lazy compilation). Returns true on
+ // success and false if the compilation resulted in a stack overflow.
+diff --git a/src/contexts.cc b/src/contexts.cc
+index 007d30d..825493a 100644
+--- a/src/contexts.cc
++++ b/src/contexts.cc
+@@ -103,6 +103,9 @@ Handle<Object> Context::Lookup(Handle<String> name,
+ PrintF(")\n");
+ }
+
++ Handle<JSObject> qml_global;
++ Handle<JSObject> qml_global_global;
++
+ do {
+ if (FLAG_trace_contexts) {
+ PrintF(" - looking in context %p", reinterpret_cast<void*>(*context));
+@@ -110,6 +113,11 @@ Handle<Object> Context::Lookup(Handle<String> name,
+ PrintF("\n");
+ }
+
++ if (qml_global.is_null() && !context->qml_global()->IsUndefined()) {
++ qml_global = Handle<JSObject>(context->qml_global(), isolate);
++ qml_global_global = Handle<JSObject>(context->global(), isolate);
++ }
++
+ // 1. Check global objects, subjects of with, and extension objects.
+ if (context->IsGlobalContext() ||
+ context->IsWithContext() ||
+@@ -221,6 +229,33 @@ Handle<Object> Context::Lookup(Handle<String> name,
+ }
+ } while (follow_context_chain);
+
++ if (!qml_global.is_null()) {
++ if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0) {
++ *attributes = qml_global_global->GetLocalPropertyAttribute(*name);
++ } else {
++ *attributes = qml_global_global->GetPropertyAttribute(*name);
++ }
++
++ if (*attributes != ABSENT) {
++ *attributes = ABSENT;
++ } else {
++ if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0) {
++ *attributes = qml_global->GetLocalPropertyAttribute(*name);
++ } else {
++ *attributes = qml_global->GetPropertyAttribute(*name);
++ }
++
++ if (*attributes != ABSENT) {
++ // property found
++ if (FLAG_trace_contexts) {
++ PrintF("=> found property in qml global object %p\n",
++ reinterpret_cast<void*>(*qml_global));
++ }
++ return qml_global;
++ }
++ }
++ }
++
+ if (FLAG_trace_contexts) {
+ PrintF("=> no property/slot found\n");
+ }
+diff --git a/src/contexts.h b/src/contexts.h
+index b80475f..28ba69e 100644
+--- a/src/contexts.h
++++ b/src/contexts.h
+@@ -196,6 +196,7 @@ class Context: public FixedArray {
+ // contexts), eval extension object (function contexts), subject of with
+ // (with contexts), or the variable name (catch contexts).
+ EXTENSION_INDEX,
++ QML_GLOBAL_INDEX,
+ GLOBAL_INDEX,
+ MIN_CONTEXT_SLOTS,
+
+@@ -297,6 +298,9 @@ class Context: public FixedArray {
+ }
+ void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); }
+
++ JSObject *qml_global() { return reinterpret_cast<JSObject *>(get(QML_GLOBAL_INDEX)); }
++ void set_qml_global(JSObject *qml_global) { set(QML_GLOBAL_INDEX, qml_global); }
++
+ // Returns a JSGlobalProxy object or null.
+ JSObject* global_proxy();
+ void set_global_proxy(JSObject* global);
+diff --git a/src/execution.cc b/src/execution.cc
+index 2021c0f..c64c9ea 100644
+--- a/src/execution.cc
++++ b/src/execution.cc
+@@ -71,7 +71,8 @@ static Handle<Object> Invoke(bool construct,
+ Handle<Object> receiver,
+ int argc,
+ Object*** args,
+- bool* has_pending_exception) {
++ bool* has_pending_exception,
++ Handle<Object> qml) {
+ Isolate* isolate = func->GetIsolate();
+
+ // Entering JavaScript.
+@@ -106,6 +107,12 @@ static Handle<Object> Invoke(bool construct,
+ // make the current one is indeed a global object.
+ ASSERT(func->context()->global()->IsGlobalObject());
+
++ Handle<JSObject> oldqml;
++ if (!qml.is_null()) {
++ oldqml = Handle<JSObject>(func->context()->qml_global());
++ func->context()->set_qml_global(JSObject::cast(*qml));
++ }
++
+ {
+ // Save and restore context around invocation and block the
+ // allocation of handles without explicit handle scopes.
+@@ -121,6 +128,9 @@ static Handle<Object> Invoke(bool construct,
+ receiver_pointer, argc, args);
+ }
+
++ if (!qml.is_null())
++ func->context()->set_qml_global(*oldqml);
++
+ #ifdef DEBUG
+ value->Verify();
+ #endif
+@@ -149,7 +159,18 @@ Handle<Object> Execution::Call(Handle<Object> callable,
+ int argc,
+ Object*** args,
+ bool* pending_exception,
+- bool convert_receiver) {
++ bool convert_receiver)
++{
++ return Call(callable, receiver, argc, args, pending_exception, convert_receiver, Handle<Object>());
++}
++
++Handle<Object> Execution::Call(Handle<Object> callable,
++ Handle<Object> receiver,
++ int argc,
++ Object*** args,
++ bool* pending_exception,
++ bool convert_receiver,
++ Handle<Object> qml) {
+ *pending_exception = false;
+
+ if (!callable->IsJSFunction()) {
+@@ -173,14 +194,14 @@ Handle<Object> Execution::Call(Handle<Object> callable,
+ if (*pending_exception) return callable;
+ }
+
+- return Invoke(false, func, receiver, argc, args, pending_exception);
++ return Invoke(false, func, receiver, argc, args, pending_exception, qml);
+ }
+
+
+ Handle<Object> Execution::New(Handle<JSFunction> func, int argc,
+ Object*** args, bool* pending_exception) {
+ return Invoke(true, func, Isolate::Current()->global(), argc, args,
+- pending_exception);
++ pending_exception, Handle<Object>());
+ }
+
+
+@@ -199,7 +220,7 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func,
+ *caught_exception = false;
+
+ Handle<Object> result = Invoke(false, func, receiver, argc, args,
+- caught_exception);
++ caught_exception, Handle<Object>());
+
+ if (*caught_exception) {
+ ASSERT(catcher.HasCaught());
+diff --git a/src/execution.h b/src/execution.h
+index 9fa6e78..baa58b5 100644
+--- a/src/execution.h
++++ b/src/execution.h
+@@ -65,6 +65,14 @@ class Execution : public AllStatic {
+ bool* pending_exception,
+ bool convert_receiver = false);
+
++ static Handle<Object> Call(Handle<Object> callable,
++ Handle<Object> receiver,
++ int argc,
++ Object*** args,
++ bool* pending_exception,
++ bool convert_receiver,
++ Handle<Object> qml);
++
+ // Construct object from function, the caller supplies an array of
+ // arguments. Arguments are Object* type. After function returns,
+ // pointers in 'args' might be invalid.
+diff --git a/src/full-codegen.cc b/src/full-codegen.cc
+index e822588..516d237 100644
+--- a/src/full-codegen.cc
++++ b/src/full-codegen.cc
+@@ -512,7 +512,7 @@ void FullCodeGenerator::VisitDeclarations(
+ // Batch declare global functions and variables.
+ if (global_count > 0) {
+ Handle<FixedArray> array =
+- isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
++ isolate()->factory()->NewFixedArray(3 * global_count, TENURED);
+ for (int j = 0, i = 0; i < length; i++) {
+ Declaration* decl = declarations->at(i);
+ Variable* var = decl->proxy()->var();
+@@ -536,6 +536,7 @@ void FullCodeGenerator::VisitDeclarations(
+ }
+ array->set(j++, *function);
+ }
++ array->set(j++, Smi::FromInt(var->is_qml_global()));
+ }
+ }
+ // Invoke the platform-dependent code generator to do the actual
+diff --git a/src/full-codegen.h b/src/full-codegen.h
+index 6958dae..48753c5 100644
+--- a/src/full-codegen.h
++++ b/src/full-codegen.h
+@@ -581,6 +581,7 @@ class FullCodeGenerator: public AstVisitor {
+ StrictModeFlag strict_mode_flag() {
+ return is_strict_mode() ? kStrictMode : kNonStrictMode;
+ }
++ bool is_qml_mode() { return function()->qml_mode(); }
+ FunctionLiteral* function() { return info_->function(); }
+ Scope* scope() { return scope_; }
+
+diff --git a/src/heap.cc b/src/heap.cc
+index c730455..447dce1 100644
+--- a/src/heap.cc
++++ b/src/heap.cc
+@@ -4407,6 +4407,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
+ context->set_previous(function->context());
+ context->set_extension(NULL);
+ context->set_global(function->context()->global());
++ context->set_qml_global(function->context()->qml_global());
+ return context;
+ }
+
+@@ -4427,6 +4428,7 @@ MaybeObject* Heap::AllocateCatchContext(JSFunction* function,
+ context->set_previous(previous);
+ context->set_extension(name);
+ context->set_global(previous->global());
++ context->set_qml_global(previous->qml_global());
+ context->set(Context::THROWN_OBJECT_INDEX, thrown_object);
+ return context;
+ }
+@@ -4445,6 +4447,7 @@ MaybeObject* Heap::AllocateWithContext(JSFunction* function,
+ context->set_previous(previous);
+ context->set_extension(extension);
+ context->set_global(previous->global());
++ context->set_qml_global(previous->qml_global());
+ return context;
+ }
+
+@@ -4463,6 +4466,7 @@ MaybeObject* Heap::AllocateBlockContext(JSFunction* function,
+ context->set_previous(previous);
+ context->set_extension(scope_info);
+ context->set_global(previous->global());
++ context->set_qml_global(previous->qml_global());
+ return context;
+ }
+
+diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
+index 6b43f53..d0e6fb0 100644
+--- a/src/hydrogen-instructions.h
++++ b/src/hydrogen-instructions.h
+@@ -1394,7 +1394,7 @@ class HOuterContext: public HUnaryOperation {
+
+ class HGlobalObject: public HUnaryOperation {
+ public:
+- explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
++ explicit HGlobalObject(HValue* context) : HUnaryOperation(context), qml_global_(false) {
+ set_representation(Representation::Tagged());
+ SetFlag(kUseGVN);
+ }
+@@ -1405,8 +1405,14 @@ class HGlobalObject: public HUnaryOperation {
+ return Representation::Tagged();
+ }
+
++ bool qml_global() { return qml_global_; }
++ void set_qml_global(bool v) { qml_global_ = v; }
++
+ protected:
+ virtual bool DataEquals(HValue* other) { return true; }
++
++ private:
++ bool qml_global_;
+ };
+
+
+diff --git a/src/hydrogen.cc b/src/hydrogen.cc
+index 64a6ae5..f0c1763 100644
+--- a/src/hydrogen.cc
++++ b/src/hydrogen.cc
+@@ -3174,6 +3174,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
+ } else {
+ HValue* context = environment()->LookupContext();
+ HGlobalObject* global_object = new(zone()) HGlobalObject(context);
++ if (variable->is_qml_global()) global_object->set_qml_global(true);
+ AddInstruction(global_object);
+ HLoadGlobalGeneric* instr =
+ new(zone()) HLoadGlobalGeneric(context,
+@@ -3640,6 +3641,7 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
+ } else {
+ HValue* context = environment()->LookupContext();
+ HGlobalObject* global_object = new(zone()) HGlobalObject(context);
++ if (var->is_qml_global()) global_object->set_qml_global(true);
+ AddInstruction(global_object);
+ HStoreGlobalGeneric* instr =
+ new(zone()) HStoreGlobalGeneric(context,
+diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
+index 1ca577c..6cc80d3 100644
+--- a/src/ia32/code-stubs-ia32.cc
++++ b/src/ia32/code-stubs-ia32.cc
+@@ -143,6 +143,11 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
+ __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx);
+
++ // Copy the qml global object from the previous context.
++ __ mov(ebx, Operand(esi, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
++ __ mov(Operand(eax, Context::SlotOffset(Context::QML_GLOBAL_INDEX)), ebx);
++
++
+ // Initialize the rest of the slots to undefined.
+ __ mov(ebx, factory->undefined_value());
+ for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
+diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
+index d45a9cd..a5883a2 100644
+--- a/src/ia32/full-codegen-ia32.cc
++++ b/src/ia32/full-codegen-ia32.cc
+@@ -178,12 +178,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
+
+ // Possibly allocate a local context.
+ int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment cmnt(masm_, "[ Allocate local context");
+ // Argument to NewContext is the function, which is still in edi.
+ __ push(edi);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewFunctionContext, 1);
+@@ -1152,10 +1153,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
+
+ // All extension objects were empty and it is safe to use a global
+ // load IC call.
+- __ mov(eax, GlobalObjectOperand());
++ __ mov(eax, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ __ mov(ecx, var->name());
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || var->is_qml_global())
+ ? RelocInfo::CODE_TARGET
+ : RelocInfo::CODE_TARGET_CONTEXT;
+ __ call(ic, mode);
+@@ -1229,10 +1230,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
+ Comment cmnt(masm_, "Global variable");
+ // Use inline caching. Variable name is passed in ecx and the global
+ // object in eax.
+- __ mov(eax, GlobalObjectOperand());
++ __ mov(eax, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ __ mov(ecx, var->name());
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+- __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
++ __ call(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
+ context()->Plug(eax);
+ break;
+ }
+@@ -1833,7 +1834,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
+ if (var->IsUnallocated()) {
+ // Global var, const, or let.
+ __ mov(ecx, var->name());
+- __ mov(edx, GlobalObjectOperand());
++ __ mov(edx, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ Handle<Code> ic = is_strict_mode()
+ ? isolate()->builtins()->StoreIC_Initialize_Strict()
+ : isolate()->builtins()->StoreIC_Initialize();
+@@ -2147,9 +2148,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+ }
+ __ push(Immediate(Smi::FromInt(strict_mode)));
+
++ // Push the qml mode flag
++ __ push(Immediate(Smi::FromInt(is_qml_mode())));
++
+ __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
+ ? Runtime::kResolvePossiblyDirectEvalNoLookup
+- : Runtime::kResolvePossiblyDirectEval, 4);
++ : Runtime::kResolvePossiblyDirectEval, 5);
+ }
+
+
+@@ -2220,9 +2224,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
+
+ } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
+ // Push global object as receiver for the call IC.
+- __ push(GlobalObjectOperand());
++ __ push(proxy->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ increment_stack_height();
+- EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
++ EmitCallWithIC(expr, proxy->name(), proxy->var()->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
+
+ } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
+ // Call to a lookup slot (dynamically introduced variable).
+@@ -3688,7 +3692,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
+ // but "delete this" is allowed.
+ ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
+ if (var->IsUnallocated()) {
+- __ push(GlobalObjectOperand());
++ __ push(var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+ __ push(Immediate(var->name()));
+ __ push(Immediate(Smi::FromInt(kNonStrictMode)));
+ __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
+@@ -3996,7 +4000,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
+
+ if (proxy != NULL && proxy->var()->IsUnallocated()) {
+ Comment cmnt(masm_, "Global variable");
+- __ mov(eax, GlobalObjectOperand());
++ __ mov(eax, proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+ __ mov(ecx, Immediate(proxy->name()));
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+ // Use a regular load, not a contextual load, to avoid a reference
+diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
+index 9e1fd34..1abcdd3 100644
+--- a/src/ia32/lithium-codegen-ia32.cc
++++ b/src/ia32/lithium-codegen-ia32.cc
+@@ -211,12 +211,13 @@ bool LCodeGen::GeneratePrologue() {
+
+ // Possibly allocate a local context.
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment(";;; Allocate local context");
+ // Argument to NewContext is the function, which is still in edi.
+ __ push(edi);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewFunctionContext, 1);
+@@ -2635,7 +2636,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
+ void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+ Register context = ToRegister(instr->context());
+ Register result = ToRegister(instr->result());
+- __ mov(result, Operand(context, Context::SlotOffset(Context::GLOBAL_INDEX)));
++ __ mov(result, Operand(context, Context::SlotOffset(instr->qml_global()?Context::QML_GLOBAL_INDEX:Context::GLOBAL_INDEX)));
+ }
+
+
+diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
+index 856106c..0b058e6 100644
+--- a/src/ia32/lithium-ia32.cc
++++ b/src/ia32/lithium-ia32.cc
+@@ -1138,7 +1138,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
+
+ LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
+ LOperand* context = UseRegisterAtStart(instr->value());
+- return DefineAsRegister(new LGlobalObject(context));
++ return DefineAsRegister(new LGlobalObject(context, instr->qml_global()));
+ }
+
+
+diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
+index 3a06ac3..087d5cb 100644
+--- a/src/ia32/lithium-ia32.h
++++ b/src/ia32/lithium-ia32.h
+@@ -1336,13 +1336,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> {
+
+ class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+- explicit LGlobalObject(LOperand* context) {
++ explicit LGlobalObject(LOperand* context, bool qml_global) {
+ inputs_[0] = context;
++ qml_global_ = qml_global;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
+
+ LOperand* context() { return InputAt(0); }
++ bool qml_global() { return qml_global_; }
++ private:
++ bool qml_global_;
+ };
+
+
+diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
+index a1b42c2..7a64b9a 100644
+--- a/src/ia32/macro-assembler-ia32.h
++++ b/src/ia32/macro-assembler-ia32.h
+@@ -931,6 +931,9 @@ static inline Operand GlobalObjectOperand() {
+ return ContextOperand(esi, Context::GLOBAL_INDEX);
+ }
+
++static inline Operand QmlGlobalObjectOperand() {
++ return ContextOperand(esi, Context::QML_GLOBAL_INDEX);
++}
+
+ // Generates an Operand for saving parameters after PrepareCallApiFunction.
+ Operand ApiParameterOperand(int index);
+diff --git a/src/objects-inl.h b/src/objects-inl.h
+index 36af868..375df0f 100644
+--- a/src/objects-inl.h
++++ b/src/objects-inl.h
+@@ -3615,6 +3615,8 @@ void SharedFunctionInfo::set_optimization_disabled(bool disable) {
+
+ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, strict_mode,
+ kStrictModeFunction)
++BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, qml_mode,
++ kQmlModeFunction)
+ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
+ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
+ name_should_print_as_anonymous,
+diff --git a/src/objects.h b/src/objects.h
+index dea5bbd..71895be 100644
+--- a/src/objects.h
++++ b/src/objects.h
+@@ -4725,6 +4725,9 @@ class SharedFunctionInfo: public HeapObject {
+ // Indicates whether the function is a strict mode function.
+ DECL_BOOLEAN_ACCESSORS(strict_mode)
+
++ // Indicates whether the function is a qml mode function.
++ DECL_BOOLEAN_ACCESSORS(qml_mode)
++
+ // False if the function definitely does not allocate an arguments object.
+ DECL_BOOLEAN_ACCESSORS(uses_arguments)
+
+@@ -4939,6 +4942,7 @@ class SharedFunctionInfo: public HeapObject {
+ kCodeAgeShift,
+ kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize,
+ kStrictModeFunction,
++ kQmlModeFunction,
+ kUsesArguments,
+ kHasDuplicateParameters,
+ kNative,
+diff --git a/src/parser.cc b/src/parser.cc
+index ad8850e..a9af8eb 100644
+--- a/src/parser.cc
++++ b/src/parser.cc
+@@ -594,7 +594,8 @@ Parser::Parser(Handle<Script> script,
+
+ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
+ bool in_global_context,
+- StrictModeFlag strict_mode) {
++ StrictModeFlag strict_mode,
++ bool qml_mode) {
+ ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
+
+ HistogramTimerScope timer(isolate()->counters()->parse());
+@@ -610,11 +611,11 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
+ ExternalTwoByteStringUC16CharacterStream stream(
+ Handle<ExternalTwoByteString>::cast(source), 0, source->length());
+ scanner_.Initialize(&stream);
+- return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
++ return DoParseProgram(source, in_global_context, strict_mode, qml_mode, &zone_scope);
+ } else {
+ GenericStringUC16CharacterStream stream(source, 0, source->length());
+ scanner_.Initialize(&stream);
+- return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
++ return DoParseProgram(source, in_global_context, strict_mode, qml_mode, &zone_scope);
+ }
+ }
+
+@@ -622,6 +623,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
+ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
+ bool in_global_context,
+ StrictModeFlag strict_mode,
++ bool qml_mode,
+ ZoneScope* zone_scope) {
+ ASSERT(target_stack_ == NULL);
+ if (pre_data_ != NULL) pre_data_->Initialize();
+@@ -642,6 +644,9 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
+ if (strict_mode == kStrictMode) {
+ top_scope_->EnableStrictMode();
+ }
++ if (qml_mode) {
++ scope->EnableQmlMode();
++ }
+ ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
+ bool ok = true;
+ int beg_loc = scanner().location().beg_pos;
+@@ -736,6 +741,9 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
+ if (shared_info->strict_mode()) {
+ top_scope_->EnableStrictMode();
+ }
++ if (shared_info->qml_mode()) {
++ top_scope_->EnableQmlMode();
++ }
+
+ FunctionLiteral::Type type = shared_info->is_expression()
+ ? (shared_info->is_anonymous()
+@@ -1806,6 +1814,11 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
+ arguments->Add(value);
+ value = NULL; // zap the value to avoid the unnecessary assignment
+
++ int qml_mode = 0;
++ if (top_scope_->is_qml_mode() && !Isolate::Current()->global()->HasProperty(*name))
++ qml_mode = 1;
++ arguments->Add(NewNumberLiteral(qml_mode));
++
+ // Construct the call to Runtime_InitializeConstGlobal
+ // and add it to the initialization statement block.
+ // Note that the function does different things depending on
+@@ -1824,6 +1837,11 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
+ : kNonStrictMode;
+ arguments->Add(NewNumberLiteral(flag));
+
++ int qml_mode = 0;
++ if (top_scope_->is_qml_mode() && !Isolate::Current()->global()->HasProperty(*name))
++ qml_mode = 1;
++ arguments->Add(NewNumberLiteral(qml_mode));
++
+ // Be careful not to assign a value to the global variable if
+ // we're in a with. The initialization value should not
+ // necessarily be stored in the global object in that case,
+@@ -5217,7 +5235,8 @@ bool ParserApi::Parse(CompilationInfo* info) {
+ Handle<String> source = Handle<String>(String::cast(script->source()));
+ result = parser.ParseProgram(source,
+ info->is_global(),
+- info->StrictMode());
++ info->StrictMode(),
++ info->is_qml_mode());
+ }
+ }
+ info->SetFunction(result);
+diff --git a/src/parser.h b/src/parser.h
+index d834ed1..d88d1ef 100644
+--- a/src/parser.h
++++ b/src/parser.h
+@@ -426,7 +426,8 @@ class Parser {
+ // Returns NULL if parsing failed.
+ FunctionLiteral* ParseProgram(Handle<String> source,
+ bool in_global_context,
+- StrictModeFlag strict_mode);
++ StrictModeFlag strict_mode,
++ bool qml_mode);
+
+ FunctionLiteral* ParseLazy(CompilationInfo* info);
+
+@@ -466,6 +467,7 @@ class Parser {
+ FunctionLiteral* DoParseProgram(Handle<String> source,
+ bool in_global_context,
+ StrictModeFlag strict_mode,
++ bool qml_mode,
+ ZoneScope* zone_scope);
+
+ // Report syntax error
+diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc
+index 37c76ce..73812fd 100644
+--- a/src/prettyprinter.cc
++++ b/src/prettyprinter.cc
+@@ -618,6 +618,9 @@ void AstPrinter::PrintLiteralWithModeIndented(const char* info,
+ EmbeddedVector<char, 256> buf;
+ int pos = OS::SNPrintF(buf, "%s (mode = %s", info,
+ Variable::Mode2String(var->mode()));
++ if (var->is_qml_global()) {
++ pos += OS::SNPrintF(buf + pos, ":QML");
++ }
+ OS::SNPrintF(buf + pos, ")");
+ PrintLiteralIndented(buf.start(), value, true);
+ }
+diff --git a/src/runtime.cc b/src/runtime.cc
+index 5a850e9..0388a77 100644
+--- a/src/runtime.cc
++++ b/src/runtime.cc
+@@ -1213,19 +1213,23 @@ static Failure* ThrowRedeclarationError(Isolate* isolate,
+ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
+ ASSERT(args.length() == 3);
+ HandleScope scope(isolate);
+- Handle<GlobalObject> global = Handle<GlobalObject>(
+- isolate->context()->global());
+
+ Handle<Context> context = args.at<Context>(0);
+ CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
+ CONVERT_SMI_ARG_CHECKED(flags, 2);
+
++ Handle<JSObject> js_global = Handle<JSObject>(isolate->context()->global());
++ Handle<JSObject> qml_global = Handle<JSObject>(isolate->context()->qml_global());
++
+ // Traverse the name/value pairs and set the properties.
+ int length = pairs->length();
+- for (int i = 0; i < length; i += 2) {
++ for (int i = 0; i < length; i += 3) {
+ HandleScope scope(isolate);
+ Handle<String> name(String::cast(pairs->get(i)));
+ Handle<Object> value(pairs->get(i + 1), isolate);
++ Handle<Smi> is_qml_global(Smi::cast(pairs->get(i + 2)));
++
++ Handle<JSObject> global = is_qml_global->value()?qml_global:js_global;
+
+ // We have to declare a global const property. To capture we only
+ // assign to it when evaluating the assignment for "const x =
+@@ -1414,19 +1418,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
+ NoHandleAllocation nha;
+ // args[0] == name
+ // args[1] == strict_mode
+- // args[2] == value (optional)
++ // args[2] == qml_mode
++ // args[3] == value (optional)
+
+ // Determine if we need to assign to the variable if it already
+ // exists (based on the number of arguments).
+- RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
+- bool assign = args.length() == 3;
++ RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
++ bool assign = args.length() == 4;
+
+ CONVERT_ARG_CHECKED(String, name, 0);
+- GlobalObject* global = isolate->context()->global();
+ RUNTIME_ASSERT(args[1]->IsSmi());
+ StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(1));
+ ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
+
++ RUNTIME_ASSERT(args[2]->IsSmi());
++ int qml_mode = Smi::cast(args[2])->value();
++
++ JSObject* global = qml_mode?isolate->context()->qml_global():isolate->context()->global();
++
+ // According to ECMA-262, section 12.2, page 62, the property must
+ // not be deletable.
+ PropertyAttributes attributes = DONT_DELETE;
+@@ -1454,7 +1463,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
+ // Found an interceptor that's not read only.
+ if (assign) {
+ return raw_holder->SetProperty(
+- &lookup, *name, args[2], attributes, strict_mode);
++ &lookup, *name, args[3], attributes, strict_mode);
+ } else {
+ return isolate->heap()->undefined_value();
+ }
+@@ -1464,9 +1473,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
+ }
+
+ // Reload global in case the loop above performed a GC.
+- global = isolate->context()->global();
++ global = qml_mode?isolate->context()->qml_global():isolate->context()->global();
+ if (assign) {
+- return global->SetProperty(*name, args[2], attributes, strict_mode, true);
++ return global->SetProperty(*name, args[3], attributes, strict_mode, true);
+ }
+ return isolate->heap()->undefined_value();
+ }
+@@ -1476,12 +1485,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
+ // All constants are declared with an initial value. The name
+ // of the constant is the first argument and the initial value
+ // is the second.
+- RUNTIME_ASSERT(args.length() == 2);
++ RUNTIME_ASSERT(args.length() == 3);
+ CONVERT_ARG_CHECKED(String, name, 0);
+ Handle<Object> value = args.at<Object>(1);
+
++ RUNTIME_ASSERT(args[2]->IsSmi());
++ int qml_mode = Smi::cast(args[2])->value();
++
+ // Get the current global object from top.
+- GlobalObject* global = isolate->context()->global();
++ JSObject* global = qml_mode?isolate->context()->qml_global():isolate->context()->global();
+
+ // According to ECMA-262, section 12.2, page 62, the property must
+ // not be deletable. Since it's a const, it must be READ_ONLY too.
+@@ -1505,7 +1517,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
+ // Restore global object from context (in case of GC) and continue
+ // with setting the value.
+ HandleScope handle_scope(isolate);
+- Handle<GlobalObject> global(isolate->context()->global());
++ Handle<JSObject> global(qml_mode?isolate->context()->qml_global():isolate->context()->global());
+
+ // BUG 1213575: Handle the case where we have to set a read-only
+ // property through an interceptor and only do it if it's
+@@ -9204,7 +9216,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
+ Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
+ context,
+ true,
+- kNonStrictMode);
++ kNonStrictMode,
++ false);
+ if (shared.is_null()) return Failure::Exception();
+ Handle<JSFunction> fun =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
+@@ -9217,7 +9230,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
+ static ObjectPair CompileGlobalEval(Isolate* isolate,
+ Handle<String> source,
+ Handle<Object> receiver,
+- StrictModeFlag strict_mode) {
++ StrictModeFlag strict_mode,
++ bool qml_mode) {
+ Handle<Context> context = Handle<Context>(isolate->context());
+ Handle<Context> global_context = Handle<Context>(context->global_context());
+
+@@ -9235,7 +9249,8 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
+ source,
+ Handle<Context>(isolate->context()),
+ context->IsGlobalContext(),
+- strict_mode);
++ strict_mode,
++ qml_mode);
+ if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
+ Handle<JSFunction> compiled =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(
+@@ -9245,7 +9260,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
+
+
+ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
+- ASSERT(args.length() == 4);
++ ASSERT(args.length() == 5);
+
+ HandleScope scope(isolate);
+ Handle<Object> callee = args.at<Object>(0);
+@@ -9308,15 +9323,17 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
+ }
+
+ ASSERT(args[3]->IsSmi());
++ ASSERT(args[4]->IsSmi());
+ return CompileGlobalEval(isolate,
+ args.at<String>(1),
+ args.at<Object>(2),
+- static_cast<StrictModeFlag>(args.smi_at(3)));
++ static_cast<StrictModeFlag>(args.smi_at(3)),
++ Smi::cast(args[4])->value());
+ }
+
+
+ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) {
+- ASSERT(args.length() == 4);
++ ASSERT(args.length() == 5);
+
+ HandleScope scope(isolate);
+ Handle<Object> callee = args.at<Object>(0);
+@@ -9329,10 +9346,12 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) {
+ }
+
+ ASSERT(args[3]->IsSmi());
++ ASSERT(args[4]->IsSmi());
+ return CompileGlobalEval(isolate,
+ args.at<String>(1),
+ args.at<Object>(2),
+- static_cast<StrictModeFlag>(args.smi_at(3)));
++ static_cast<StrictModeFlag>(args.smi_at(3)),
++ Smi::cast(args[4])->value());
+ }
+
+
+@@ -11771,6 +11790,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
+ Handle<JSFunction> function(JSFunction::cast(frame->function()));
+ Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
+ ScopeInfo<> sinfo(*scope_info);
++ bool qml_mode = function->shared()->qml_mode();
+
+ // Traverse the saved contexts chain to find the active context for the
+ // selected frame.
+@@ -11840,7 +11860,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
+ Compiler::CompileEval(function_source,
+ context,
+ context->IsGlobalContext(),
+- kNonStrictMode);
++ kNonStrictMode,
++ qml_mode);
+ if (shared.is_null()) return Failure::Exception();
+ Handle<JSFunction> compiled_function =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
+@@ -11850,7 +11871,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
+ Handle<Object> receiver(frame->receiver(), isolate);
+ Handle<Object> evaluation_function =
+ Execution::Call(compiled_function, receiver, 0, NULL,
+- &has_pending_exception);
++ &has_pending_exception, false,
++ Handle<Object>(function->context()->qml_global()));
+ if (has_pending_exception) return Failure::Exception();
+
+ Handle<Object> arguments = GetArgumentsObject(isolate,
+@@ -11930,7 +11952,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
+ // Currently, the eval code will be executed in non-strict mode,
+ // even in the strict code context.
+ Handle<SharedFunctionInfo> shared =
+- Compiler::CompileEval(source, context, is_global, kNonStrictMode);
++ Compiler::CompileEval(source, context, is_global, kNonStrictMode, false);
+ if (shared.is_null()) return Failure::Exception();
+ Handle<JSFunction> compiled_function =
+ Handle<JSFunction>(
+diff --git a/src/runtime.h b/src/runtime.h
+index c6f7773..284f723 100644
+--- a/src/runtime.h
++++ b/src/runtime.h
+@@ -257,8 +257,8 @@ namespace internal {
+ \
+ /* Eval */ \
+ F(GlobalReceiver, 1, 1) \
+- F(ResolvePossiblyDirectEval, 4, 2) \
+- F(ResolvePossiblyDirectEvalNoLookup, 4, 2) \
++ F(ResolvePossiblyDirectEval, 5, 2) \
++ F(ResolvePossiblyDirectEvalNoLookup, 5, 2) \
+ \
+ F(SetProperty, -1 /* 4 or 5 */, 1) \
+ F(DefineOrRedefineDataProperty, 4, 1) \
+@@ -325,8 +325,8 @@ namespace internal {
+ /* Declarations and initialization */ \
+ F(DeclareGlobals, 3, 1) \
+ F(DeclareContextSlot, 4, 1) \
+- F(InitializeVarGlobal, -1 /* 2 or 3 */, 1) \
+- F(InitializeConstGlobal, 2, 1) \
++ F(InitializeVarGlobal, -1 /* 3 or 4 */, 1) \
++ F(InitializeConstGlobal, 3, 1) \
+ F(InitializeConstContextSlot, 3, 1) \
+ F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
+ \
+diff --git a/src/scopes.cc b/src/scopes.cc
+index d5a7a9f..25921fa 100644
+--- a/src/scopes.cc
++++ b/src/scopes.cc
+@@ -35,6 +35,8 @@
+
+ #include "allocation-inl.h"
+
++#include "debug.h"
++
+ namespace v8 {
+ namespace internal {
+
+@@ -202,6 +204,7 @@ void Scope::SetDefaults(Type type,
+ scope_calls_eval_ = false;
+ // Inherit the strict mode from the parent scope.
+ strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_;
++ qml_mode_ = (outer_scope != NULL) && outer_scope->qml_mode_;
+ outer_scope_calls_eval_ = false;
+ outer_scope_calls_non_strict_eval_ = false;
+ inner_scope_calls_eval_ = false;
+@@ -923,6 +926,25 @@ void Scope::ResolveVariable(Scope* global_scope,
+ ASSERT(global_scope != NULL);
+ var = global_scope->DeclareGlobal(proxy->name());
+
++ if (qml_mode_) {
++ Handle<GlobalObject> global = Isolate::Current()->global();
++
++#ifdef ENABLE_DEBUGGER_SUPPORT
++ if (Isolate::Current()->debug()->IsLoaded() && Isolate::Current()->debug()->InDebugger()) {
++ //Get the context before the debugger was entered.
++ SaveContext *save = Isolate::Current()->save_context();
++ while (save != NULL && *save->context() == *Isolate::Current()->debug()->debug_context())
++ save = save->prev();
++
++ global = Handle<GlobalObject>(save->context()->global());
++ }
++#endif
++
++ if (!global->HasProperty(*(proxy->name()))) {
++ var->set_is_qml_global(true);
++ }
++ }
++
+ } else if (scope_inside_with_) {
+ // If we are inside a with statement we give up and look up
+ // the variable at runtime.
+@@ -944,6 +966,25 @@ void Scope::ResolveVariable(Scope* global_scope,
+ if (context->GlobalIfNotShadowedByEval(proxy->name())) {
+ var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
+
++ if (qml_mode_) {
++ Handle<GlobalObject> global = Isolate::Current()->global();
++
++#ifdef ENABLE_DEBUGGER_SUPPORT
++ if (Isolate::Current()->debug()->IsLoaded() && Isolate::Current()->debug()->InDebugger()) {
++ //Get the context before the debugger was entered.
++ SaveContext *save = Isolate::Current()->save_context();
++ while (save != NULL && *save->context() == *Isolate::Current()->debug()->debug_context())
++ save = save->prev();
++
++ global = Handle<GlobalObject>(save->context()->global());
++ }
++#endif
++
++ if (qml_mode_ && !global->HasProperty(*(proxy->name()))) {
++ var->set_is_qml_global(true);
++ }
++ }
++
+ } else {
+ var = NonLocal(proxy->name(), Variable::DYNAMIC);
+ }
+@@ -954,6 +995,26 @@ void Scope::ResolveVariable(Scope* global_scope,
+ // variable is global unless it is shadowed by eval-introduced
+ // variables.
+ var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
++
++ if (qml_mode_) {
++ Handle<GlobalObject> global = Isolate::Current()->global();
++
++#ifdef ENABLE_DEBUGGER_SUPPORT
++ if (Isolate::Current()->debug()->IsLoaded() && Isolate::Current()->debug()->InDebugger()) {
++ //Get the context before the debugger was entered.
++ SaveContext *save = Isolate::Current()->save_context();
++ while (save != NULL && *save->context() == *Isolate::Current()->debug()->debug_context())
++ save = save->prev();
++
++ global = Handle<GlobalObject>(save->context()->global());
++ }
++#endif
++
++ if (qml_mode_ && !global->HasProperty(*(proxy->name()))) {
++ var->set_is_qml_global(true);
++ }
++ }
++
+ }
+ }
+ }
+diff --git a/src/scopes.h b/src/scopes.h
+index 2917a63..0f1ed6d 100644
+--- a/src/scopes.h
++++ b/src/scopes.h
+@@ -206,6 +206,11 @@ class Scope: public ZoneObject {
+ strict_mode_ = FLAG_strict_mode;
+ }
+
++ // Enable qml mode for this scope
++ void EnableQmlMode() {
++ qml_mode_ = true;
++ }
++
+ // ---------------------------------------------------------------------------
+ // Predicates.
+
+@@ -216,6 +221,7 @@ class Scope: public ZoneObject {
+ bool is_catch_scope() const { return type_ == CATCH_SCOPE; }
+ bool is_block_scope() const { return type_ == BLOCK_SCOPE; }
+ bool is_strict_mode() const { return strict_mode_; }
++ bool is_qml_mode() const { return qml_mode_; }
+ bool is_strict_mode_eval_scope() const {
+ return is_eval_scope() && is_strict_mode();
+ }
+@@ -381,6 +387,8 @@ class Scope: public ZoneObject {
+ bool scope_calls_eval_;
+ // This scope is a strict mode scope.
+ bool strict_mode_;
++ // This scope is a qml mode scope.
++ bool qml_mode_;
+
+ // Computed via PropagateScopeInfo.
+ bool outer_scope_calls_eval_;
+diff --git a/src/variables.cc b/src/variables.cc
+index 971061b..da07620 100644
+--- a/src/variables.cc
++++ b/src/variables.cc
+@@ -67,7 +67,8 @@ Variable::Variable(Scope* scope,
+ local_if_not_shadowed_(NULL),
+ is_valid_LHS_(is_valid_LHS),
+ is_accessed_from_inner_scope_(false),
+- is_used_(false) {
++ is_used_(false),
++ is_qml_global_(false) {
+ // names must be canonicalized for fast equality checks
+ ASSERT(name->IsSymbol());
+ }
+diff --git a/src/variables.h b/src/variables.h
+index 56c8dab..4d27f98 100644
+--- a/src/variables.h
++++ b/src/variables.h
+@@ -174,6 +174,8 @@ class Variable: public ZoneObject {
+ index_ = index;
+ }
+
++ bool is_qml_global() const { return is_qml_global_; }
++ void set_is_qml_global(bool is_qml_global) { is_qml_global_ = is_qml_global; }
+ private:
+ Scope* scope_;
+ Handle<String> name_;
+@@ -190,6 +192,9 @@ class Variable: public ZoneObject {
+ // Usage info.
+ bool is_accessed_from_inner_scope_; // set by variable resolver
+ bool is_used_;
++
++ // QML info
++ bool is_qml_global_;
+ };
+
+
+diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
+index 8d9dba7..6ab12fc 100644
+--- a/src/x64/code-stubs-x64.cc
++++ b/src/x64/code-stubs-x64.cc
+@@ -139,6 +139,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
+ __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx);
+
++ // Copy the qmlglobal object from the previous context.
++ __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
++ __ movq(Operand(rax, Context::SlotOffset(Context::QML_GLOBAL_INDEX)), rbx);
++
+ // Initialize the rest of the slots to undefined.
+ __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
+ for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
+diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
+index 1d9b8ff..08b3872 100644
+--- a/src/x64/full-codegen-x64.cc
++++ b/src/x64/full-codegen-x64.cc
+@@ -173,12 +173,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
+
+ // Possibly allocate a local context.
+ int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment cmnt(masm_, "[ Allocate local context");
+ // Argument to NewContext is the function, which is still in rdi.
+ __ push(rdi);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewFunctionContext, 1);
+@@ -1129,10 +1130,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
+
+ // All extension objects were empty and it is safe to use a global
+ // load IC call.
+- __ movq(rax, GlobalObjectOperand());
++ __ movq(rax, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+ __ Move(rcx, var->name());
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || var->is_qml_global())
+ ? RelocInfo::CODE_TARGET
+ : RelocInfo::CODE_TARGET_CONTEXT;
+ __ call(ic, mode);
+@@ -1207,9 +1208,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
+ // Use inline caching. Variable name is passed in rcx and the global
+ // object on the stack.
+ __ Move(rcx, var->name());
+- __ movq(rax, GlobalObjectOperand());
++ __ movq(rax, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+- __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
++ __ call(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT);
+ context()->Plug(rax);
+ break;
+ }
+@@ -1750,7 +1751,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
+ if (var->IsUnallocated()) {
+ // Global var, const, or let.
+ __ Move(rcx, var->name());
+- __ movq(rdx, GlobalObjectOperand());
++ __ movq(rdx, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+ Handle<Code> ic = is_strict_mode()
+ ? isolate()->builtins()->StoreIC_Initialize_Strict()
+ : isolate()->builtins()->StoreIC_Initialize();
+@@ -2034,9 +2035,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+ }
+ __ Push(Smi::FromInt(strict_mode));
+
++ // Push the qml mode flag
++ __ Push(Smi::FromInt(is_qml_mode()));
++
+ __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
+ ? Runtime::kResolvePossiblyDirectEvalNoLookup
+- : Runtime::kResolvePossiblyDirectEval, 4);
++ : Runtime::kResolvePossiblyDirectEval, 5);
+ }
+
+
+@@ -2105,8 +2109,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
+ } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
+ // Call to a global variable. Push global object as receiver for the
+ // call IC lookup.
+- __ push(GlobalObjectOperand());
+- EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
++ __ push(proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
++ EmitCallWithIC(expr, proxy->name(), proxy->var()->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT);
+ } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
+ // Call to a lookup slot (dynamically introduced variable).
+ Label slow, done;
+@@ -3552,7 +3556,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
+ // but "delete this" is allowed.
+ ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
+ if (var->IsUnallocated()) {
+- __ push(GlobalObjectOperand());
++ __ push(var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+ __ Push(var->name());
+ __ Push(Smi::FromInt(kNonStrictMode));
+ __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
+@@ -3850,7 +3854,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
+ if (proxy != NULL && proxy->var()->IsUnallocated()) {
+ Comment cmnt(masm_, "Global variable");
+ __ Move(rcx, proxy->name());
+- __ movq(rax, GlobalObjectOperand());
++ __ movq(rax, proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+ // Use a regular load, not a contextual load, to avoid a reference
+ // error.
+diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
+index 45aaad7..08050f0 100644
+--- a/src/x64/lithium-codegen-x64.cc
++++ b/src/x64/lithium-codegen-x64.cc
+@@ -196,12 +196,13 @@ bool LCodeGen::GeneratePrologue() {
+
+ // Possibly allocate a local context.
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment(";;; Allocate local context");
+ // Argument to NewContext is the function, which is still in rdi.
+ __ push(rdi);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewFunctionContext, 1);
+@@ -2581,7 +2582,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
+
+ void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+ Register result = ToRegister(instr->result());
+- __ movq(result, GlobalObjectOperand());
++ __ movq(result, instr->qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ }
+
+
+diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
+index a67a593..a243fef 100644
+--- a/src/x64/lithium-x64.cc
++++ b/src/x64/lithium-x64.cc
+@@ -1117,7 +1117,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
+
+
+ LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
+- return DefineAsRegister(new LGlobalObject);
++ return DefineAsRegister(new LGlobalObject(instr->qml_global()));
+ }
+
+
+diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
+index d43a86a..cf89181 100644
+--- a/src/x64/lithium-x64.h
++++ b/src/x64/lithium-x64.h
+@@ -1301,7 +1301,13 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> {
+
+ class LGlobalObject: public LTemplateInstruction<1, 0, 0> {
+ public:
++ explicit LGlobalObject(bool qml_global) : qml_global_(qml_global) {}
++
+ DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
++
++ bool qml_global() { return qml_global_; }
++ private:
++ bool qml_global_;
+ };
+
+
+diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
+index 7e0ba00..744ce20 100644
+--- a/src/x64/macro-assembler-x64.h
++++ b/src/x64/macro-assembler-x64.h
+@@ -1413,6 +1413,11 @@ static inline Operand GlobalObjectOperand() {
+ }
+
+
++static inline Operand QmlGlobalObjectOperand() {
++ return ContextOperand(rsi, Context::QML_GLOBAL_INDEX);
++}
++
++
+ // Provides access to exit frame stack space (not GCed).
+ static inline Operand StackSpaceOperand(int index) {
+ #ifdef _WIN64
+--
+1.7.4.4
+