diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2011-10-11 15:06:25 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-10-19 20:48:25 +0200 |
commit | 7dc5973bf12919d2d35230844beabe558d4faa00 (patch) | |
tree | 88d6128a911d2ec3b9a72d8e45d56fc2b250c714 /src/v8/0004-Introduce-a-QML-compilation-mode.patch | |
parent | 4dc25c1f2995a5e02da47f0f6f3522af9eb6f78c (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.patch | 1871 |
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 + |