summaryrefslogtreecommitdiffstats
path: root/src/v8/0005-Introduce-a-QML-compilation-mode.patch
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2011-08-16 10:50:00 +0200
committerQt by Nokia <qt-info@nokia.com>2011-08-29 10:16:01 +0200
commit9830cb8e5992a352ec6508491ab52e8f2a9da877 (patch)
tree9baa3969878a1e070c56c9a3a67143c2d96ee5d6 /src/v8/0005-Introduce-a-QML-compilation-mode.patch
parent13b3545e833f6175f686c9776e1510db3f3f11eb (diff)
Add QtV8 library to QtBase
This adds Aaron's copy of V8 to src/3rdparty/v8 (as a git submodule), and builds it as a "normal" Qt library (without any dependencies on Qt itself). The library can be added to a project with QT += v8-private V8 API headers are available as private includes, e.g. #include <private/v8.h> The API is private because we're exposing a third-party API directly, and we don't want to (and cannot) make source or binary compatibility guarantees for it. Since we want the V8 public API headers to be private headers in Qt, syncqt and sync.profile were extended to understand a new configuration option, the @allmoduleheadersprivate array, that tells syncqt whether all the library headers should be treated as private even though they don't follow the _p.h Qt convention. The V8 project files, patches and autotests are copied from the QtDeclarative repository. The next step after this commit is to remove QtDeclarative's copy of V8 and link with QtV8 instead. Task-number: QTBUG-20963 Change-Id: Ib8820362cdbc8fa662a5e97db841656cf38d1b62 Reviewed-on: http://codereview.qt.nokia.com/3092 Reviewed-by: Kent Hansen <kent.hansen@nokia.com> Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'src/v8/0005-Introduce-a-QML-compilation-mode.patch')
-rw-r--r--src/v8/0005-Introduce-a-QML-compilation-mode.patch1777
1 files changed, 1777 insertions, 0 deletions
diff --git a/src/v8/0005-Introduce-a-QML-compilation-mode.patch b/src/v8/0005-Introduce-a-QML-compilation-mode.patch
new file mode 100644
index 0000000000..b464e61266
--- /dev/null
+++ b/src/v8/0005-Introduce-a-QML-compilation-mode.patch
@@ -0,0 +1,1777 @@
+From fd7d475e298e5b63cd6383c78cc900635c82aa38 Mon Sep 17 00:00:00 2001
+From: Aaron Kennedy <aaron.kennedy@nokia.com>
+Date: Mon, 23 May 2011 18:26:19 +1000
+Subject: [PATCH 05/13] 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 | 18 ++++++++--
+ src/api.cc | 52 ++++++++++++++++++++++++-----
+ src/arm/code-stubs-arm.cc | 4 ++
+ src/arm/full-codegen-arm.cc | 26 ++++++++------
+ 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 | 22 ++++++++++--
+ src/contexts.cc | 23 +++++++++++++
+ src/contexts.h | 4 ++
+ src/execution.cc | 28 +++++++++++++--
+ src/execution.h | 6 +++
+ src/full-codegen.cc | 3 +-
+ src/full-codegen.h | 1 +
+ src/heap.cc | 2 +
+ src/hydrogen-instructions.h | 10 ++++-
+ src/hydrogen.cc | 2 +
+ src/ia32/code-stubs-ia32.cc | 7 ++++
+ src/ia32/full-codegen-ia32.cc | 26 ++++++++------
+ 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 | 5 +++
+ src/objects-inl.h | 12 +++++++
+ src/objects.h | 5 +++
+ src/parser.cc | 27 +++++++++++++--
+ src/parser.h | 4 ++-
+ src/prettyprinter.cc | 3 ++
+ src/runtime.cc | 68 ++++++++++++++++++++++++-------------
+ src/runtime.h | 8 ++--
+ src/scopes.cc | 10 +++++
+ src/scopes.h | 7 ++++
+ src/variables.cc | 3 +-
+ src/variables.h | 5 +++
+ src/x64/code-stubs-x64.cc | 4 ++
+ src/x64/full-codegen-x64.cc | 26 ++++++++------
+ 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, 391 insertions(+), 108 deletions(-)
+
+diff --git a/include/v8.h b/include/v8.h
+index 7f06ae7..a858eae 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -577,6 +577,10 @@ class ScriptOrigin {
+ */
+ class V8EXPORT Script {
+ public:
++ enum CompileFlags {
++ Default = 0x00,
++ QmlMode = 0x01
++ };
+
+ /**
+ * Compiles the specified script (context-independent).
+@@ -596,7 +600,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
+@@ -609,7 +614,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).
+@@ -630,7 +636,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
+@@ -647,7 +654,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
+@@ -657,6 +665,7 @@ class V8EXPORT Script {
+ * compiled.
+ */
+ Local<Value> Run();
++ Local<Value> Run(Handle<Object> qml);
+
+ /**
+ * Returns the script id value.
+@@ -3326,6 +3335,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 1a6fbbb..39767f4 100644
+--- a/src/api.cc
++++ b/src/api.cc
+@@ -1372,7 +1372,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");
+@@ -1409,7 +1410,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));
+@@ -1417,21 +1419,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);
+@@ -1447,13 +1451,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");
+@@ -1472,10 +1481,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, qmlglobal);
+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
+ raw_result = *result;
+ }
+@@ -3943,6 +3953,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 8c147f9..a2626bf 100644
+--- a/src/arm/code-stubs-arm.cc
++++ b/src/arm/code-stubs-arm.cc
+@@ -166,6 +166,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 871b453..a69f10d 100644
+--- a/src/arm/full-codegen-arm.cc
++++ b/src/arm/full-codegen-arm.cc
+@@ -154,12 +154,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
+
+ // 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 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::kNewContext, 1);
+@@ -1247,9 +1248,9 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
+ __ bind(&fast);
+ }
+
+- __ ldr(r0, GlobalObjectOperand());
++ __ ldr(r0, slot->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ __ mov(r2, Operand(slot->var()->name()));
+- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global())
+ ? RelocInfo::CODE_TARGET
+ : RelocInfo::CODE_TARGET_CONTEXT;
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+@@ -1268,10 +1269,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
+ 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();
+- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
++ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
+ context()->Plug(r0);
+
+ } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+@@ -1893,11 +1894,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
+ // assignment. Right-hand-side value is passed in r0, variable name in
+ // r2, and the global object in r1.
+ __ 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();
+- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
++ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
+
+ } else if (op == Token::INIT_CONST) {
+ // Like var declarations, const declarations are hoisted to function
+@@ -2184,10 +2185,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+ // Push the strict mode flag.
+ __ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
+ __ 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);
+ }
+
+
+@@ -2263,9 +2267,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
+ context()->DropAndPlug(1, r0);
+ } else if (var != NULL && !var->is_this() && var->is_global()) {
+ // Push global object as receiver for the call IC.
+- __ ldr(r0, GlobalObjectOperand());
++ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ __ push(r0);
+- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
++ EmitCallWithIC(expr, var->name(), var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
+ } else if (var != NULL && var->AsSlot() != NULL &&
+ var->AsSlot()->type() == Slot::LOOKUP) {
+ // Call to a lookup slot (dynamically introduced variable).
+diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
+index 3f1d15b..8406a96 100644
+--- a/src/arm/lithium-arm.cc
++++ b/src/arm/lithium-arm.cc
+@@ -1195,7 +1195,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 6da7c86..10b901f 100644
+--- a/src/arm/lithium-arm.h
++++ b/src/arm/lithium-arm.h
+@@ -1378,13 +1378,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 4912449..db114ea 100644
+--- a/src/arm/lithium-codegen-arm.cc
++++ b/src/arm/lithium-codegen-arm.cc
+@@ -166,12 +166,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::kNewContext, 1);
+@@ -2664,7 +2665,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
+ void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+ Register context = ToRegister(instr->context());
+ 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 ab5efb0..d40cdbc 100644
+--- a/src/arm/macro-assembler-arm.h
++++ b/src/arm/macro-assembler-arm.h
+@@ -1056,6 +1056,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 d80684a..adc5a1f 100644
+--- a/src/ast-inl.h
++++ b/src/ast-inl.h
+@@ -106,6 +106,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 65a25a9..f790dc0 100644
+--- a/src/ast.h
++++ b/src/ast.h
+@@ -1712,6 +1712,7 @@ class FunctionLiteral: public Expression {
+ int end_position() const { return end_position_; }
+ bool is_expression() const { return is_expression_; }
+ 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 56ef072..37e5383 100644
+--- a/src/code-stubs.h
++++ b/src/code-stubs.h
+@@ -303,7 +303,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 86d5de3..d2191b9 100755
+--- a/src/compiler.cc
++++ b/src/compiler.cc
+@@ -462,7 +462,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);
+@@ -523,6 +524,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();
+ result = MakeFunctionInfo(&info);
+ if (extension == NULL && !result.is_null()) {
+@@ -543,7 +545,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);
+@@ -567,6 +570,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);
+@@ -610,6 +614,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()) {
+@@ -755,6 +765,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());
+ }
+
+
+diff --git a/src/compiler.h b/src/compiler.h
+index e75e869..17cd369 100644
+--- a/src/compiler.h
++++ b/src/compiler.h
+@@ -54,6 +54,7 @@ class CompilationInfo BASE_EMBEDDED {
+ bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
+ bool is_strict_mode() const { return (flags_ & IsStrictMode::mask()) != 0; }
+ bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
++ bool is_qml_mode() const { return (flags_ & IsQmlMode::mask()) != 0; }
+ 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);
+ }
+@@ -141,6 +145,7 @@ class CompilationInfo BASE_EMBEDDED {
+
+ // Determine whether or not we can adaptively optimize.
+ bool AllowOptimize() {
++ // XXX - fix qml mode optimizations
+ return V8::UseCrankshaft() && !closure_.is_null();
+ }
+
+@@ -163,8 +168,13 @@ class CompilationInfo BASE_EMBEDDED {
+
+ void Initialize(Mode mode) {
+ mode_ = V8::UseCrankshaft() ? mode : NONOPT;
+- if (!shared_info_.is_null() && shared_info_->strict_mode()) {
+- MarkAsStrictMode();
++ if (!shared_info_.is_null()) {
++ if (shared_info_->strict_mode()) {
++ MarkAsStrictMode();
++ }
++ if (shared_info_->qml_mode()) {
++ MarkAsQmlMode();
++ }
+ }
+ }
+
+@@ -187,6 +197,8 @@ class CompilationInfo BASE_EMBEDDED {
+ class IsStrictMode: public BitField<bool, 4, 1> {};
+ // Native syntax (%-stuff) allowed?
+ class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {};
++ // Qml mode
++ class IsQmlMode: public BitField<bool, 6, 1> {};
+
+ unsigned flags_;
+
+@@ -252,13 +264,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 compile_flags = 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 520f3dd..da5cacb 100644
+--- a/src/contexts.cc
++++ b/src/contexts.cc
+@@ -89,6 +89,8 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
+ PrintF(")\n");
+ }
+
++ Handle<JSObject> qml_global;
++
+ do {
+ if (FLAG_trace_contexts) {
+ PrintF(" - looking in context %p", reinterpret_cast<void*>(*context));
+@@ -119,6 +121,10 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
+ }
+ }
+
++ if (qml_global.is_null() && !context->qml_global()->IsUndefined()) {
++ qml_global = Handle<JSObject>(context->qml_global(), isolate);
++ }
++
+ if (context->is_function_context()) {
+ // we have context-local slots
+
+@@ -198,6 +204,23 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
+ }
+ } while (follow_context_chain);
+
++ if (!qml_global.is_null()) {
++ 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;
++ }
++ }
++
+ // slot not found
+ if (FLAG_trace_contexts) {
+ PrintF("=> no property/slot found\n");
+diff --git a/src/contexts.h b/src/contexts.h
+index e46619e..57d8e7b 100644
+--- a/src/contexts.h
++++ b/src/contexts.h
+@@ -182,6 +182,7 @@ class Context: public FixedArray {
+ FCONTEXT_INDEX,
+ PREVIOUS_INDEX,
+ EXTENSION_INDEX,
++ QML_GLOBAL_INDEX,
+ GLOBAL_INDEX,
+ MIN_CONTEXT_SLOTS,
+
+@@ -273,6 +274,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 eb26438..1632076 100644
+--- a/src/execution.cc
++++ b/src/execution.cc
+@@ -70,7 +70,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.
+@@ -107,6 +108,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.
+@@ -122,6 +129,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
+@@ -150,14 +160,24 @@ Handle<Object> Execution::Call(Handle<JSFunction> func,
+ int argc,
+ Object*** args,
+ bool* pending_exception) {
+- return Invoke(false, func, receiver, argc, args, pending_exception);
++ return Invoke(false, func, receiver, argc, args, pending_exception, Handle<Object>());
++}
++
++
++Handle<Object> Execution::Call(Handle<JSFunction> func,
++ Handle<Object> receiver,
++ int argc,
++ Object*** args,
++ bool* pending_exception,
++ Handle<Object> qml) {
++ 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>());
+ }
+
+
+@@ -175,7 +195,7 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func,
+ catcher.SetCaptureMessage(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 d4b80d2..a476eb4 100644
+--- a/src/execution.h
++++ b/src/execution.h
+@@ -56,6 +56,12 @@ class Execution : public AllStatic {
+ int argc,
+ Object*** args,
+ bool* pending_exception);
++ static Handle<Object> Call(Handle<JSFunction> func,
++ Handle<Object> receiver,
++ int argc,
++ Object*** args,
++ bool* pending_exception,
++ Handle<Object> qml);
+
+ // Construct object from function, the caller supplies an array of
+ // arguments. Arguments are Object* type. After function returns,
+diff --git a/src/full-codegen.cc b/src/full-codegen.cc
+index d6ba56e..2eaef0f 100644
+--- a/src/full-codegen.cc
++++ b/src/full-codegen.cc
+@@ -542,7 +542,7 @@ void FullCodeGenerator::VisitDeclarations(
+ // Do nothing in case of no declared global functions or variables.
+ if (globals > 0) {
+ Handle<FixedArray> array =
+- isolate()->factory()->NewFixedArray(2 * globals, TENURED);
++ isolate()->factory()->NewFixedArray(3 * globals, TENURED);
+ for (int j = 0, i = 0; i < length; i++) {
+ Declaration* decl = declarations->at(i);
+ Variable* var = decl->proxy()->var();
+@@ -567,6 +567,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 d6ed1b9..e3241aa 100644
+--- a/src/full-codegen.h
++++ b/src/full-codegen.h
+@@ -505,6 +505,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 info_->scope(); }
+
+diff --git a/src/heap.cc b/src/heap.cc
+index bf2940e..da958c2 100644
+--- a/src/heap.cc
++++ b/src/heap.cc
+@@ -3795,6 +3795,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
+ context->set_previous(NULL);
+ context->set_extension(NULL);
+ context->set_global(function->context()->global());
++ context->set_qml_global(function->context()->qml_global());
+ ASSERT(!context->IsGlobalContext());
+ ASSERT(context->is_function_context());
+ ASSERT(result->IsContext());
+@@ -3817,6 +3818,7 @@ MaybeObject* Heap::AllocateWithContext(Context* previous,
+ context->set_previous(previous);
+ context->set_extension(extension);
+ context->set_global(previous->global());
++ context->set_qml_global(previous->qml_global());
+ ASSERT(!context->IsGlobalContext());
+ ASSERT(!context->is_function_context());
+ ASSERT(result->IsContext());
+diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
+index a623775..52455bc 100644
+--- a/src/hydrogen-instructions.h
++++ b/src/hydrogen-instructions.h
+@@ -1148,7 +1148,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);
+ }
+@@ -1159,8 +1159,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_;
+ };
+
+
+@@ -1177,7 +1183,7 @@ class HGlobalReceiver: public HUnaryOperation {
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+-
++
+ protected:
+ virtual bool DataEquals(HValue* other) { return true; }
+ };
+diff --git a/src/hydrogen.cc b/src/hydrogen.cc
+index 73ea97d..d17e304 100644
+--- a/src/hydrogen.cc
++++ b/src/hydrogen.cc
+@@ -2918,6 +2918,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
+ HContext* context = new(zone()) HContext;
+ AddInstruction(context);
+ 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,
+@@ -3307,6 +3308,7 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
+ HContext* context = new(zone()) HContext;
+ AddInstruction(context);
+ 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 5d32095..afa599e 100644
+--- a/src/ia32/code-stubs-ia32.cc
++++ b/src/ia32/code-stubs-ia32.cc
+@@ -147,6 +147,13 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
+ __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx);
+
++ // Copy the qml global object from the surrounding context. We go through the
++ // context in the function (ecx) to match the allocation behavior we have
++ // in the runtime system (see Heap::AllocateFunctionContext).
++ __ mov(ebx, FieldOperand(ecx, JSFunction::kContextOffset));
++ __ mov(ebx, Operand(ebx, 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 5d153a8..0ddcde2 100644
+--- a/src/ia32/full-codegen-ia32.cc
++++ b/src/ia32/full-codegen-ia32.cc
+@@ -142,12 +142,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
+
+ // 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 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::kNewContext, 1);
+@@ -1107,10 +1108,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
+
+ // All extension objects were empty and it is safe to use a global
+ // load IC call.
+- __ mov(eax, GlobalObjectOperand());
++ __ mov(eax, slot->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ __ mov(ecx, slot->var()->name());
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global())
+ ? RelocInfo::CODE_TARGET
+ : RelocInfo::CODE_TARGET_CONTEXT;
+ EmitCallIC(ic, mode);
+@@ -1214,10 +1215,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
+ Comment cmnt(masm_, "Global variable");
+ // Use inline caching. Variable name is passed in ecx and the global
+ // object on the stack.
+- __ mov(eax, GlobalObjectOperand());
++ __ mov(eax, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ __ mov(ecx, var->name());
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
++ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
+ context()->Plug(eax);
+
+ } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+@@ -1837,11 +1838,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
+ // assignment. Right-hand-side value is passed in eax, variable name in
+ // ecx, and the global object on the stack.
+ __ 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();
+- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
++ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
+
+ } else if (op == Token::INIT_CONST) {
+ // Like var declarations, const declarations are hoisted to function
+@@ -2113,9 +2114,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+ // Push the strict mode flag.
+ __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+
++ // 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);
+ }
+
+
+@@ -2188,8 +2192,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
+ context()->DropAndPlug(1, eax);
+ } else if (var != NULL && !var->is_this() && var->is_global()) {
+ // Push global object as receiver for the call IC.
+- __ push(GlobalObjectOperand());
+- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
++ __ push(var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
++ EmitCallWithIC(expr, var->name(), var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
+ } else if (var != NULL && var->AsSlot() != NULL &&
+ var->AsSlot()->type() == Slot::LOOKUP) {
+ // Call to a lookup slot (dynamically introduced variable).
+diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
+index 0f96f78..c1da075 100644
+--- a/src/ia32/lithium-codegen-ia32.cc
++++ b/src/ia32/lithium-codegen-ia32.cc
+@@ -159,12 +159,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::kNewContext, 1);
+@@ -2525,7 +2526,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 9ccd189..8e98b73 100644
+--- a/src/ia32/lithium-ia32.cc
++++ b/src/ia32/lithium-ia32.cc
+@@ -1205,7 +1205,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 9ace8f8..95ed001 100644
+--- a/src/ia32/lithium-ia32.h
++++ b/src/ia32/lithium-ia32.h
+@@ -1416,13 +1416,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 b986264..f8479ae 100644
+--- a/src/ia32/macro-assembler-ia32.h
++++ b/src/ia32/macro-assembler-ia32.h
+@@ -778,6 +778,11 @@ static inline Operand GlobalObjectOperand() {
+ }
+
+
++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 231b835..1c7f83e 100644
+--- a/src/objects-inl.h
++++ b/src/objects-inl.h
+@@ -3242,6 +3242,18 @@ void SharedFunctionInfo::set_strict_mode(bool value) {
+ }
+
+
++bool SharedFunctionInfo::qml_mode() {
++ return BooleanBit::get(compiler_hints(), kQmlModeFunction);
++}
++
++
++void SharedFunctionInfo::set_qml_mode(bool value) {
++ set_compiler_hints(BooleanBit::set(compiler_hints(),
++ kQmlModeFunction,
++ value));
++}
++
++
+ ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
+ ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
+
+diff --git a/src/objects.h b/src/objects.h
+index 1bdb5c7..edbc47a 100644
+--- a/src/objects.h
++++ b/src/objects.h
+@@ -4331,6 +4331,10 @@ class SharedFunctionInfo: public HeapObject {
+ inline bool strict_mode();
+ inline void set_strict_mode(bool value);
+
++ // Indicates whether the function is a qml mode function
++ inline bool qml_mode();
++ inline void set_qml_mode(bool value);
++
+ // Indicates whether or not the code in the shared function support
+ // deoptimization.
+ inline bool has_deoptimization_support();
+@@ -4511,6 +4515,7 @@ class SharedFunctionInfo: public HeapObject {
+ static const int kCodeAgeMask = 0x7;
+ static const int kOptimizationDisabled = 6;
+ static const int kStrictModeFunction = 7;
++ static const int kQmlModeFunction = 8;
+
+ private:
+ #if V8_HOST_ARCH_32_BIT
+diff --git a/src/parser.cc b/src/parser.cc
+index a84ec6f..7f5c361 100644
+--- a/src/parser.cc
++++ b/src/parser.cc
+@@ -593,7 +593,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) {
+ CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
+
+ HistogramTimerScope timer(isolate()->counters()->parse());
+@@ -609,11 +610,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);
+ }
+ }
+
+@@ -621,6 +622,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();
+@@ -641,6 +643,9 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
+ if (strict_mode == kStrictMode) {
+ top_scope_->EnableStrictMode();
+ }
++ if (qml_mode) {
++ scope->EnableQmlMode();
++ }
+ ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
+ bool ok = true;
+ int beg_loc = scanner().location().beg_pos;
+@@ -729,6 +734,9 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
+ if (shared_info->strict_mode()) {
+ top_scope_->EnableStrictMode();
+ }
++ if (shared_info->qml_mode()) {
++ top_scope_->EnableQmlMode();
++ }
+
+ FunctionLiteralType type =
+ shared_info->is_expression() ? EXPRESSION : DECLARATION;
+@@ -1661,6 +1669,11 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
+ 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
+@@ -1676,6 +1689,11 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
+ arguments->Add(NewNumberLiteral(
+ top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode));
+
++ 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,
+@@ -5157,7 +5175,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());
+ }
+ }
+
+diff --git a/src/parser.h b/src/parser.h
+index 64f1303..4d45e45 100644
+--- a/src/parser.h
++++ b/src/parser.h
+@@ -431,7 +431,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);
+
+@@ -464,6 +465,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 c777ab4..1964e02 100644
+--- a/src/prettyprinter.cc
++++ b/src/prettyprinter.cc
+@@ -656,6 +656,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 660352c..827d954 100644
+--- a/src/runtime.cc
++++ b/src/runtime.cc
+@@ -1065,8 +1065,6 @@ static Failure* ThrowRedeclarationError(Isolate* isolate,
+ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
+ ASSERT(args.length() == 4);
+ HandleScope scope(isolate);
+- Handle<GlobalObject> global = Handle<GlobalObject>(
+- isolate->context()->global());
+
+ Handle<Context> context = args.at<Context>(0);
+ CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
+@@ -1075,6 +1073,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
+ static_cast<StrictModeFlag>(Smi::cast(args[3])->value());
+ ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
+
++ Handle<JSObject> js_global = Handle<JSObject>(isolate->context()->global());
++ Handle<JSObject> qml_global = Handle<JSObject>(isolate->context()->qml_global());
++
+ // Compute the property attributes. According to ECMA-262, section
+ // 13, page 71, the property must be read-only and
+ // non-deletable. However, neither SpiderMonkey nor KJS creates the
+@@ -1083,10 +1084,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
+
+ // 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 =
+@@ -1316,20 +1320,25 @@ 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>(Smi::cast(args[1])->value());
+ 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;
+@@ -1350,7 +1359,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
+ if (lookup.IsReadOnly()) {
+ // If we found readonly property on one of hidden prototypes,
+ // just shadow it.
+- if (real_holder != isolate->context()->global()) break;
++ if (real_holder != global) break;
+ return ThrowRedeclarationError(isolate, "const", name);
+ }
+
+@@ -1372,7 +1381,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
+ // overwrite it with a variable declaration we must throw a
+ // re-declaration error. However if we found readonly property
+ // on one of hidden prototypes, just shadow it.
+- if (real_holder != isolate->context()->global()) break;
++ if (real_holder != global) break;
+ return ThrowRedeclarationError(isolate, "const", name);
+ }
+ }
+@@ -1384,7 +1393,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
+ }
+
+ // Assign the value (or undefined) to the property.
+- Object* value = (assign) ? args[2] : isolate->heap()->undefined_value();
++ Object* value = (assign) ? args[3] : isolate->heap()->undefined_value();
+ return real_holder->SetProperty(
+ &lookup, *name, value, attributes, strict_mode);
+ }
+@@ -1399,9 +1408,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
+ real_holder = JSObject::cast(proto);
+ }
+
+- 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();
+ }
+@@ -1411,12 +1420,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.
+@@ -1456,7 +1468,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
+ // with setting the value because the property is either absent or
+ // read-only. We also have to do redo the lookup.
+ 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
+@@ -8160,7 +8172,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,
+@@ -8173,14 +8186,16 @@ 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) {
+ // Deal with a normal eval call with a string argument. Compile it
+ // and return the compiled function bound in the local context.
+ Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
+ source,
+ Handle<Context>(isolate->context()),
+ isolate->context()->IsGlobalContext(),
+- strict_mode);
++ strict_mode,
++ qml_mode);
+ if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
+ Handle<JSFunction> compiled =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(
+@@ -8190,7 +8205,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);
+@@ -8257,16 +8272,18 @@ 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>(
+- Smi::cast(args[3])->value()));
++ Smi::cast(args[3])->value()),
++ 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);
+@@ -8280,11 +8297,13 @@ 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>(
+- Smi::cast(args[3])->value()));
++ Smi::cast(args[3])->value()),
++ Smi::cast(args[4])->value());
+ }
+
+
+@@ -10633,7 +10652,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
+ Compiler::CompileEval(function_source,
+ context,
+ context->IsGlobalContext(),
+- kNonStrictMode);
++ kNonStrictMode,
++ false);
+ if (shared.is_null()) return Failure::Exception();
+ Handle<JSFunction> compiled_function =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
+@@ -10722,7 +10742,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 bf1ba68..5e97173 100644
+--- a/src/runtime.h
++++ b/src/runtime.h
+@@ -241,8 +241,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) \
+@@ -296,8 +296,8 @@ namespace internal {
+ /* Declarations and initialization */ \
+ F(DeclareGlobals, 4, 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 8df93c5..734a217 100644
+--- a/src/scopes.cc
++++ b/src/scopes.cc
+@@ -198,6 +198,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;
+ inner_scope_calls_eval_ = false;
+ outer_scope_is_eval_scope_ = false;
+@@ -796,6 +797,10 @@ void Scope::ResolveVariable(Scope* global_scope,
+ ASSERT(global_scope != NULL);
+ var = global_scope->DeclareGlobal(proxy->name());
+
++ if (qml_mode_ && !Isolate::Current()->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.
+@@ -816,6 +821,8 @@ void Scope::ResolveVariable(Scope* global_scope,
+ // variables.
+ if (context->GlobalIfNotShadowedByEval(proxy->name())) {
+ var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
++ if (qml_mode_ && !Isolate::Current()->global()->HasProperty(*(proxy->name())))
++ var->set_is_qml_global(true);
+
+ } else {
+ var = NonLocal(proxy->name(), Variable::DYNAMIC);
+@@ -827,6 +834,9 @@ 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_ && !Isolate::Current()->global()->HasProperty(*(proxy->name())))
++ var->set_is_qml_global(true);
+ }
+ }
+ }
+diff --git a/src/scopes.h b/src/scopes.h
+index a0e56a4..6dd3f65 100644
+--- a/src/scopes.h
++++ b/src/scopes.h
+@@ -210,6 +210,11 @@ class Scope: public ZoneObject {
+ strict_mode_ = FLAG_strict_mode;
+ }
+
++ // Enable qml mode for this scope
++ void EnableQmlMode() {
++ qml_mode_ = true;
++ }
++
+ // ---------------------------------------------------------------------------
+ // Predicates.
+
+@@ -218,6 +223,7 @@ class Scope: public ZoneObject {
+ bool is_function_scope() const { return type_ == FUNCTION_SCOPE; }
+ bool is_global_scope() const { return type_ == GLOBAL_SCOPE; }
+ bool is_strict_mode() const { return strict_mode_; }
++ bool is_qml_mode() const { return qml_mode_; }
+
+ // Information about which scopes calls eval.
+ bool calls_eval() const { return scope_calls_eval_; }
+@@ -376,6 +382,7 @@ class Scope: public ZoneObject {
+ bool scope_contains_with_; // this scope contains a 'with' statement
+ bool scope_calls_eval_; // this scope contains an 'eval' call
+ bool strict_mode_; // this scope is a strict mode scope
++ bool qml_mode_; // this scope is a qml mode scope
+
+ // Computed via PropagateScopeInfo.
+ bool outer_scope_calls_eval_;
+diff --git a/src/variables.cc b/src/variables.cc
+index 0502722..190baf6 100644
+--- a/src/variables.cc
++++ b/src/variables.cc
+@@ -99,7 +99,8 @@ Variable::Variable(Scope* scope,
+ rewrite_(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 b1ff0db..0b31d1a 100644
+--- a/src/variables.h
++++ b/src/variables.h
+@@ -141,6 +141,8 @@ class Variable: public ZoneObject {
+ Expression* rewrite() const { return rewrite_; }
+ void set_rewrite(Expression* expr) { rewrite_ = expr; }
+
++ 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_;
+@@ -159,6 +161,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 c365385..d923494 100644
+--- a/src/x64/code-stubs-x64.cc
++++ b/src/x64/code-stubs-x64.cc
+@@ -140,6 +140,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 qml global object from the surrounding 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 97168cd..c45cdb6 100644
+--- a/src/x64/full-codegen-x64.cc
++++ b/src/x64/full-codegen-x64.cc
+@@ -141,12 +141,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
+
+ // 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 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::kNewContext, 1);
+@@ -1119,10 +1120,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
+
+ // All extension objects were empty and it is safe to use a global
+ // load IC call.
+- __ movq(rax, GlobalObjectOperand());
++ __ movq(rax, slot->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+ __ Move(rcx, slot->var()->name());
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global())
+ ? RelocInfo::CODE_TARGET
+ : RelocInfo::CODE_TARGET_CONTEXT;
+ EmitCallIC(ic, mode);
+@@ -1227,9 +1228,9 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
+ // 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();
+- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
++ EmitCallIC(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT);
+ context()->Plug(rax);
+
+ } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+@@ -1806,11 +1807,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
+ // assignment. Right-hand-side value is passed in rax, variable name in
+ // rcx, and the global object on the stack.
+ __ 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();
+- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
++ EmitCallIC(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT);
+
+ } else if (op == Token::INIT_CONST) {
+ // Like var declarations, const declarations are hoisted to function
+@@ -2085,9 +2086,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+ // Push the strict mode flag.
+ __ Push(Smi::FromInt(strict_mode_flag()));
+
++ // Push the qml mode flag
++ __ Push(Smi::FromInt(is_qml_mode()));
++
+ __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
+ ? Runtime::kResolvePossiblyDirectEvalNoLookup
+- : Runtime::kResolvePossiblyDirectEval, 4);
++ : Runtime::kResolvePossiblyDirectEval, 5);
+ }
+
+
+@@ -2160,8 +2164,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
+ } else if (var != NULL && !var->is_this() && var->is_global()) {
+ // Call to a global variable.
+ // Push global object as receiver for the call IC lookup.
+- __ push(GlobalObjectOperand());
+- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
++ __ push(var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
++ EmitCallWithIC(expr, var->name(), var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT);
+ } else if (var != NULL && var->AsSlot() != NULL &&
+ var->AsSlot()->type() == Slot::LOOKUP) {
+ // Call to a lookup slot (dynamically introduced variable).
+diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
+index 202e7a2..45acbdf 100644
+--- a/src/x64/lithium-codegen-x64.cc
++++ b/src/x64/lithium-codegen-x64.cc
+@@ -174,12 +174,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::kNewContext, 1);
+@@ -2540,7 +2541,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 07ca3a5..00feeac 100644
+--- a/src/x64/lithium-x64.cc
++++ b/src/x64/lithium-x64.cc
+@@ -1194,7 +1194,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 15bb894..16f754c 100644
+--- a/src/x64/lithium-x64.h
++++ b/src/x64/lithium-x64.h
+@@ -1365,7 +1365,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 4c17720..aa284ed 100644
+--- a/src/x64/macro-assembler-x64.h
++++ b/src/x64/macro-assembler-x64.h
+@@ -1233,6 +1233,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.2.3
+