diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2011-10-20 10:31:42 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-10-20 13:30:26 +0200 |
commit | ce5adc76847edf10dc843f5c93485e393f0ca099 (patch) | |
tree | 26ba0fde1d5a343dba15a5e8be1a78c91e3d6bb4 /src/v8/0005-Introduce-a-QML-compilation-mode.patch | |
parent | 3885a45e48b7fd680b6cb83e2d0d618fd04cf690 (diff) |
Revert "Update V8"
This reverts commit 1c4a5fcab76d1b769a4c0369d40dd0dd7c0e7495
Several of the qtdeclarative tests and examples are dying randomly with messages like this:
>
> #
> # Fatal error in ../3rdparty/v8/src/objects-inl.h, line 2169
> # CHECK(object->IsJSFunction()) failed
> #
>
>
> ==== Stack trace ============================================
>
>
> ==== Details ================================================
>
> ==== Key ============================================
>
> =====================
>
> Aborted (core dumped)
Change-Id: Iebaa2497a6f6ef616ef4c3576c217d2a8a2c1ea5
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Diffstat (limited to 'src/v8/0005-Introduce-a-QML-compilation-mode.patch')
-rw-r--r-- | src/v8/0005-Introduce-a-QML-compilation-mode.patch | 1856 |
1 files changed, 1856 insertions, 0 deletions
diff --git a/src/v8/0005-Introduce-a-QML-compilation-mode.patch b/src/v8/0005-Introduce-a-QML-compilation-mode.patch new file mode 100644 index 0000000000..c5c36a1f95 --- /dev/null +++ b/src/v8/0005-Introduce-a-QML-compilation-mode.patch @@ -0,0 +1,1856 @@ +From 60c1a26bf89d3b06bcdd8408fcee89a018120f32 Mon Sep 17 00:00:00 2001 +From: Aaron Kennedy <aaron.kennedy@nokia.com> +Date: Mon, 23 May 2011 18:26:19 +1000 +Subject: [PATCH 05/16] Introduce a QML compilation mode + +In QML mode, there is a second global object - known as the QML +global object. During property resolution, if a property is not +present on the JS global object, it is resolve on the QML global +object. + +This global object behavior is only enabled if a script is being +compiled in QML mode. The object to use as the QML global object +is passed as a parameter to the Script::Run() method. Any function +closures etc. created during the run will retain a reference to this +object, so different objects can be passed in different script +runs. +--- + include/v8.h | 18 +++++++-- + src/api.cc | 52 ++++++++++++++++++++++----- + src/arm/code-stubs-arm.cc | 4 ++ + src/arm/full-codegen-arm.cc | 26 ++++++++------ + src/arm/lithium-arm.cc | 2 +- + src/arm/lithium-arm.h | 6 +++- + src/arm/lithium-codegen-arm.cc | 7 ++-- + src/arm/macro-assembler-arm.h | 5 +++ + src/ast-inl.h | 5 +++ + src/ast.h | 1 + + src/code-stubs.h | 2 +- + src/compiler.cc | 15 +++++++- + src/compiler.h | 22 +++++++++-- + src/contexts.cc | 35 ++++++++++++++++++ + src/contexts.h | 4 ++ + src/execution.cc | 28 ++++++++++++-- + src/execution.h | 6 +++ + src/full-codegen.cc | 3 +- + src/full-codegen.h | 1 + + src/heap.cc | 2 + + src/hydrogen-instructions.h | 10 ++++- + src/hydrogen.cc | 2 + + src/ia32/code-stubs-ia32.cc | 7 ++++ + src/ia32/full-codegen-ia32.cc | 26 ++++++++------ + src/ia32/lithium-codegen-ia32.cc | 7 ++-- + src/ia32/lithium-ia32.cc | 2 +- + src/ia32/lithium-ia32.h | 6 +++- + src/ia32/macro-assembler-ia32.h | 5 +++ + src/objects-inl.h | 12 ++++++ + src/objects.h | 5 +++ + src/parser.cc | 27 ++++++++++++-- + src/parser.h | 4 ++- + src/prettyprinter.cc | 3 ++ + src/runtime.cc | 72 ++++++++++++++++++++++++------------- + src/runtime.h | 8 ++-- + src/scopes.cc | 59 +++++++++++++++++++++++++++++++ + src/scopes.h | 7 ++++ + src/variables.cc | 3 +- + src/variables.h | 5 +++ + src/x64/code-stubs-x64.cc | 4 ++ + src/x64/full-codegen-x64.cc | 26 ++++++++------ + src/x64/lithium-codegen-x64.cc | 7 ++-- + src/x64/lithium-x64.cc | 2 +- + src/x64/lithium-x64.h | 6 +++ + src/x64/macro-assembler-x64.h | 5 +++ + 45 files changed, 455 insertions(+), 109 deletions(-) + +diff --git a/include/v8.h b/include/v8.h +index 205e856..d78ab1f 100644 +--- a/include/v8.h ++++ b/include/v8.h +@@ -577,6 +577,10 @@ class ScriptOrigin { + */ + class V8EXPORT Script { + public: ++ enum CompileFlags { ++ Default = 0x00, ++ QmlMode = 0x01 ++ }; + + /** + * Compiles the specified script (context-independent). +@@ -596,7 +600,8 @@ class V8EXPORT Script { + static Local<Script> New(Handle<String> source, + ScriptOrigin* origin = NULL, + ScriptData* pre_data = NULL, +- Handle<String> script_data = Handle<String>()); ++ Handle<String> script_data = Handle<String>(), ++ CompileFlags = Default); + + /** + * Compiles the specified script using the specified file name +@@ -609,7 +614,8 @@ class V8EXPORT Script { + * will use the currently entered context). + */ + static Local<Script> New(Handle<String> source, +- Handle<Value> file_name); ++ Handle<Value> file_name, ++ CompileFlags = Default); + + /** + * Compiles the specified script (bound to current context). +@@ -630,7 +636,8 @@ class V8EXPORT Script { + static Local<Script> Compile(Handle<String> source, + ScriptOrigin* origin = NULL, + ScriptData* pre_data = NULL, +- Handle<String> script_data = Handle<String>()); ++ Handle<String> script_data = Handle<String>(), ++ CompileFlags = Default); + + /** + * Compiles the specified script using the specified file name +@@ -647,7 +654,8 @@ class V8EXPORT Script { + */ + static Local<Script> Compile(Handle<String> source, + Handle<Value> file_name, +- Handle<String> script_data = Handle<String>()); ++ Handle<String> script_data = Handle<String>(), ++ CompileFlags = Default); + + /** + * Runs the script returning the resulting value. If the script is +@@ -657,6 +665,7 @@ class V8EXPORT Script { + * compiled. + */ + Local<Value> Run(); ++ Local<Value> Run(Handle<Object> qml); + + /** + * Returns the script id value. +@@ -3327,6 +3336,7 @@ class V8EXPORT Context { + * JavaScript frames an empty handle is returned. + */ + static Local<Context> GetCalling(); ++ static Local<Object> GetCallingQmlGlobal(); + + /** + * Sets the security token for the context. To access an object in +diff --git a/src/api.cc b/src/api.cc +index 1a6fbbb..39767f4 100644 +--- a/src/api.cc ++++ b/src/api.cc +@@ -1372,7 +1372,8 @@ ScriptData* ScriptData::New(const char* data, int length) { + Local<Script> Script::New(v8::Handle<String> source, + v8::ScriptOrigin* origin, + v8::ScriptData* pre_data, +- v8::Handle<String> script_data) { ++ v8::Handle<String> script_data, ++ v8::Script::CompileFlags compile_flags) { + i::Isolate* isolate = i::Isolate::Current(); + ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>()); + LOG_API(isolate, "Script::New"); +@@ -1409,7 +1410,8 @@ Local<Script> Script::New(v8::Handle<String> source, + NULL, + pre_data_impl, + Utils::OpenHandle(*script_data), +- i::NOT_NATIVES_CODE); ++ i::NOT_NATIVES_CODE, ++ compile_flags); + has_pending_exception = result.is_null(); + EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>()); + return Local<Script>(ToApi<Script>(result)); +@@ -1417,21 +1419,23 @@ Local<Script> Script::New(v8::Handle<String> source, + + + Local<Script> Script::New(v8::Handle<String> source, +- v8::Handle<Value> file_name) { ++ v8::Handle<Value> file_name, ++ v8::Script::CompileFlags compile_flags) { + ScriptOrigin origin(file_name); +- return New(source, &origin); ++ return New(source, &origin, 0, Handle<String>(), compile_flags); + } + + + Local<Script> Script::Compile(v8::Handle<String> source, + v8::ScriptOrigin* origin, + v8::ScriptData* pre_data, +- v8::Handle<String> script_data) { ++ v8::Handle<String> script_data, ++ v8::Script::CompileFlags compile_flags) { + i::Isolate* isolate = i::Isolate::Current(); + ON_BAILOUT(isolate, "v8::Script::Compile()", return Local<Script>()); + LOG_API(isolate, "Script::Compile"); + ENTER_V8(isolate); +- Local<Script> generic = New(source, origin, pre_data, script_data); ++ Local<Script> generic = New(source, origin, pre_data, script_data, compile_flags); + if (generic.IsEmpty()) + return generic; + i::Handle<i::Object> obj = Utils::OpenHandle(*generic); +@@ -1447,13 +1451,18 @@ Local<Script> Script::Compile(v8::Handle<String> source, + + Local<Script> Script::Compile(v8::Handle<String> source, + v8::Handle<Value> file_name, +- v8::Handle<String> script_data) { ++ v8::Handle<String> script_data, ++ v8::Script::CompileFlags compile_flags) { + ScriptOrigin origin(file_name); +- return Compile(source, &origin, 0, script_data); ++ return Compile(source, &origin, 0, script_data, compile_flags); + } + + + Local<Value> Script::Run() { ++ return Run(Handle<Object>()); ++} ++ ++Local<Value> Script::Run(Handle<Object> qml) { + i::Isolate* isolate = i::Isolate::Current(); + ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>()); + LOG_API(isolate, "Script::Run"); +@@ -1472,10 +1481,11 @@ Local<Value> Script::Run() { + fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate); + } + EXCEPTION_PREAMBLE(isolate); ++ i::Handle<i::Object> qmlglobal = Utils::OpenHandle(*qml); + i::Handle<i::Object> receiver( + isolate->context()->global_proxy(), isolate); + i::Handle<i::Object> result = +- i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception); ++ i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception, qmlglobal); + EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); + raw_result = *result; + } +@@ -3943,6 +3953,30 @@ v8::Local<v8::Context> Context::GetCalling() { + } + + ++v8::Local<v8::Object> Context::GetCallingQmlGlobal() { ++ i::Isolate* isolate = i::Isolate::Current(); ++ if (IsDeadCheck(isolate, "v8::Context::GetCallingQmlGlobal()")) { ++ return Local<Object>(); ++ } ++ ++ i::Context *context = isolate->context(); ++ if (!context->qml_global()->IsUndefined()) { ++ i::Handle<i::Object> qmlglobal(context->qml_global()); ++ return Utils::ToLocal(i::Handle<i::JSObject>::cast(qmlglobal)); ++ } ++ ++ i::JavaScriptFrameIterator it; ++ if (it.done()) return Local<Object>(); ++ context = i::Context::cast(it.frame()->context()); ++ if (!context->qml_global()->IsUndefined()) { ++ i::Handle<i::Object> qmlglobal(context->qml_global()); ++ return Utils::ToLocal(i::Handle<i::JSObject>::cast(qmlglobal)); ++ } else { ++ return Local<Object>(); ++ } ++} ++ ++ + v8::Local<v8::Object> Context::Global() { + if (IsDeadCheck(i::Isolate::Current(), "v8::Context::Global()")) { + return Local<v8::Object>(); +diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc +index 8c147f9..a2626bf 100644 +--- a/src/arm/code-stubs-arm.cc ++++ b/src/arm/code-stubs-arm.cc +@@ -166,6 +166,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { + __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); + __ str(r1, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX))); + ++ // Copy the qml global object from the surrounding context. ++ __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); ++ __ str(r1, MemOperand(r0, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); ++ + // Initialize the rest of the slots to undefined. + __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); + for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { +diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc +index 871b453..a69f10d 100644 +--- a/src/arm/full-codegen-arm.cc ++++ b/src/arm/full-codegen-arm.cc +@@ -154,12 +154,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { + + // Possibly allocate a local context. + int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; +- if (heap_slots > 0) { ++ if (heap_slots > 0 || ++ (scope()->is_qml_mode() && scope()->is_global_scope())) { + Comment cmnt(masm_, "[ Allocate local context"); + // Argument to NewContext is the function, which is in r1. + __ push(r1); + if (heap_slots <= FastNewContextStub::kMaximumSlots) { +- FastNewContextStub stub(heap_slots); ++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); + __ CallStub(&stub); + } else { + __ CallRuntime(Runtime::kNewContext, 1); +@@ -1247,9 +1248,9 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( + __ bind(&fast); + } + +- __ ldr(r0, GlobalObjectOperand()); ++ __ ldr(r0, slot->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + __ mov(r2, Operand(slot->var()->name())); +- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) ++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global()) + ? RelocInfo::CODE_TARGET + : RelocInfo::CODE_TARGET_CONTEXT; + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); +@@ -1268,10 +1269,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) { + Comment cmnt(masm_, "Global variable"); + // Use inline caching. Variable name is passed in r2 and the global + // object (receiver) in r0. +- __ ldr(r0, GlobalObjectOperand()); ++ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + __ mov(r2, Operand(var->name())); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); +- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); ++ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); + context()->Plug(r0); + + } else if (slot != NULL && slot->type() == Slot::LOOKUP) { +@@ -1893,11 +1894,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, + // assignment. Right-hand-side value is passed in r0, variable name in + // r2, and the global object in r1. + __ mov(r2, Operand(var->name())); +- __ ldr(r1, GlobalObjectOperand()); ++ __ ldr(r1, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + Handle<Code> ic = is_strict_mode() + ? isolate()->builtins()->StoreIC_Initialize_Strict() + : isolate()->builtins()->StoreIC_Initialize(); +- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); ++ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); + + } else if (op == Token::INIT_CONST) { + // Like var declarations, const declarations are hoisted to function +@@ -2184,10 +2185,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + // Push the strict mode flag. + __ mov(r1, Operand(Smi::FromInt(strict_mode_flag()))); + __ push(r1); ++ // Push the qml mode flag. ++ __ mov(r1, Operand(Smi::FromInt(is_qml_mode()))); ++ __ push(r1); + + __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP + ? Runtime::kResolvePossiblyDirectEvalNoLookup +- : Runtime::kResolvePossiblyDirectEval, 4); ++ : Runtime::kResolvePossiblyDirectEval, 5); + } + + +@@ -2263,9 +2267,9 @@ void FullCodeGenerator::VisitCall(Call* expr) { + context()->DropAndPlug(1, r0); + } else if (var != NULL && !var->is_this() && var->is_global()) { + // Push global object as receiver for the call IC. +- __ ldr(r0, GlobalObjectOperand()); ++ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + __ push(r0); +- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); ++ EmitCallWithIC(expr, var->name(), var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); + } else if (var != NULL && var->AsSlot() != NULL && + var->AsSlot()->type() == Slot::LOOKUP) { + // Call to a lookup slot (dynamically introduced variable). +diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc +index 3f1d15b..8406a96 100644 +--- a/src/arm/lithium-arm.cc ++++ b/src/arm/lithium-arm.cc +@@ -1195,7 +1195,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { + + LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { + LOperand* context = UseRegisterAtStart(instr->value()); +- return DefineAsRegister(new LGlobalObject(context)); ++ return DefineAsRegister(new LGlobalObject(context, instr->qml_global())); + } + + +diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h +index 6da7c86..10b901f 100644 +--- a/src/arm/lithium-arm.h ++++ b/src/arm/lithium-arm.h +@@ -1378,13 +1378,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { + + class LGlobalObject: public LTemplateInstruction<1, 1, 0> { + public: +- explicit LGlobalObject(LOperand* context) { ++ explicit LGlobalObject(LOperand* context, bool qml_global) { + inputs_[0] = context; ++ qml_global_ = qml_global; + } + + DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object") + + LOperand* context() { return InputAt(0); } ++ bool qml_global() { return qml_global_; } ++ private: ++ bool qml_global_; + }; + + +diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc +index 4912449..db114ea 100644 +--- a/src/arm/lithium-codegen-arm.cc ++++ b/src/arm/lithium-codegen-arm.cc +@@ -166,12 +166,13 @@ bool LCodeGen::GeneratePrologue() { + + // Possibly allocate a local context. + int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; +- if (heap_slots > 0) { ++ if (heap_slots > 0 || ++ (scope()->is_qml_mode() && scope()->is_global_scope())) { + Comment(";;; Allocate local context"); + // Argument to NewContext is the function, which is in r1. + __ push(r1); + if (heap_slots <= FastNewContextStub::kMaximumSlots) { +- FastNewContextStub stub(heap_slots); ++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); + __ CallStub(&stub); + } else { + __ CallRuntime(Runtime::kNewContext, 1); +@@ -2664,7 +2665,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { + void LCodeGen::DoGlobalObject(LGlobalObject* instr) { + Register context = ToRegister(instr->context()); + Register result = ToRegister(instr->result()); +- __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX)); ++ __ ldr(result, ContextOperand(cp, instr->qml_global()?Context::QML_GLOBAL_INDEX:Context::GLOBAL_INDEX)); + } + + +diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h +index ab5efb0..d40cdbc 100644 +--- a/src/arm/macro-assembler-arm.h ++++ b/src/arm/macro-assembler-arm.h +@@ -1056,6 +1056,11 @@ static inline MemOperand GlobalObjectOperand() { + } + + ++static inline MemOperand QmlGlobalObjectOperand() { ++ return ContextOperand(cp, Context::QML_GLOBAL_INDEX); ++} ++ ++ + #ifdef GENERATED_CODE_COVERAGE + #define CODE_COVERAGE_STRINGIFY(x) #x + #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) +diff --git a/src/ast-inl.h b/src/ast-inl.h +index d80684a..adc5a1f 100644 +--- a/src/ast-inl.h ++++ b/src/ast-inl.h +@@ -106,6 +106,11 @@ bool FunctionLiteral::strict_mode() const { + } + + ++bool FunctionLiteral::qml_mode() const { ++ return scope()->is_qml_mode(); ++} ++ ++ + } } // namespace v8::internal + + #endif // V8_AST_INL_H_ +diff --git a/src/ast.h b/src/ast.h +index 65a25a9..f790dc0 100644 +--- a/src/ast.h ++++ b/src/ast.h +@@ -1712,6 +1712,7 @@ class FunctionLiteral: public Expression { + int end_position() const { return end_position_; } + bool is_expression() const { return is_expression_; } + bool strict_mode() const; ++ bool qml_mode() const; + + int materialized_literal_count() { return materialized_literal_count_; } + int expected_property_count() { return expected_property_count_; } +diff --git a/src/code-stubs.h b/src/code-stubs.h +index 56ef072..37e5383 100644 +--- a/src/code-stubs.h ++++ b/src/code-stubs.h +@@ -303,7 +303,7 @@ class FastNewContextStub : public CodeStub { + static const int kMaximumSlots = 64; + + explicit FastNewContextStub(int slots) : slots_(slots) { +- ASSERT(slots_ > 0 && slots <= kMaximumSlots); ++ ASSERT(slots_ >= 0 && slots <= kMaximumSlots); + } + + void Generate(MacroAssembler* masm); +diff --git a/src/compiler.cc b/src/compiler.cc +index 86d5de3..d2191b9 100755 +--- a/src/compiler.cc ++++ b/src/compiler.cc +@@ -462,7 +462,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, + v8::Extension* extension, + ScriptDataImpl* input_pre_data, + Handle<Object> script_data, +- NativesFlag natives) { ++ NativesFlag natives, ++ v8::Script::CompileFlags compile_flags) { + Isolate* isolate = source->GetIsolate(); + int source_length = source->length(); + isolate->counters()->total_load_size()->Increment(source_length); +@@ -523,6 +524,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, + info.MarkAsGlobal(); + info.SetExtension(extension); + info.SetPreParseData(pre_data); ++ if (compile_flags & v8::Script::QmlMode) info.MarkAsQmlMode(); + if (natives == NATIVES_CODE) info.MarkAsAllowingNativesSyntax(); + result = MakeFunctionInfo(&info); + if (extension == NULL && !result.is_null()) { +@@ -543,7 +545,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, + Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, + Handle<Context> context, + bool is_global, +- StrictModeFlag strict_mode) { ++ StrictModeFlag strict_mode, ++ bool qml_mode) { + Isolate* isolate = source->GetIsolate(); + int source_length = source->length(); + isolate->counters()->total_eval_size()->Increment(source_length); +@@ -567,6 +570,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, + CompilationInfo info(script); + info.MarkAsEval(); + if (is_global) info.MarkAsGlobal(); ++ if (qml_mode) info.MarkAsQmlMode(); + if (strict_mode == kStrictMode) info.MarkAsStrictMode(); + info.SetCallingContext(context); + result = MakeFunctionInfo(&info); +@@ -610,6 +614,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) { + info->MarkAsStrictMode(); + } + ++ // After parsing we know function's qml mode. Remember it. ++ if (info->function()->qml_mode()) { ++ shared->set_qml_mode(true); ++ info->MarkAsQmlMode(); ++ } ++ + // Compile the code. + if (!MakeCode(info)) { + if (!isolate->has_pending_exception()) { +@@ -755,6 +765,7 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info, + *lit->this_property_assignments()); + function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); + function_info->set_strict_mode(lit->strict_mode()); ++ function_info->set_qml_mode(lit->qml_mode()); + } + + +diff --git a/src/compiler.h b/src/compiler.h +index e75e869..17cd369 100644 +--- a/src/compiler.h ++++ b/src/compiler.h +@@ -54,6 +54,7 @@ class CompilationInfo BASE_EMBEDDED { + bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; } + bool is_strict_mode() const { return (flags_ & IsStrictMode::mask()) != 0; } + bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; } ++ bool is_qml_mode() const { return (flags_ & IsQmlMode::mask()) != 0; } + FunctionLiteral* function() const { return function_; } + Scope* scope() const { return scope_; } + Handle<Code> code() const { return code_; } +@@ -83,6 +84,9 @@ class CompilationInfo BASE_EMBEDDED { + ASSERT(is_lazy()); + flags_ |= IsInLoop::encode(true); + } ++ void MarkAsQmlMode() { ++ flags_ |= IsQmlMode::encode(true); ++ } + void MarkAsAllowingNativesSyntax() { + flags_ |= IsNativesSyntaxAllowed::encode(true); + } +@@ -141,6 +145,7 @@ class CompilationInfo BASE_EMBEDDED { + + // Determine whether or not we can adaptively optimize. + bool AllowOptimize() { ++ // XXX - fix qml mode optimizations + return V8::UseCrankshaft() && !closure_.is_null(); + } + +@@ -163,8 +168,13 @@ class CompilationInfo BASE_EMBEDDED { + + void Initialize(Mode mode) { + mode_ = V8::UseCrankshaft() ? mode : NONOPT; +- if (!shared_info_.is_null() && shared_info_->strict_mode()) { +- MarkAsStrictMode(); ++ if (!shared_info_.is_null()) { ++ if (shared_info_->strict_mode()) { ++ MarkAsStrictMode(); ++ } ++ if (shared_info_->qml_mode()) { ++ MarkAsQmlMode(); ++ } + } + } + +@@ -187,6 +197,8 @@ class CompilationInfo BASE_EMBEDDED { + class IsStrictMode: public BitField<bool, 4, 1> {}; + // Native syntax (%-stuff) allowed? + class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {}; ++ // Qml mode ++ class IsQmlMode: public BitField<bool, 6, 1> {}; + + unsigned flags_; + +@@ -252,13 +264,15 @@ class Compiler : public AllStatic { + v8::Extension* extension, + ScriptDataImpl* pre_data, + Handle<Object> script_data, +- NativesFlag is_natives_code); ++ NativesFlag is_natives_code, ++ v8::Script::CompileFlags compile_flags = v8::Script::Default); + + // Compile a String source within a context for Eval. + static Handle<SharedFunctionInfo> CompileEval(Handle<String> source, + Handle<Context> context, + bool is_global, +- StrictModeFlag strict_mode); ++ StrictModeFlag strict_mode, ++ bool qml_mode); + + // Compile from function info (used for lazy compilation). Returns true on + // success and false if the compilation resulted in a stack overflow. +diff --git a/src/contexts.cc b/src/contexts.cc +index 520f3dd..035ac3b 100644 +--- a/src/contexts.cc ++++ b/src/contexts.cc +@@ -89,6 +89,9 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags, + 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)); +@@ -119,6 +122,11 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags, + } + } + ++ if (qml_global.is_null() && !context->qml_global()->IsUndefined()) { ++ qml_global = Handle<JSObject>(context->qml_global(), isolate); ++ qml_global_global = Handle<JSObject>(context->global(), isolate); ++ } ++ + if (context->is_function_context()) { + // we have context-local slots + +@@ -198,6 +206,33 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags, + } + } while (follow_context_chain); + ++ if (!qml_global.is_null()) { ++ if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0) { ++ *attributes = qml_global_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; ++ } ++ } ++ } ++ + // slot not found + if (FLAG_trace_contexts) { + PrintF("=> no property/slot found\n"); +diff --git a/src/contexts.h b/src/contexts.h +index e46619e..57d8e7b 100644 +--- a/src/contexts.h ++++ b/src/contexts.h +@@ -182,6 +182,7 @@ class Context: public FixedArray { + FCONTEXT_INDEX, + PREVIOUS_INDEX, + EXTENSION_INDEX, ++ QML_GLOBAL_INDEX, + GLOBAL_INDEX, + MIN_CONTEXT_SLOTS, + +@@ -273,6 +274,9 @@ class Context: public FixedArray { + } + void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); } + ++ JSObject *qml_global() { return reinterpret_cast<JSObject *>(get(QML_GLOBAL_INDEX)); } ++ void set_qml_global(JSObject *qml_global) { set(QML_GLOBAL_INDEX, qml_global); } ++ + // Returns a JSGlobalProxy object or null. + JSObject* global_proxy(); + void set_global_proxy(JSObject* global); +diff --git a/src/execution.cc b/src/execution.cc +index eb26438..1632076 100644 +--- a/src/execution.cc ++++ b/src/execution.cc +@@ -70,7 +70,8 @@ static Handle<Object> Invoke(bool construct, + Handle<Object> receiver, + int argc, + Object*** args, +- bool* has_pending_exception) { ++ bool* has_pending_exception, ++ Handle<Object> qml) { + Isolate* isolate = func->GetIsolate(); + + // Entering JavaScript. +@@ -107,6 +108,12 @@ static Handle<Object> Invoke(bool construct, + // make the current one is indeed a global object. + ASSERT(func->context()->global()->IsGlobalObject()); + ++ Handle<JSObject> oldqml; ++ if (!qml.is_null()) { ++ oldqml = Handle<JSObject>(func->context()->qml_global()); ++ func->context()->set_qml_global(JSObject::cast(*qml)); ++ } ++ + { + // Save and restore context around invocation and block the + // allocation of handles without explicit handle scopes. +@@ -122,6 +129,9 @@ static Handle<Object> Invoke(bool construct, + receiver_pointer, argc, args); + } + ++ if (!qml.is_null()) ++ func->context()->set_qml_global(*oldqml); ++ + #ifdef DEBUG + value->Verify(); + #endif +@@ -150,14 +160,24 @@ Handle<Object> Execution::Call(Handle<JSFunction> func, + int argc, + Object*** args, + bool* pending_exception) { +- return Invoke(false, func, receiver, argc, args, pending_exception); ++ return Invoke(false, func, receiver, argc, args, pending_exception, Handle<Object>()); ++} ++ ++ ++Handle<Object> Execution::Call(Handle<JSFunction> func, ++ Handle<Object> receiver, ++ int argc, ++ Object*** args, ++ bool* pending_exception, ++ Handle<Object> qml) { ++ return Invoke(false, func, receiver, argc, args, pending_exception, qml); + } + + + Handle<Object> Execution::New(Handle<JSFunction> func, int argc, + Object*** args, bool* pending_exception) { + return Invoke(true, func, Isolate::Current()->global(), argc, args, +- pending_exception); ++ pending_exception, Handle<Object>()); + } + + +@@ -175,7 +195,7 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func, + catcher.SetCaptureMessage(false); + + Handle<Object> result = Invoke(false, func, receiver, argc, args, +- caught_exception); ++ caught_exception, Handle<Object>()); + + if (*caught_exception) { + ASSERT(catcher.HasCaught()); +diff --git a/src/execution.h b/src/execution.h +index d4b80d2..a476eb4 100644 +--- a/src/execution.h ++++ b/src/execution.h +@@ -56,6 +56,12 @@ class Execution : public AllStatic { + int argc, + Object*** args, + bool* pending_exception); ++ static Handle<Object> Call(Handle<JSFunction> func, ++ Handle<Object> receiver, ++ int argc, ++ Object*** args, ++ bool* pending_exception, ++ Handle<Object> qml); + + // Construct object from function, the caller supplies an array of + // arguments. Arguments are Object* type. After function returns, +diff --git a/src/full-codegen.cc b/src/full-codegen.cc +index d6ba56e..2eaef0f 100644 +--- a/src/full-codegen.cc ++++ b/src/full-codegen.cc +@@ -542,7 +542,7 @@ void FullCodeGenerator::VisitDeclarations( + // Do nothing in case of no declared global functions or variables. + if (globals > 0) { + Handle<FixedArray> array = +- isolate()->factory()->NewFixedArray(2 * globals, TENURED); ++ isolate()->factory()->NewFixedArray(3 * globals, TENURED); + for (int j = 0, i = 0; i < length; i++) { + Declaration* decl = declarations->at(i); + Variable* var = decl->proxy()->var(); +@@ -567,6 +567,7 @@ void FullCodeGenerator::VisitDeclarations( + } + array->set(j++, *function); + } ++ array->set(j++, Smi::FromInt(var->is_qml_global())); + } + } + // Invoke the platform-dependent code generator to do the actual +diff --git a/src/full-codegen.h b/src/full-codegen.h +index d6ed1b9..e3241aa 100644 +--- a/src/full-codegen.h ++++ b/src/full-codegen.h +@@ -505,6 +505,7 @@ class FullCodeGenerator: public AstVisitor { + StrictModeFlag strict_mode_flag() { + return is_strict_mode() ? kStrictMode : kNonStrictMode; + } ++ bool is_qml_mode() { return function()->qml_mode(); } + FunctionLiteral* function() { return info_->function(); } + Scope* scope() { return info_->scope(); } + +diff --git a/src/heap.cc b/src/heap.cc +index bf2940e..da958c2 100644 +--- a/src/heap.cc ++++ b/src/heap.cc +@@ -3795,6 +3795,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) { + context->set_previous(NULL); + context->set_extension(NULL); + context->set_global(function->context()->global()); ++ context->set_qml_global(function->context()->qml_global()); + ASSERT(!context->IsGlobalContext()); + ASSERT(context->is_function_context()); + ASSERT(result->IsContext()); +@@ -3817,6 +3818,7 @@ MaybeObject* Heap::AllocateWithContext(Context* previous, + context->set_previous(previous); + context->set_extension(extension); + context->set_global(previous->global()); ++ context->set_qml_global(previous->qml_global()); + ASSERT(!context->IsGlobalContext()); + ASSERT(!context->is_function_context()); + ASSERT(result->IsContext()); +diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h +index a623775..52455bc 100644 +--- a/src/hydrogen-instructions.h ++++ b/src/hydrogen-instructions.h +@@ -1148,7 +1148,7 @@ class HOuterContext: public HUnaryOperation { + + class HGlobalObject: public HUnaryOperation { + public: +- explicit HGlobalObject(HValue* context) : HUnaryOperation(context) { ++ explicit HGlobalObject(HValue* context) : HUnaryOperation(context), qml_global_(false) { + set_representation(Representation::Tagged()); + SetFlag(kUseGVN); + } +@@ -1159,8 +1159,14 @@ class HGlobalObject: public HUnaryOperation { + return Representation::Tagged(); + } + ++ bool qml_global() { return qml_global_; } ++ void set_qml_global(bool v) { qml_global_ = v; } ++ + protected: + virtual bool DataEquals(HValue* other) { return true; } ++ ++ private: ++ bool qml_global_; + }; + + +@@ -1177,7 +1183,7 @@ class HGlobalReceiver: public HUnaryOperation { + virtual Representation RequiredInputRepresentation(int index) const { + return Representation::Tagged(); + } +- ++ + protected: + virtual bool DataEquals(HValue* other) { return true; } + }; +diff --git a/src/hydrogen.cc b/src/hydrogen.cc +index 73ea97d..d17e304 100644 +--- a/src/hydrogen.cc ++++ b/src/hydrogen.cc +@@ -2918,6 +2918,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { + HContext* context = new(zone()) HContext; + AddInstruction(context); + HGlobalObject* global_object = new(zone()) HGlobalObject(context); ++ if (variable->is_qml_global()) global_object->set_qml_global(true); + AddInstruction(global_object); + HLoadGlobalGeneric* instr = + new(zone()) HLoadGlobalGeneric(context, +@@ -3307,6 +3308,7 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, + HContext* context = new(zone()) HContext; + AddInstruction(context); + HGlobalObject* global_object = new(zone()) HGlobalObject(context); ++ if (var->is_qml_global()) global_object->set_qml_global(true); + AddInstruction(global_object); + HStoreGlobalGeneric* instr = + new(zone()) HStoreGlobalGeneric(context, +diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc +index 5d32095..afa599e 100644 +--- a/src/ia32/code-stubs-ia32.cc ++++ b/src/ia32/code-stubs-ia32.cc +@@ -147,6 +147,13 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { + __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::GLOBAL_INDEX))); + __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx); + ++ // Copy the qml global object from the surrounding context. We go through the ++ // context in the function (ecx) to match the allocation behavior we have ++ // in the runtime system (see Heap::AllocateFunctionContext). ++ __ mov(ebx, FieldOperand(ecx, JSFunction::kContextOffset)); ++ __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); ++ __ mov(Operand(eax, Context::SlotOffset(Context::QML_GLOBAL_INDEX)), ebx); ++ + // Initialize the rest of the slots to undefined. + __ mov(ebx, factory->undefined_value()); + for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { +diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc +index 5d153a8..0ddcde2 100644 +--- a/src/ia32/full-codegen-ia32.cc ++++ b/src/ia32/full-codegen-ia32.cc +@@ -142,12 +142,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { + + // Possibly allocate a local context. + int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; +- if (heap_slots > 0) { ++ if (heap_slots > 0 || ++ (scope()->is_qml_mode() && scope()->is_global_scope())) { + Comment cmnt(masm_, "[ Allocate local context"); + // Argument to NewContext is the function, which is still in edi. + __ push(edi); + if (heap_slots <= FastNewContextStub::kMaximumSlots) { +- FastNewContextStub stub(heap_slots); ++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); + __ CallStub(&stub); + } else { + __ CallRuntime(Runtime::kNewContext, 1); +@@ -1107,10 +1108,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( + + // All extension objects were empty and it is safe to use a global + // load IC call. +- __ mov(eax, GlobalObjectOperand()); ++ __ mov(eax, slot->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + __ mov(ecx, slot->var()->name()); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); +- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) ++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global()) + ? RelocInfo::CODE_TARGET + : RelocInfo::CODE_TARGET_CONTEXT; + EmitCallIC(ic, mode); +@@ -1214,10 +1215,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) { + Comment cmnt(masm_, "Global variable"); + // Use inline caching. Variable name is passed in ecx and the global + // object on the stack. +- __ mov(eax, GlobalObjectOperand()); ++ __ mov(eax, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + __ mov(ecx, var->name()); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); +- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); ++ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); + context()->Plug(eax); + + } else if (slot != NULL && slot->type() == Slot::LOOKUP) { +@@ -1837,11 +1838,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, + // assignment. Right-hand-side value is passed in eax, variable name in + // ecx, and the global object on the stack. + __ mov(ecx, var->name()); +- __ mov(edx, GlobalObjectOperand()); ++ __ mov(edx, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + Handle<Code> ic = is_strict_mode() + ? isolate()->builtins()->StoreIC_Initialize_Strict() + : isolate()->builtins()->StoreIC_Initialize(); +- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); ++ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); + + } else if (op == Token::INIT_CONST) { + // Like var declarations, const declarations are hoisted to function +@@ -2113,9 +2114,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + // Push the strict mode flag. + __ push(Immediate(Smi::FromInt(strict_mode_flag()))); + ++ // Push the qml mode flag ++ __ push(Immediate(Smi::FromInt(is_qml_mode()))); ++ + __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP + ? Runtime::kResolvePossiblyDirectEvalNoLookup +- : Runtime::kResolvePossiblyDirectEval, 4); ++ : Runtime::kResolvePossiblyDirectEval, 5); + } + + +@@ -2188,8 +2192,8 @@ void FullCodeGenerator::VisitCall(Call* expr) { + context()->DropAndPlug(1, eax); + } else if (var != NULL && !var->is_this() && var->is_global()) { + // Push global object as receiver for the call IC. +- __ push(GlobalObjectOperand()); +- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); ++ __ push(var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); ++ EmitCallWithIC(expr, var->name(), var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); + } else if (var != NULL && var->AsSlot() != NULL && + var->AsSlot()->type() == Slot::LOOKUP) { + // Call to a lookup slot (dynamically introduced variable). +diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc +index 0f96f78..c1da075 100644 +--- a/src/ia32/lithium-codegen-ia32.cc ++++ b/src/ia32/lithium-codegen-ia32.cc +@@ -159,12 +159,13 @@ bool LCodeGen::GeneratePrologue() { + + // Possibly allocate a local context. + int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; +- if (heap_slots > 0) { ++ if (heap_slots > 0 || ++ (scope()->is_qml_mode() && scope()->is_global_scope())) { + Comment(";;; Allocate local context"); + // Argument to NewContext is the function, which is still in edi. + __ push(edi); + if (heap_slots <= FastNewContextStub::kMaximumSlots) { +- FastNewContextStub stub(heap_slots); ++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); + __ CallStub(&stub); + } else { + __ CallRuntime(Runtime::kNewContext, 1); +@@ -2525,7 +2526,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { + void LCodeGen::DoGlobalObject(LGlobalObject* instr) { + Register context = ToRegister(instr->context()); + Register result = ToRegister(instr->result()); +- __ mov(result, Operand(context, Context::SlotOffset(Context::GLOBAL_INDEX))); ++ __ mov(result, Operand(context, Context::SlotOffset(instr->qml_global()?Context::QML_GLOBAL_INDEX:Context::GLOBAL_INDEX))); + } + + +diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc +index 9ccd189..8e98b73 100644 +--- a/src/ia32/lithium-ia32.cc ++++ b/src/ia32/lithium-ia32.cc +@@ -1205,7 +1205,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { + + LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { + LOperand* context = UseRegisterAtStart(instr->value()); +- return DefineAsRegister(new LGlobalObject(context)); ++ return DefineAsRegister(new LGlobalObject(context, instr->qml_global())); + } + + +diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h +index 9ace8f8..95ed001 100644 +--- a/src/ia32/lithium-ia32.h ++++ b/src/ia32/lithium-ia32.h +@@ -1416,13 +1416,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { + + class LGlobalObject: public LTemplateInstruction<1, 1, 0> { + public: +- explicit LGlobalObject(LOperand* context) { ++ explicit LGlobalObject(LOperand* context, bool qml_global) { + inputs_[0] = context; ++ qml_global_ = qml_global; + } + + DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object") + + LOperand* context() { return InputAt(0); } ++ bool qml_global() { return qml_global_; } ++ private: ++ bool qml_global_; + }; + + +diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h +index b986264..f8479ae 100644 +--- a/src/ia32/macro-assembler-ia32.h ++++ b/src/ia32/macro-assembler-ia32.h +@@ -778,6 +778,11 @@ static inline Operand GlobalObjectOperand() { + } + + ++static inline Operand QmlGlobalObjectOperand() { ++ return ContextOperand(esi, Context::QML_GLOBAL_INDEX); ++} ++ ++ + // Generates an Operand for saving parameters after PrepareCallApiFunction. + Operand ApiParameterOperand(int index); + +diff --git a/src/objects-inl.h b/src/objects-inl.h +index 231b835..1c7f83e 100644 +--- a/src/objects-inl.h ++++ b/src/objects-inl.h +@@ -3242,6 +3242,18 @@ void SharedFunctionInfo::set_strict_mode(bool value) { + } + + ++bool SharedFunctionInfo::qml_mode() { ++ return BooleanBit::get(compiler_hints(), kQmlModeFunction); ++} ++ ++ ++void SharedFunctionInfo::set_qml_mode(bool value) { ++ set_compiler_hints(BooleanBit::set(compiler_hints(), ++ kQmlModeFunction, ++ value)); ++} ++ ++ + ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset) + ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset) + +diff --git a/src/objects.h b/src/objects.h +index 1bdb5c7..edbc47a 100644 +--- a/src/objects.h ++++ b/src/objects.h +@@ -4331,6 +4331,10 @@ class SharedFunctionInfo: public HeapObject { + inline bool strict_mode(); + inline void set_strict_mode(bool value); + ++ // Indicates whether the function is a qml mode function ++ inline bool qml_mode(); ++ inline void set_qml_mode(bool value); ++ + // Indicates whether or not the code in the shared function support + // deoptimization. + inline bool has_deoptimization_support(); +@@ -4511,6 +4515,7 @@ class SharedFunctionInfo: public HeapObject { + static const int kCodeAgeMask = 0x7; + static const int kOptimizationDisabled = 6; + static const int kStrictModeFunction = 7; ++ static const int kQmlModeFunction = 8; + + private: + #if V8_HOST_ARCH_32_BIT +diff --git a/src/parser.cc b/src/parser.cc +index a84ec6f..7f5c361 100644 +--- a/src/parser.cc ++++ b/src/parser.cc +@@ -593,7 +593,8 @@ Parser::Parser(Handle<Script> script, + + FunctionLiteral* Parser::ParseProgram(Handle<String> source, + bool in_global_context, +- StrictModeFlag strict_mode) { ++ StrictModeFlag strict_mode, ++ bool qml_mode) { + CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); + + HistogramTimerScope timer(isolate()->counters()->parse()); +@@ -609,11 +610,11 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, + ExternalTwoByteStringUC16CharacterStream stream( + Handle<ExternalTwoByteString>::cast(source), 0, source->length()); + scanner_.Initialize(&stream); +- return DoParseProgram(source, in_global_context, strict_mode, &zone_scope); ++ return DoParseProgram(source, in_global_context, strict_mode, qml_mode, &zone_scope); + } else { + GenericStringUC16CharacterStream stream(source, 0, source->length()); + scanner_.Initialize(&stream); +- return DoParseProgram(source, in_global_context, strict_mode, &zone_scope); ++ return DoParseProgram(source, in_global_context, strict_mode, qml_mode, &zone_scope); + } + } + +@@ -621,6 +622,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, + FunctionLiteral* Parser::DoParseProgram(Handle<String> source, + bool in_global_context, + StrictModeFlag strict_mode, ++ bool qml_mode, + ZoneScope* zone_scope) { + ASSERT(target_stack_ == NULL); + if (pre_data_ != NULL) pre_data_->Initialize(); +@@ -641,6 +643,9 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, + if (strict_mode == kStrictMode) { + top_scope_->EnableStrictMode(); + } ++ if (qml_mode) { ++ scope->EnableQmlMode(); ++ } + ZoneList<Statement*>* body = new ZoneList<Statement*>(16); + bool ok = true; + int beg_loc = scanner().location().beg_pos; +@@ -729,6 +734,9 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, + if (shared_info->strict_mode()) { + top_scope_->EnableStrictMode(); + } ++ if (shared_info->qml_mode()) { ++ top_scope_->EnableQmlMode(); ++ } + + FunctionLiteralType type = + shared_info->is_expression() ? EXPRESSION : DECLARATION; +@@ -1661,6 +1669,11 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, + arguments->Add(value); + value = NULL; // zap the value to avoid the unnecessary assignment + ++ int qml_mode = 0; ++ if (top_scope_->is_qml_mode() && !Isolate::Current()->global()->HasProperty(*name)) ++ qml_mode = 1; ++ arguments->Add(NewNumberLiteral(qml_mode)); ++ + // Construct the call to Runtime_InitializeConstGlobal + // and add it to the initialization statement block. + // Note that the function does different things depending on +@@ -1676,6 +1689,11 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, + arguments->Add(NewNumberLiteral( + top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode)); + ++ int qml_mode = 0; ++ if (top_scope_->is_qml_mode() && !Isolate::Current()->global()->HasProperty(*name)) ++ qml_mode = 1; ++ arguments->Add(NewNumberLiteral(qml_mode)); ++ + // Be careful not to assign a value to the global variable if + // we're in a with. The initialization value should not + // necessarily be stored in the global object in that case, +@@ -5157,7 +5175,8 @@ bool ParserApi::Parse(CompilationInfo* info) { + Handle<String> source = Handle<String>(String::cast(script->source())); + result = parser.ParseProgram(source, + info->is_global(), +- info->StrictMode()); ++ info->StrictMode(), ++ info->is_qml_mode()); + } + } + +diff --git a/src/parser.h b/src/parser.h +index 64f1303..4d45e45 100644 +--- a/src/parser.h ++++ b/src/parser.h +@@ -431,7 +431,8 @@ class Parser { + // Returns NULL if parsing failed. + FunctionLiteral* ParseProgram(Handle<String> source, + bool in_global_context, +- StrictModeFlag strict_mode); ++ StrictModeFlag strict_mode, ++ bool qml_mode); + + FunctionLiteral* ParseLazy(CompilationInfo* info); + +@@ -464,6 +465,7 @@ class Parser { + FunctionLiteral* DoParseProgram(Handle<String> source, + bool in_global_context, + StrictModeFlag strict_mode, ++ bool qml_mode, + ZoneScope* zone_scope); + + // Report syntax error +diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc +index c777ab4..1964e02 100644 +--- a/src/prettyprinter.cc ++++ b/src/prettyprinter.cc +@@ -656,6 +656,9 @@ void AstPrinter::PrintLiteralWithModeIndented(const char* info, + EmbeddedVector<char, 256> buf; + int pos = OS::SNPrintF(buf, "%s (mode = %s", info, + Variable::Mode2String(var->mode())); ++ if (var->is_qml_global()) { ++ pos += OS::SNPrintF(buf + pos, ":QML"); ++ } + OS::SNPrintF(buf + pos, ")"); + PrintLiteralIndented(buf.start(), value, true); + } +diff --git a/src/runtime.cc b/src/runtime.cc +index 660352c..c13f92d 100644 +--- a/src/runtime.cc ++++ b/src/runtime.cc +@@ -1065,8 +1065,6 @@ static Failure* ThrowRedeclarationError(Isolate* isolate, + RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + ASSERT(args.length() == 4); + HandleScope scope(isolate); +- Handle<GlobalObject> global = Handle<GlobalObject>( +- isolate->context()->global()); + + Handle<Context> context = args.at<Context>(0); + CONVERT_ARG_CHECKED(FixedArray, pairs, 1); +@@ -1075,6 +1073,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + static_cast<StrictModeFlag>(Smi::cast(args[3])->value()); + ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); + ++ Handle<JSObject> js_global = Handle<JSObject>(isolate->context()->global()); ++ Handle<JSObject> qml_global = Handle<JSObject>(isolate->context()->qml_global()); ++ + // Compute the property attributes. According to ECMA-262, section + // 13, page 71, the property must be read-only and + // non-deletable. However, neither SpiderMonkey nor KJS creates the +@@ -1083,10 +1084,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + + // Traverse the name/value pairs and set the properties. + int length = pairs->length(); +- for (int i = 0; i < length; i += 2) { ++ for (int i = 0; i < length; i += 3) { + HandleScope scope(isolate); + Handle<String> name(String::cast(pairs->get(i))); + Handle<Object> value(pairs->get(i + 1), isolate); ++ Handle<Smi> is_qml_global(Smi::cast(pairs->get(i + 2))); ++ ++ Handle<JSObject> global = is_qml_global->value()?qml_global:js_global; + + // We have to declare a global const property. To capture we only + // assign to it when evaluating the assignment for "const x = +@@ -1316,20 +1320,25 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + NoHandleAllocation nha; + // args[0] == name + // args[1] == strict_mode +- // args[2] == value (optional) ++ // args[2] == qml_mode ++ // args[3] == value (optional) + + // Determine if we need to assign to the variable if it already + // exists (based on the number of arguments). +- RUNTIME_ASSERT(args.length() == 2 || args.length() == 3); +- bool assign = args.length() == 3; ++ RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); ++ bool assign = args.length() == 4; + + CONVERT_ARG_CHECKED(String, name, 0); +- GlobalObject* global = isolate->context()->global(); + RUNTIME_ASSERT(args[1]->IsSmi()); + StrictModeFlag strict_mode = + static_cast<StrictModeFlag>(Smi::cast(args[1])->value()); + ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); + ++ RUNTIME_ASSERT(args[2]->IsSmi()); ++ int qml_mode = Smi::cast(args[2])->value(); ++ ++ JSObject* global = qml_mode?isolate->context()->qml_global():isolate->context()->global(); ++ + // According to ECMA-262, section 12.2, page 62, the property must + // not be deletable. + PropertyAttributes attributes = DONT_DELETE; +@@ -1350,7 +1359,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + if (lookup.IsReadOnly()) { + // If we found readonly property on one of hidden prototypes, + // just shadow it. +- if (real_holder != isolate->context()->global()) break; ++ if (real_holder != global) break; + return ThrowRedeclarationError(isolate, "const", name); + } + +@@ -1372,7 +1381,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + // overwrite it with a variable declaration we must throw a + // re-declaration error. However if we found readonly property + // on one of hidden prototypes, just shadow it. +- if (real_holder != isolate->context()->global()) break; ++ if (real_holder != global) break; + return ThrowRedeclarationError(isolate, "const", name); + } + } +@@ -1384,7 +1393,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + } + + // Assign the value (or undefined) to the property. +- Object* value = (assign) ? args[2] : isolate->heap()->undefined_value(); ++ Object* value = (assign) ? args[3] : isolate->heap()->undefined_value(); + return real_holder->SetProperty( + &lookup, *name, value, attributes, strict_mode); + } +@@ -1399,9 +1408,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + real_holder = JSObject::cast(proto); + } + +- global = isolate->context()->global(); ++ global = qml_mode?isolate->context()->qml_global():isolate->context()->global(); + if (assign) { +- return global->SetProperty(*name, args[2], attributes, strict_mode, true); ++ return global->SetProperty(*name, args[3], attributes, strict_mode, true); + } + return isolate->heap()->undefined_value(); + } +@@ -1411,12 +1420,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { + // All constants are declared with an initial value. The name + // of the constant is the first argument and the initial value + // is the second. +- RUNTIME_ASSERT(args.length() == 2); ++ RUNTIME_ASSERT(args.length() == 3); + CONVERT_ARG_CHECKED(String, name, 0); + Handle<Object> value = args.at<Object>(1); + ++ RUNTIME_ASSERT(args[2]->IsSmi()); ++ int qml_mode = Smi::cast(args[2])->value(); ++ + // Get the current global object from top. +- GlobalObject* global = isolate->context()->global(); ++ JSObject* global = qml_mode?isolate->context()->qml_global():isolate->context()->global(); + + // According to ECMA-262, section 12.2, page 62, the property must + // not be deletable. Since it's a const, it must be READ_ONLY too. +@@ -1456,7 +1468,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { + // with setting the value because the property is either absent or + // read-only. We also have to do redo the lookup. + HandleScope handle_scope(isolate); +- Handle<GlobalObject> global(isolate->context()->global()); ++ Handle<JSObject> global(qml_mode?isolate->context()->qml_global():isolate->context()->global()); + + // BUG 1213575: Handle the case where we have to set a read-only + // property through an interceptor and only do it if it's +@@ -8160,7 +8172,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) { + Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source, + context, + true, +- kNonStrictMode); ++ kNonStrictMode, ++ false); + if (shared.is_null()) return Failure::Exception(); + Handle<JSFunction> fun = + isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, +@@ -8173,14 +8186,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) { + static ObjectPair CompileGlobalEval(Isolate* isolate, + Handle<String> source, + Handle<Object> receiver, +- StrictModeFlag strict_mode) { ++ StrictModeFlag strict_mode, ++ bool qml_mode) { + // Deal with a normal eval call with a string argument. Compile it + // and return the compiled function bound in the local context. + Handle<SharedFunctionInfo> shared = Compiler::CompileEval( + source, + Handle<Context>(isolate->context()), + isolate->context()->IsGlobalContext(), +- strict_mode); ++ strict_mode, ++ qml_mode); + if (shared.is_null()) return MakePair(Failure::Exception(), NULL); + Handle<JSFunction> compiled = + isolate->factory()->NewFunctionFromSharedFunctionInfo( +@@ -8190,7 +8205,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate, + + + RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { +- ASSERT(args.length() == 4); ++ ASSERT(args.length() == 5); + + HandleScope scope(isolate); + Handle<Object> callee = args.at<Object>(0); +@@ -8257,16 +8272,18 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { + } + + ASSERT(args[3]->IsSmi()); ++ ASSERT(args[4]->IsSmi()); + return CompileGlobalEval(isolate, + args.at<String>(1), + args.at<Object>(2), + static_cast<StrictModeFlag>( +- Smi::cast(args[3])->value())); ++ Smi::cast(args[3])->value()), ++ Smi::cast(args[4])->value()); + } + + + RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { +- ASSERT(args.length() == 4); ++ ASSERT(args.length() == 5); + + HandleScope scope(isolate); + Handle<Object> callee = args.at<Object>(0); +@@ -8280,11 +8297,13 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { + } + + ASSERT(args[3]->IsSmi()); ++ ASSERT(args[4]->IsSmi()); + return CompileGlobalEval(isolate, + args.at<String>(1), + args.at<Object>(2), + static_cast<StrictModeFlag>( +- Smi::cast(args[3])->value())); ++ Smi::cast(args[3])->value()), ++ Smi::cast(args[4])->value()); + } + + +@@ -10570,6 +10589,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. +@@ -10633,7 +10653,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); +@@ -10656,7 +10677,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { + Handle<Object>::cast(source).location() }; + Handle<Object> result = + Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver, +- argc, argv, &has_pending_exception); ++ argc, argv, &has_pending_exception, ++ Handle<Object>(function->context()->qml_global())); + if (has_pending_exception) return Failure::Exception(); + + // Skip the global proxy as it has no properties and always delegates to the +@@ -10722,7 +10744,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) { + // Currently, the eval code will be executed in non-strict mode, + // even in the strict code context. + Handle<SharedFunctionInfo> shared = +- Compiler::CompileEval(source, context, is_global, kNonStrictMode); ++ Compiler::CompileEval(source, context, is_global, kNonStrictMode, false); + if (shared.is_null()) return Failure::Exception(); + Handle<JSFunction> compiled_function = + Handle<JSFunction>( +diff --git a/src/runtime.h b/src/runtime.h +index bf1ba68..5e97173 100644 +--- a/src/runtime.h ++++ b/src/runtime.h +@@ -241,8 +241,8 @@ namespace internal { + \ + /* Eval */ \ + F(GlobalReceiver, 1, 1) \ +- F(ResolvePossiblyDirectEval, 4, 2) \ +- F(ResolvePossiblyDirectEvalNoLookup, 4, 2) \ ++ F(ResolvePossiblyDirectEval, 5, 2) \ ++ F(ResolvePossiblyDirectEvalNoLookup, 5, 2) \ + \ + F(SetProperty, -1 /* 4 or 5 */, 1) \ + F(DefineOrRedefineDataProperty, 4, 1) \ +@@ -296,8 +296,8 @@ namespace internal { + /* Declarations and initialization */ \ + F(DeclareGlobals, 4, 1) \ + F(DeclareContextSlot, 4, 1) \ +- F(InitializeVarGlobal, -1 /* 2 or 3 */, 1) \ +- F(InitializeConstGlobal, 2, 1) \ ++ F(InitializeVarGlobal, -1 /* 3 or 4 */, 1) \ ++ F(InitializeConstGlobal, 3, 1) \ + F(InitializeConstContextSlot, 3, 1) \ + F(OptimizeObjectForAddingMultipleProperties, 2, 1) \ + \ +diff --git a/src/scopes.cc b/src/scopes.cc +index 8df93c5..b5d7ff3 100644 +--- a/src/scopes.cc ++++ b/src/scopes.cc +@@ -198,6 +198,7 @@ void Scope::SetDefaults(Type type, + scope_calls_eval_ = false; + // Inherit the strict mode from the parent scope. + strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; ++ qml_mode_ = (outer_scope != NULL) && outer_scope->qml_mode_; + outer_scope_calls_eval_ = false; + inner_scope_calls_eval_ = false; + outer_scope_is_eval_scope_ = false; +@@ -796,6 +797,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. +@@ -817,6 +837,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); + } +@@ -827,6 +866,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 a0e56a4..6dd3f65 100644 +--- a/src/scopes.h ++++ b/src/scopes.h +@@ -210,6 +210,11 @@ class Scope: public ZoneObject { + strict_mode_ = FLAG_strict_mode; + } + ++ // Enable qml mode for this scope ++ void EnableQmlMode() { ++ qml_mode_ = true; ++ } ++ + // --------------------------------------------------------------------------- + // Predicates. + +@@ -218,6 +223,7 @@ class Scope: public ZoneObject { + bool is_function_scope() const { return type_ == FUNCTION_SCOPE; } + bool is_global_scope() const { return type_ == GLOBAL_SCOPE; } + bool is_strict_mode() const { return strict_mode_; } ++ bool is_qml_mode() const { return qml_mode_; } + + // Information about which scopes calls eval. + bool calls_eval() const { return scope_calls_eval_; } +@@ -376,6 +382,7 @@ class Scope: public ZoneObject { + bool scope_contains_with_; // this scope contains a 'with' statement + bool scope_calls_eval_; // this scope contains an 'eval' call + bool strict_mode_; // this scope is a strict mode scope ++ bool qml_mode_; // this scope is a qml mode scope + + // Computed via PropagateScopeInfo. + bool outer_scope_calls_eval_; +diff --git a/src/variables.cc b/src/variables.cc +index 0502722..190baf6 100644 +--- a/src/variables.cc ++++ b/src/variables.cc +@@ -99,7 +99,8 @@ Variable::Variable(Scope* scope, + rewrite_(NULL), + is_valid_LHS_(is_valid_LHS), + is_accessed_from_inner_scope_(false), +- is_used_(false) { ++ is_used_(false), ++ is_qml_global_(false) { + // names must be canonicalized for fast equality checks + ASSERT(name->IsSymbol()); + } +diff --git a/src/variables.h b/src/variables.h +index b1ff0db..0b31d1a 100644 +--- a/src/variables.h ++++ b/src/variables.h +@@ -141,6 +141,8 @@ class Variable: public ZoneObject { + Expression* rewrite() const { return rewrite_; } + void set_rewrite(Expression* expr) { rewrite_ = expr; } + ++ bool is_qml_global() const { return is_qml_global_; } ++ void set_is_qml_global(bool is_qml_global) { is_qml_global_ = is_qml_global; } + private: + Scope* scope_; + Handle<String> name_; +@@ -159,6 +161,9 @@ class Variable: public ZoneObject { + // Usage info. + bool is_accessed_from_inner_scope_; // set by variable resolver + bool is_used_; ++ ++ // QML info ++ bool is_qml_global_; + }; + + +diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc +index c365385..d923494 100644 +--- a/src/x64/code-stubs-x64.cc ++++ b/src/x64/code-stubs-x64.cc +@@ -140,6 +140,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { + __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); + __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx); + ++ // Copy the qml global object from the surrounding context. ++ __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); ++ __ movq(Operand(rax, Context::SlotOffset(Context::QML_GLOBAL_INDEX)), rbx); ++ + // Initialize the rest of the slots to undefined. + __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); + for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { +diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc +index 97168cd..c45cdb6 100644 +--- a/src/x64/full-codegen-x64.cc ++++ b/src/x64/full-codegen-x64.cc +@@ -141,12 +141,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { + + // Possibly allocate a local context. + int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; +- if (heap_slots > 0) { ++ if (heap_slots > 0 || ++ (scope()->is_qml_mode() && scope()->is_global_scope())) { + Comment cmnt(masm_, "[ Allocate local context"); + // Argument to NewContext is the function, which is still in rdi. + __ push(rdi); + if (heap_slots <= FastNewContextStub::kMaximumSlots) { +- FastNewContextStub stub(heap_slots); ++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); + __ CallStub(&stub); + } else { + __ CallRuntime(Runtime::kNewContext, 1); +@@ -1119,10 +1120,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( + + // All extension objects were empty and it is safe to use a global + // load IC call. +- __ movq(rax, GlobalObjectOperand()); ++ __ movq(rax, slot->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + __ Move(rcx, slot->var()->name()); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); +- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) ++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global()) + ? RelocInfo::CODE_TARGET + : RelocInfo::CODE_TARGET_CONTEXT; + EmitCallIC(ic, mode); +@@ -1227,9 +1228,9 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) { + // Use inline caching. Variable name is passed in rcx and the global + // object on the stack. + __ Move(rcx, var->name()); +- __ movq(rax, GlobalObjectOperand()); ++ __ movq(rax, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); +- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); ++ EmitCallIC(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); + context()->Plug(rax); + + } else if (slot != NULL && slot->type() == Slot::LOOKUP) { +@@ -1806,11 +1807,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, + // assignment. Right-hand-side value is passed in rax, variable name in + // rcx, and the global object on the stack. + __ Move(rcx, var->name()); +- __ movq(rdx, GlobalObjectOperand()); ++ __ movq(rdx, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + Handle<Code> ic = is_strict_mode() + ? isolate()->builtins()->StoreIC_Initialize_Strict() + : isolate()->builtins()->StoreIC_Initialize(); +- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); ++ EmitCallIC(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); + + } else if (op == Token::INIT_CONST) { + // Like var declarations, const declarations are hoisted to function +@@ -2085,9 +2086,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + // Push the strict mode flag. + __ Push(Smi::FromInt(strict_mode_flag())); + ++ // Push the qml mode flag ++ __ Push(Smi::FromInt(is_qml_mode())); ++ + __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP + ? Runtime::kResolvePossiblyDirectEvalNoLookup +- : Runtime::kResolvePossiblyDirectEval, 4); ++ : Runtime::kResolvePossiblyDirectEval, 5); + } + + +@@ -2160,8 +2164,8 @@ void FullCodeGenerator::VisitCall(Call* expr) { + } else if (var != NULL && !var->is_this() && var->is_global()) { + // Call to a global variable. + // Push global object as receiver for the call IC lookup. +- __ push(GlobalObjectOperand()); +- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); ++ __ push(var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); ++ EmitCallWithIC(expr, var->name(), var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); + } else if (var != NULL && var->AsSlot() != NULL && + var->AsSlot()->type() == Slot::LOOKUP) { + // Call to a lookup slot (dynamically introduced variable). +diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc +index 202e7a2..45acbdf 100644 +--- a/src/x64/lithium-codegen-x64.cc ++++ b/src/x64/lithium-codegen-x64.cc +@@ -174,12 +174,13 @@ bool LCodeGen::GeneratePrologue() { + + // Possibly allocate a local context. + int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; +- if (heap_slots > 0) { ++ if (heap_slots > 0 || ++ (scope()->is_qml_mode() && scope()->is_global_scope())) { + Comment(";;; Allocate local context"); + // Argument to NewContext is the function, which is still in rdi. + __ push(rdi); + if (heap_slots <= FastNewContextStub::kMaximumSlots) { +- FastNewContextStub stub(heap_slots); ++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); + __ CallStub(&stub); + } else { + __ CallRuntime(Runtime::kNewContext, 1); +@@ -2540,7 +2541,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { + + void LCodeGen::DoGlobalObject(LGlobalObject* instr) { + Register result = ToRegister(instr->result()); +- __ movq(result, GlobalObjectOperand()); ++ __ movq(result, instr->qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + } + + +diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc +index 07ca3a5..00feeac 100644 +--- a/src/x64/lithium-x64.cc ++++ b/src/x64/lithium-x64.cc +@@ -1194,7 +1194,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { + + + LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { +- return DefineAsRegister(new LGlobalObject); ++ return DefineAsRegister(new LGlobalObject(instr->qml_global())); + } + + +diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h +index 15bb894..16f754c 100644 +--- a/src/x64/lithium-x64.h ++++ b/src/x64/lithium-x64.h +@@ -1365,7 +1365,13 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { + + class LGlobalObject: public LTemplateInstruction<1, 0, 0> { + public: ++ explicit LGlobalObject(bool qml_global) : qml_global_(qml_global) {} ++ + DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object") ++ ++ bool qml_global() { return qml_global_; } ++ private: ++ bool qml_global_; + }; + + +diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h +index 4c17720..aa284ed 100644 +--- a/src/x64/macro-assembler-x64.h ++++ b/src/x64/macro-assembler-x64.h +@@ -1233,6 +1233,11 @@ static inline Operand GlobalObjectOperand() { + } + + ++static inline Operand QmlGlobalObjectOperand() { ++ return ContextOperand(rsi, Context::QML_GLOBAL_INDEX); ++} ++ ++ + // Provides access to exit frame stack space (not GCed). + static inline Operand StackSpaceOperand(int index) { + #ifdef _WIN64 +-- +1.7.4.4 + |