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-11-10 13:22:13 +0100 |
commit | bcd16f9453e543ba819385d87bd7061a4caeb325 (patch) | |
tree | 4296919fa02e8188be3b28ca7fa4ab548693be33 /src/v8/0004-Introduce-a-QML-compilation-mode.patch | |
parent | 95d7abb694d5d21acf0a15dcbf3feb4514bd2ab4 (diff) |
Update V8
Change-Id: Ic239ef1e55bed06260e4a04cc2199f64c2d30059
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 | 2059 |
1 files changed, 2059 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..8e91114ca4 --- /dev/null +++ b/src/v8/0004-Introduce-a-QML-compilation-mode.patch @@ -0,0 +1,2059 @@ +From 6f97385cf3cb17d245e7f3d61ba975183a786220 Mon Sep 17 00:00:00 2001 +From: Aaron Kennedy <aaron.kennedy@nokia.com> +Date: Thu, 27 Oct 2011 13:34:16 +0100 +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 | 4 +- + src/arm/lithium-arm.h | 12 ++++++- + src/arm/lithium-codegen-arm.cc | 9 +++-- + src/arm/macro-assembler-arm.h | 5 +++ + src/ast-inl.h | 5 +++ + src/ast.cc | 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.cc | 5 +++ + src/hydrogen-instructions.h | 16 ++++++++- + src/hydrogen.cc | 4 ++ + src/ia32/code-stubs-ia32.cc | 5 +++ + src/ia32/full-codegen-ia32.cc | 28 +++++++++------- + src/ia32/lithium-codegen-ia32.cc | 9 +++-- + src/ia32/lithium-ia32.cc | 4 +- + src/ia32/lithium-ia32.h | 12 +++++- + src/ia32/macro-assembler-ia32.h | 3 ++ + src/objects-inl.h | 2 + + src/objects.h | 4 ++ + src/parser.cc | 28 +++++++++++++-- + src/parser.h | 4 ++- + src/prettyprinter.cc | 3 ++ + src/runtime.cc | 68 +++++++++++++++++++++++++------------- + src/runtime.h | 8 ++-- + src/scopes.cc | 63 +++++++++++++++++++++++++++++++++++ + 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 | 9 +++-- + src/x64/lithium-x64.cc | 4 +- + src/x64/lithium-x64.h | 12 +++++++ + src/x64/macro-assembler-x64.h | 5 +++ + 47 files changed, 490 insertions(+), 117 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 7d54252..2d3d97a 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; + } +@@ -4337,6 +4347,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 cb3bc88..f5be938 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 497a295..b8e3f30 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); +@@ -1193,9 +1194,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(); +@@ -1280,10 +1281,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; + } +@@ -1920,7 +1921,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(); +@@ -2220,10 +2221,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + FLAG_harmony_scoping ? kStrictMode : strict_mode_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); + } + + +@@ -2296,9 +2300,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; +@@ -3711,7 +3715,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); +@@ -3997,7 +4001,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 5197842..943bc82 100644 +--- a/src/arm/lithium-arm.cc ++++ b/src/arm/lithium-arm.cc +@@ -1128,7 +1128,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())); + } + + +@@ -1198,7 +1198,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { + + LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { + argument_count_ -= instr->argument_count(); +- return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr); ++ return MarkAsCall(DefineFixed(new LCallGlobal(instr->qml_global()), r0), instr); + } + + +diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h +index 5733bd0..a7e1704 100644 +--- a/src/arm/lithium-arm.h ++++ b/src/arm/lithium-arm.h +@@ -1303,13 +1303,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_; + }; + + +@@ -1396,10 +1400,16 @@ class LCallGlobal: public LTemplateInstruction<1, 0, 0> { + DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global") + DECLARE_HYDROGEN_ACCESSOR(CallGlobal) + ++ explicit LCallGlobal(bool qml_global) : qml_global_(qml_global) {} ++ + virtual void PrintDataTo(StringStream* stream); + + Handle<String> name() const {return hydrogen()->name(); } + int arity() const { return hydrogen()->argument_count() - 1; } ++ ++ 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 4cf7df4..2e1e6fa 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); +@@ -2826,7 +2827,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)); + } + + +@@ -3280,7 +3281,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { + ASSERT(ToRegister(instr->result()).is(r0)); + + int arity = instr->arity(); +- RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; ++ RelocInfo::Mode mode = instr->qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT; + Handle<Code> ic = + isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + __ mov(r2, Operand(instr->name())); +diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h +index 90c4b37..5947e6a 100644 +--- a/src/arm/macro-assembler-arm.h ++++ b/src/arm/macro-assembler-arm.h +@@ -1326,6 +1326,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 f8b460d..217c71f 100644 +--- a/src/ast-inl.h ++++ b/src/ast-inl.h +@@ -126,6 +126,11 @@ StrictModeFlag FunctionLiteral::strict_mode_flag() const { + } + + ++bool FunctionLiteral::qml_mode() const { ++ return scope()->is_qml_mode(); ++} ++ ++ + } } // namespace v8::internal + + #endif // V8_AST_INL_H_ +diff --git a/src/ast.cc b/src/ast.cc +index 9e34bc0..0dc3c1c 100644 +--- a/src/ast.cc ++++ b/src/ast.cc +@@ -764,6 +764,11 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle, + is_monomorphic_ = oracle->CallIsMonomorphic(this); + Property* property = expression()->AsProperty(); + if (property == NULL) { ++ if (VariableProxy *proxy = expression()->AsVariableProxy()) { ++ if (proxy->var()->is_qml_global()) ++ return; ++ } ++ + // Function call. Specialize for monomorphic calls. + if (is_monomorphic_) target_ = oracle->GetCallTarget(this); + } else { +diff --git a/src/ast.h b/src/ast.h +index 3de00ef..8920b50 100644 +--- a/src/ast.h ++++ b/src/ast.h +@@ -1653,6 +1653,7 @@ class FunctionLiteral: public Expression { + bool is_anonymous() const { return is_anonymous_; } + bool strict_mode() const { return strict_mode_flag() == kStrictMode; } + StrictModeFlag strict_mode_flag() 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 fc7000b..4380764 100644 +--- a/src/code-stubs.h ++++ b/src/code-stubs.h +@@ -326,7 +326,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 88db467..4902e72 100644 +--- a/src/compiler.cc ++++ b/src/compiler.cc +@@ -447,7 +447,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); +@@ -515,6 +516,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(); + result = MakeFunctionInfo(&info); + if (extension == NULL && !result.is_null()) { + compilation_cache->PutScript(source, result); +@@ -534,7 +536,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); +@@ -559,6 +562,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, + info.MarkAsEval(); + if (is_global) info.MarkAsGlobal(); + info.SetStrictModeFlag(strict_mode); ++ if (qml_mode) info.MarkAsQmlMode(); + info.SetCallingContext(context); + result = MakeFunctionInfo(&info); + if (!result.is_null()) { +@@ -606,6 +610,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) { + info->SetStrictModeFlag(strict_mode); + shared->set_strict_mode_flag(strict_mode); + ++ // 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()) { +@@ -751,6 +761,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_flag(lit->strict_mode_flag()); ++ 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 bedf5ee..054e3b9 100644 +--- a/src/compiler.h ++++ b/src/compiler.h +@@ -57,6 +57,7 @@ class CompilationInfo BASE_EMBEDDED { + return StrictModeFlagField::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_; } +@@ -85,6 +86,9 @@ class CompilationInfo BASE_EMBEDDED { + ASSERT(is_lazy()); + flags_ |= IsInLoop::encode(true); + } ++ void MarkAsQmlMode() { ++ flags_ |= IsQmlMode::encode(true); ++ } + void MarkAsNative() { + flags_ |= IsNative::encode(true); + } +@@ -192,6 +196,9 @@ class CompilationInfo BASE_EMBEDDED { + ASSERT(strict_mode_flag() == kNonStrictMode); + SetStrictModeFlag(shared_info_->strict_mode_flag()); + } ++ if (!shared_info_.is_null() && shared_info_->qml_mode()) { ++ MarkAsQmlMode(); ++ } + } + + void SetMode(Mode mode) { +@@ -218,7 +225,8 @@ class CompilationInfo BASE_EMBEDDED { + // If compiling for debugging produce just full code matching the + // initial mode setting. + class IsCompilingForDebugging: public BitField<bool, 8, 1> {}; +- ++ // Qml mode ++ class IsQmlMode: public BitField<bool, 9, 1> {}; + + unsigned flags_; + +@@ -283,13 +291,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 b25ffac..3129af0 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() || +@@ -228,6 +236,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 7021ff8..c3cfeee 100644 +--- a/src/contexts.h ++++ b/src/contexts.h +@@ -218,6 +218,7 @@ class Context: public FixedArray { + // (with contexts), or the variable name (catch contexts), the serialized + // scope info (block contexts). + EXTENSION_INDEX, ++ QML_GLOBAL_INDEX, + GLOBAL_INDEX, + MIN_CONTEXT_SLOTS, + +@@ -321,6 +322,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 29955fa..4261ac2 100644 +--- a/src/execution.cc ++++ b/src/execution.cc +@@ -71,7 +71,8 @@ static Handle<Object> Invoke(bool is_construct, + Handle<Object> receiver, + int argc, + Handle<Object> args[], +- bool* has_pending_exception) { ++ bool* has_pending_exception, ++ Handle<Object> qml) { + Isolate* isolate = function->GetIsolate(); + + // Entering JavaScript. +@@ -102,6 +103,12 @@ static Handle<Object> Invoke(bool is_construct, + // make the current one is indeed a global object. + ASSERT(function->context()->global()->IsGlobalObject()); + ++ Handle<JSObject> oldqml; ++ if (!qml.is_null()) { ++ oldqml = Handle<JSObject>(function->context()->qml_global()); ++ function->context()->set_qml_global(JSObject::cast(*qml)); ++ } ++ + { + // Save and restore context around invocation and block the + // allocation of handles without explicit handle scopes. +@@ -118,6 +125,9 @@ static Handle<Object> Invoke(bool is_construct, + CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv); + } + ++ if (!qml.is_null()) ++ function->context()->set_qml_global(*oldqml); ++ + #ifdef DEBUG + value->Verify(); + #endif +@@ -146,7 +156,18 @@ Handle<Object> Execution::Call(Handle<Object> callable, + int argc, + Handle<Object> argv[], + bool* pending_exception, +- bool convert_receiver) { ++ bool convert_receiver) ++{ ++ return Call(callable, receiver, argc, argv, pending_exception, convert_receiver, Handle<Object>()); ++} ++ ++Handle<Object> Execution::Call(Handle<Object> callable, ++ Handle<Object> receiver, ++ int argc, ++ Handle<Object> argv[], ++ bool* pending_exception, ++ bool convert_receiver, ++ Handle<Object> qml) { + *pending_exception = false; + + if (!callable->IsJSFunction()) { +@@ -170,7 +191,7 @@ Handle<Object> Execution::Call(Handle<Object> callable, + if (*pending_exception) return callable; + } + +- return Invoke(false, func, receiver, argc, argv, pending_exception); ++ return Invoke(false, func, receiver, argc, argv, pending_exception, qml); + } + + +@@ -179,7 +200,7 @@ Handle<Object> Execution::New(Handle<JSFunction> func, + Handle<Object> argv[], + bool* pending_exception) { + return Invoke(true, func, Isolate::Current()->global(), argc, argv, +- pending_exception); ++ pending_exception, Handle<Object>()); + } + + +@@ -198,7 +219,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 f2d17d0..532e5d8 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, ++ Handle<Object> argv[], ++ 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 27c509f..f099d25 100644 +--- a/src/full-codegen.cc ++++ b/src/full-codegen.cc +@@ -513,7 +513,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(); +@@ -537,6 +537,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 9132502..78e6089 100644 +--- a/src/full-codegen.h ++++ b/src/full-codegen.h +@@ -583,6 +583,7 @@ class FullCodeGenerator: public AstVisitor { + StrictModeFlag strict_mode_flag() { + return function()->strict_mode_flag(); + } ++ 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 53a0f27..881a876 100644 +--- a/src/heap.cc ++++ b/src/heap.cc +@@ -4355,6 +4355,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; + } + +@@ -4375,6 +4376,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; + } +@@ -4393,6 +4395,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; + } + +@@ -4411,6 +4414,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.cc b/src/hydrogen-instructions.cc +index 6f46509..ac9728c 100644 +--- a/src/hydrogen-instructions.cc ++++ b/src/hydrogen-instructions.cc +@@ -655,6 +655,11 @@ void HCallNamed::PrintDataTo(StringStream* stream) { + } + + ++void HGlobalObject::PrintDataTo(StringStream* stream) { ++ stream->Add("qml_global: %s ", qml_global()?"true":"false"); ++ HUnaryOperation::PrintDataTo(stream); ++} ++ + void HCallGlobal::PrintDataTo(StringStream* stream) { + stream->Add("%o ", *name()); + HUnaryCall::PrintDataTo(stream); +diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h +index 65fc4df..c29d781 100644 +--- a/src/hydrogen-instructions.h ++++ b/src/hydrogen-instructions.h +@@ -1410,19 +1410,27 @@ 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); + } + ++ virtual void PrintDataTo(StringStream* stream); ++ + DECLARE_CONCRETE_INSTRUCTION(GlobalObject) + + virtual Representation RequiredInputRepresentation(int index) { + 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_; + }; + + +@@ -1601,7 +1609,7 @@ class HCallFunction: public HUnaryCall { + class HCallGlobal: public HUnaryCall { + public: + HCallGlobal(HValue* context, Handle<String> name, int argument_count) +- : HUnaryCall(context, argument_count), name_(name) { ++ : HUnaryCall(context, argument_count), name_(name), qml_global_(false) { + } + + virtual void PrintDataTo(StringStream* stream); +@@ -1613,10 +1621,14 @@ class HCallGlobal: public HUnaryCall { + return Representation::Tagged(); + } + ++ bool qml_global() { return qml_global_; } ++ void set_qml_global(bool v) { qml_global_ = v; } ++ + DECLARE_CONCRETE_INSTRUCTION(CallGlobal) + + private: + Handle<String> name_; ++ bool qml_global_; + }; + + +diff --git a/src/hydrogen.cc b/src/hydrogen.cc +index 3a4d172..0a7fad1 100644 +--- a/src/hydrogen.cc ++++ b/src/hydrogen.cc +@@ -3185,6 +3185,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, +@@ -3644,6 +3645,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, +@@ -5106,11 +5108,13 @@ void HGraphBuilder::VisitCall(Call* expr) { + } else { + HValue* context = environment()->LookupContext(); + HGlobalObject* receiver = new(zone()) HGlobalObject(context); ++ if (var->is_qml_global()) receiver->set_qml_global(true); + AddInstruction(receiver); + PushAndAdd(new(zone()) HPushArgument(receiver)); + CHECK_ALIVE(VisitArgumentList(expr->arguments())); + + call = new(zone()) HCallGlobal(context, var->name(), argument_count); ++ if (var->is_qml_global()) static_cast<HCallGlobal*>(call)->set_qml_global(true); + Drop(argument_count); + } + +diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc +index 37b519a..8a94a06 100644 +--- a/src/ia32/code-stubs-ia32.cc ++++ b/src/ia32/code-stubs-ia32.cc +@@ -144,6 +144,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 25588c8..9cee4a3 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); +@@ -1179,10 +1180,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); +@@ -1263,10 +1264,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; + } +@@ -1920,7 +1921,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(); +@@ -2235,9 +2236,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + FLAG_harmony_scoping ? kStrictMode : strict_mode_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); + } + + +@@ -2308,9 +2312,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). +@@ -3777,7 +3781,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); +@@ -4085,7 +4089,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 d4cbbce..b381227 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); +@@ -2661,7 +2662,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))); + } + + +@@ -3131,7 +3132,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { + ASSERT(ToRegister(instr->result()).is(eax)); + + int arity = instr->arity(); +- RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; ++ RelocInfo::Mode mode = instr->qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT; + Handle<Code> ic = + isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + __ mov(ecx, instr->name()); +diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc +index 626f899..d09d55f 100644 +--- a/src/ia32/lithium-ia32.cc ++++ b/src/ia32/lithium-ia32.cc +@@ -1144,7 +1144,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())); + } + + +@@ -1228,7 +1228,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { + LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { + LOperand* context = UseFixed(instr->context(), esi); + argument_count_ -= instr->argument_count(); +- LCallGlobal* result = new LCallGlobal(context); ++ LCallGlobal* result = new LCallGlobal(context, instr->qml_global()); + return MarkAsCall(DefineFixed(result, eax), instr); + } + +diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h +index 5f23afa..22541c8 100644 +--- a/src/ia32/lithium-ia32.h ++++ b/src/ia32/lithium-ia32.h +@@ -1338,13 +1338,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_; + }; + + +@@ -1443,7 +1447,7 @@ class LCallFunction: public LTemplateInstruction<1, 1, 0> { + + class LCallGlobal: public LTemplateInstruction<1, 1, 0> { + public: +- explicit LCallGlobal(LOperand* context) { ++ explicit LCallGlobal(LOperand* context, bool qml_global) : qml_global_(qml_global) { + inputs_[0] = context; + } + +@@ -1455,6 +1459,10 @@ class LCallGlobal: public LTemplateInstruction<1, 1, 0> { + LOperand* context() { return inputs_[0]; } + Handle<String> name() const {return hydrogen()->name(); } + int arity() const { return hydrogen()->argument_count() - 1; } ++ ++ 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 8528c55..de3c3a0 100644 +--- a/src/ia32/macro-assembler-ia32.h ++++ b/src/ia32/macro-assembler-ia32.h +@@ -935,6 +935,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 6a80c9c..2e83fb7 100644 +--- a/src/objects-inl.h ++++ b/src/objects-inl.h +@@ -3535,6 +3535,8 @@ void SharedFunctionInfo::set_strict_mode_flag(StrictModeFlag strict_mode_flag) { + + BOOL_GETTER(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 c38d461..73e7f8b 100644 +--- a/src/objects.h ++++ b/src/objects.h +@@ -4929,6 +4929,9 @@ class SharedFunctionInfo: public HeapObject { + inline StrictModeFlag strict_mode_flag(); + inline void set_strict_mode_flag(StrictModeFlag strict_mode_flag); + ++ // 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) + +@@ -5150,6 +5153,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 37204c9..357d340 100644 +--- a/src/parser.cc ++++ b/src/parser.cc +@@ -607,7 +607,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()); +@@ -623,11 +624,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); + } + } + +@@ -635,6 +636,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(top_scope_ == NULL); + ASSERT(target_stack_ == NULL); +@@ -654,6 +656,9 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, + LexicalScope lexical_scope(this, scope, isolate()); + ASSERT(top_scope_->strict_mode_flag() == kNonStrictMode); + top_scope_->SetStrictModeFlag(strict_mode); ++ if (qml_mode) { ++ scope->EnableQmlMode(); ++ } + ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16); + bool ok = true; + int beg_loc = scanner().location().beg_pos; +@@ -747,6 +752,10 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, + scope->strict_mode_flag() == info->strict_mode_flag()); + ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag()); + scope->SetStrictModeFlag(shared_info->strict_mode_flag()); ++ if (shared_info->qml_mode()) { ++ top_scope_->EnableQmlMode(); ++ } ++ + FunctionLiteral::Type type = shared_info->is_expression() + ? (shared_info->is_anonymous() + ? FunctionLiteral::ANONYMOUS_EXPRESSION +@@ -1856,6 +1865,11 @@ Block* Parser::ParseVariableDeclarations( + 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 +@@ -1872,6 +1886,11 @@ Block* Parser::ParseVariableDeclarations( + StrictModeFlag flag = initialization_scope->strict_mode_flag(); + 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, +@@ -5418,7 +5437,8 @@ bool ParserApi::Parse(CompilationInfo* info) { + Handle<String> source = Handle<String>(String::cast(script->source())); + result = parser.ParseProgram(source, + info->is_global(), +- info->strict_mode_flag()); ++ info->strict_mode_flag(), ++ info->is_qml_mode()); + } + } + info->SetFunction(result); +diff --git a/src/parser.h b/src/parser.h +index eaae6f7..a60951d 100644 +--- a/src/parser.h ++++ b/src/parser.h +@@ -430,7 +430,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 = false); + + FunctionLiteral* ParseLazy(CompilationInfo* info); + +@@ -476,6 +477,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 0e256c1..5746c20 100644 +--- a/src/runtime.cc ++++ b/src/runtime.cc +@@ -1307,19 +1307,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 = +@@ -1506,19 +1510,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; +@@ -1546,7 +1555,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(); + } +@@ -1556,9 +1565,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(); + } +@@ -1568,12 +1577,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. +@@ -1597,7 +1609,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 +@@ -9386,7 +9398,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, +@@ -9399,7 +9412,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()); + +@@ -9417,7 +9431,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( +@@ -9427,7 +9442,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); +@@ -9490,15 +9505,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); +@@ -9511,10 +9528,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()); + } + + +@@ -12034,6 +12053,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. +@@ -12107,7 +12127,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); +@@ -12117,7 +12138,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, +@@ -12198,7 +12220,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 67fc628..aada06d 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) \ +@@ -336,8 +336,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 3167c4d..6503d07 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(ScopeType type, + // Inherit the strict mode from the parent scope. + strict_mode_flag_ = (outer_scope != NULL) + ? outer_scope->strict_mode_flag_ : kNonStrictMode; ++ qml_mode_ = (outer_scope != NULL) && outer_scope->qml_mode_; + outer_scope_calls_non_strict_eval_ = false; + inner_scope_calls_eval_ = false; + force_eager_compilation_ = false; +@@ -907,6 +910,26 @@ void Scope::ResolveVariable(Scope* global_scope, + // by 'eval' introduced variable bindings. + if (var->is_global()) { + var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); ++ ++ if (qml_mode_) { ++ Handle<GlobalObject> global = isolate_->global(); ++ ++#ifdef ENABLE_DEBUGGER_SUPPORT ++ if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) { ++ //Get the context before the debugger was entered. ++ SaveContext *save = isolate_->save_context(); ++ while (save != NULL && *save->context() == *isolate_->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 { + Variable* invalidated = var; + var = NonLocal(proxy->name(), DYNAMIC_LOCAL); +@@ -918,12 +941,52 @@ void Scope::ResolveVariable(Scope* global_scope, + // No binding has been found. Declare a variable in global scope. + ASSERT(global_scope != NULL); + var = global_scope->DeclareGlobal(proxy->name()); ++ ++ if (qml_mode_) { ++ Handle<GlobalObject> global = isolate_->global(); ++ ++#ifdef ENABLE_DEBUGGER_SUPPORT ++ if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) { ++ //Get the context before the debugger was entered. ++ SaveContext *save = isolate_->save_context(); ++ while (save != NULL && *save->context() == *isolate_->debug()->debug_context()) ++ save = save->prev(); ++ ++ global = Handle<GlobalObject>(save->context()->global()); ++ } ++#endif ++ ++ if (!global->HasProperty(*(proxy->name()))) { ++ var->set_is_qml_global(true); ++ } ++ } ++ + break; + + case UNBOUND_EVAL_SHADOWED: + // No binding has been found. But some scope makes a + // non-strict 'eval' call. + var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); ++ ++ if (qml_mode_) { ++ Handle<GlobalObject> global = isolate_->global(); ++ ++#ifdef ENABLE_DEBUGGER_SUPPORT ++ if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) { ++ //Get the context before the debugger was entered. ++ SaveContext *save = isolate_->save_context(); ++ while (save != NULL && *save->context() == *isolate_->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); ++ } ++ } ++ + break; + + case DYNAMIC_LOOKUP: +diff --git a/src/scopes.h b/src/scopes.h +index a141887..41e5f5c 100644 +--- a/src/scopes.h ++++ b/src/scopes.h +@@ -228,6 +228,11 @@ class Scope: public ZoneObject { + end_position_ = statement_pos; + } + ++ // Enable qml mode for this scope ++ void EnableQmlMode() { ++ qml_mode_ = true; ++ } ++ + // --------------------------------------------------------------------------- + // Predicates. + +@@ -242,6 +247,7 @@ class Scope: public ZoneObject { + return is_eval_scope() || is_function_scope() || is_global_scope(); + } + bool is_strict_mode() const { return strict_mode_flag() == kStrictMode; } ++ bool is_qml_mode() const { return qml_mode_; } + bool is_strict_mode_eval_scope() const { + return is_eval_scope() && is_strict_mode(); + } +@@ -427,6 +433,8 @@ class Scope: public ZoneObject { + // Source positions. + int start_position_; + int end_position_; ++ // This scope is a qml mode scope. ++ bool qml_mode_; + + // Computed via PropagateScopeInfo. + bool outer_scope_calls_non_strict_eval_; +diff --git a/src/variables.cc b/src/variables.cc +index d85e1b2..1887935 100644 +--- a/src/variables.cc ++++ b/src/variables.cc +@@ -68,7 +68,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 8b2d869..33561b0 100644 +--- a/src/variables.h ++++ b/src/variables.h +@@ -155,6 +155,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_; +@@ -175,6 +177,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 f62c517..f30221f 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 bf640db..b1e5d35 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); +@@ -1155,10 +1156,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); +@@ -1240,9 +1241,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; + } +@@ -1834,7 +1835,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(); +@@ -2117,9 +2118,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + FLAG_harmony_scoping ? kStrictMode : strict_mode_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); + } + + +@@ -2188,8 +2192,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; +@@ -3638,7 +3642,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); +@@ -3936,7 +3940,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 38a8c18..2a95fee 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); +@@ -2610,7 +2611,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()); + } + + +@@ -3049,7 +3050,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) { + void LCodeGen::DoCallGlobal(LCallGlobal* instr) { + ASSERT(ToRegister(instr->result()).is(rax)); + int arity = instr->arity(); +- RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; ++ RelocInfo::Mode mode = instr->qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT; + Handle<Code> ic = + isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + __ Move(rcx, instr->name()); +diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc +index 0af2ce4..9e2731f 100644 +--- a/src/x64/lithium-x64.cc ++++ b/src/x64/lithium-x64.cc +@@ -1123,7 +1123,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { + + + LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { +- return DefineAsRegister(new LGlobalObject); ++ return DefineAsRegister(new LGlobalObject(instr->qml_global())); + } + + +@@ -1193,7 +1193,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { + + LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { + argument_count_ -= instr->argument_count(); +- return MarkAsCall(DefineFixed(new LCallGlobal, rax), instr); ++ return MarkAsCall(DefineFixed(new LCallGlobal(instr->qml_global()), rax), instr); + } + + +diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h +index 20a6937..8f1a3d8 100644 +--- a/src/x64/lithium-x64.h ++++ b/src/x64/lithium-x64.h +@@ -1303,7 +1303,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_; + }; + + +@@ -1393,10 +1399,16 @@ class LCallGlobal: public LTemplateInstruction<1, 0, 0> { + DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global") + DECLARE_HYDROGEN_ACCESSOR(CallGlobal) + ++ explicit LCallGlobal(bool qml_global) : qml_global_(qml_global) {} ++ + virtual void PrintDataTo(StringStream* stream); + + Handle<String> name() const {return hydrogen()->name(); } + int arity() const { return hydrogen()->argument_count() - 1; } ++ ++ 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 f5f81b1..5caa6cf 100644 +--- a/src/x64/macro-assembler-x64.h ++++ b/src/x64/macro-assembler-x64.h +@@ -1418,6 +1418,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 + |