diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2011-10-27 13:34:16 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-01-05 12:18:10 +0100 |
commit | 2fe857938c3d1683df88133582bc3e7736264b10 (patch) | |
tree | 1ec9903bd86ffe2d264dcc52a658ebdb0474714e /src/3rdparty/v8 | |
parent | e5ba7458fc5418e688de9cf294f5eb96cd6c4510 (diff) | |
download | qtjsbackend-2fe857938c3d1683df88133582bc3e7736264b10.tar.gz |
[V8] 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 resolved 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.
Change-Id: I4950562d455074578c372d8e0e3089887b06e0a1
Diffstat (limited to 'src/3rdparty/v8')
52 files changed, 559 insertions, 141 deletions
diff --git a/src/3rdparty/v8/include/v8.h b/src/3rdparty/v8/include/v8.h index 3ef4dd6..193e2fe 100644 --- a/src/3rdparty/v8/include/v8.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/api.cc b/src/3rdparty/v8/src/api.cc index 7d54252..2d3d97a 100644 --- a/src/3rdparty/v8/src/api.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/arm/code-stubs-arm.cc b/src/3rdparty/v8/src/arm/code-stubs-arm.cc index cb3bc88..f5be938 100644 --- a/src/3rdparty/v8/src/arm/code-stubs-arm.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/arm/full-codegen-arm.cc b/src/3rdparty/v8/src/arm/full-codegen-arm.cc index 497a295..b8e3f30 100644 --- a/src/3rdparty/v8/src/arm/full-codegen-arm.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/arm/lithium-arm.cc b/src/3rdparty/v8/src/arm/lithium-arm.cc index 5197842..943bc82 100644 --- a/src/3rdparty/v8/src/arm/lithium-arm.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/arm/lithium-arm.h b/src/3rdparty/v8/src/arm/lithium-arm.h index 5733bd0..a7e1704 100644 --- a/src/3rdparty/v8/src/arm/lithium-arm.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/arm/lithium-codegen-arm.cc b/src/3rdparty/v8/src/arm/lithium-codegen-arm.cc index 4cf7df4..2e1e6fa 100644 --- a/src/3rdparty/v8/src/arm/lithium-codegen-arm.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/arm/macro-assembler-arm.h b/src/3rdparty/v8/src/arm/macro-assembler-arm.h index 90c4b37..5947e6a 100644 --- a/src/3rdparty/v8/src/arm/macro-assembler-arm.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/ast-inl.h b/src/3rdparty/v8/src/ast-inl.h index f8b460d..217c71f 100644 --- a/src/3rdparty/v8/src/ast-inl.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/ast.cc b/src/3rdparty/v8/src/ast.cc index 9e34bc0..0dc3c1c 100644 --- a/src/3rdparty/v8/src/ast.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/ast.h b/src/3rdparty/v8/src/ast.h index 3de00ef..8920b50 100644 --- a/src/3rdparty/v8/src/ast.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/code-stubs.h b/src/3rdparty/v8/src/code-stubs.h index fc7000b..4380764 100644 --- a/src/3rdparty/v8/src/code-stubs.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/compiler.cc b/src/3rdparty/v8/src/compiler.cc index 88db467..4902e72 100644 --- a/src/3rdparty/v8/src/compiler.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/compiler.h b/src/3rdparty/v8/src/compiler.h index bedf5ee..054e3b9 100644 --- a/src/3rdparty/v8/src/compiler.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/contexts.cc b/src/3rdparty/v8/src/contexts.cc index b25ffac..3129af0 100644 --- a/src/3rdparty/v8/src/contexts.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/contexts.h b/src/3rdparty/v8/src/contexts.h index 7021ff8..c3cfeee 100644 --- a/src/3rdparty/v8/src/contexts.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/execution.cc b/src/3rdparty/v8/src/execution.cc index 29955fa..4261ac2 100644 --- a/src/3rdparty/v8/src/execution.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/execution.h b/src/3rdparty/v8/src/execution.h index f2d17d0..532e5d8 100644 --- a/src/3rdparty/v8/src/execution.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/full-codegen.cc b/src/3rdparty/v8/src/full-codegen.cc index 27c509f..f099d25 100644 --- a/src/3rdparty/v8/src/full-codegen.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/full-codegen.h b/src/3rdparty/v8/src/full-codegen.h index 9132502..78e6089 100644 --- a/src/3rdparty/v8/src/full-codegen.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/heap.cc b/src/3rdparty/v8/src/heap.cc index 53a0f27..881a876 100644 --- a/src/3rdparty/v8/src/heap.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/hydrogen-instructions.cc b/src/3rdparty/v8/src/hydrogen-instructions.cc index 6f46509..ac9728c 100644 --- a/src/3rdparty/v8/src/hydrogen-instructions.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/hydrogen-instructions.h b/src/3rdparty/v8/src/hydrogen-instructions.h index 65fc4df..ebf0030 100644 --- a/src/3rdparty/v8/src/hydrogen-instructions.h +++ b/src/3rdparty/v8/src/hydrogen-instructions.h @@ -1410,19 +1410,30 @@ 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; } + virtual bool DataEquals(HValue* other) { + HGlobalObject* o = HGlobalObject::cast(other); + return o->qml_global_ == qml_global_; + } + + private: + bool qml_global_; }; @@ -1601,7 +1612,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 +1624,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/3rdparty/v8/src/hydrogen.cc b/src/3rdparty/v8/src/hydrogen.cc index 3a4d172..0a7fad1 100644 --- a/src/3rdparty/v8/src/hydrogen.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/ia32/code-stubs-ia32.cc b/src/3rdparty/v8/src/ia32/code-stubs-ia32.cc index 37b519a..8a94a06 100644 --- a/src/3rdparty/v8/src/ia32/code-stubs-ia32.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/ia32/full-codegen-ia32.cc b/src/3rdparty/v8/src/ia32/full-codegen-ia32.cc index 25588c8..9cee4a3 100644 --- a/src/3rdparty/v8/src/ia32/full-codegen-ia32.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/ia32/lithium-codegen-ia32.cc b/src/3rdparty/v8/src/ia32/lithium-codegen-ia32.cc index d4cbbce..b381227 100644 --- a/src/3rdparty/v8/src/ia32/lithium-codegen-ia32.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/ia32/lithium-ia32.cc b/src/3rdparty/v8/src/ia32/lithium-ia32.cc index 626f899..d09d55f 100644 --- a/src/3rdparty/v8/src/ia32/lithium-ia32.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/ia32/lithium-ia32.h b/src/3rdparty/v8/src/ia32/lithium-ia32.h index 5f23afa..22541c8 100644 --- a/src/3rdparty/v8/src/ia32/lithium-ia32.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/ia32/macro-assembler-ia32.h b/src/3rdparty/v8/src/ia32/macro-assembler-ia32.h index 8528c55..de3c3a0 100644 --- a/src/3rdparty/v8/src/ia32/macro-assembler-ia32.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/mips/code-stubs-mips.cc b/src/3rdparty/v8/src/mips/code-stubs-mips.cc index 85e929d..a534b78 100644 --- a/src/3rdparty/v8/src/mips/code-stubs-mips.cc +++ b/src/3rdparty/v8/src/mips/code-stubs-mips.cc @@ -173,6 +173,11 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { __ lw(a1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); __ sw(a1, MemOperand(v0, Context::SlotOffset(Context::GLOBAL_INDEX))); + // Copy the qml global object from the surrounding context. + __ lw(a1, MemOperand(cp, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); + __ sw(a1, MemOperand(v0, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); + + // Initialize the rest of the slots to undefined. __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { diff --git a/src/3rdparty/v8/src/mips/full-codegen-mips.cc b/src/3rdparty/v8/src/mips/full-codegen-mips.cc index 2f989bc..b6bd407 100644 --- a/src/3rdparty/v8/src/mips/full-codegen-mips.cc +++ b/src/3rdparty/v8/src/mips/full-codegen-mips.cc @@ -191,12 +191,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 a1. __ push(a1); if (heap_slots <= FastNewContextStub::kMaximumSlots) { - FastNewContextStub stub(heap_slots); + FastNewContextStub stub((heap_slots < 0)?0:heap_slots); __ CallStub(&stub); } else { __ CallRuntime(Runtime::kNewFunctionContext, 1); @@ -1199,9 +1200,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, __ bind(&fast); } - __ lw(a0, GlobalObjectOperand()); + __ lw(a0, var->is_qml_global() ? QmlGlobalObjectOperand():GlobalObjectOperand()); __ li(a2, 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(); @@ -1286,10 +1287,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { Comment cmnt(masm_, "Global variable"); // Use inline caching. Variable name is passed in a2 and the global // object (receiver) in a0. - __ lw(a0, GlobalObjectOperand()); + __ lw(a0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); __ li(a2, 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(v0); break; } @@ -1937,7 +1938,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, // Global var, const, or let. __ mov(a0, result_register()); __ li(a2, Operand(var->name())); - __ lw(a1, GlobalObjectOperand()); + __ lw(a1, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); Handle<Code> ic = is_strict_mode() ? isolate()->builtins()->StoreIC_Initialize_Strict() : isolate()->builtins()->StoreIC_Initialize(); @@ -2246,9 +2247,14 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, __ li(a1, Operand(Smi::FromInt(strict_mode))); __ push(a1); + + // Push the qml mode flag. + __ li(a1, Operand(Smi::FromInt(is_qml_mode()))); + __ push(a1); + __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP ? Runtime::kResolvePossiblyDirectEvalNoLookup - : Runtime::kResolvePossiblyDirectEval, 4); + : Runtime::kResolvePossiblyDirectEval, 5); } @@ -2320,9 +2326,9 @@ void FullCodeGenerator::VisitCall(Call* expr) { context()->DropAndPlug(1, v0); } else if (proxy != NULL && proxy->var()->IsUnallocated()) { // Push global object as receiver for the call IC. - __ lw(a0, GlobalObjectOperand()); + __ lw(a0, proxy->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); __ push(a0); - 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; @@ -3743,7 +3749,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { // but "delete this" is allowed. ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); if (var->IsUnallocated()) { - __ lw(a2, GlobalObjectOperand()); + __ lw(a2, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); __ li(a1, Operand(var->name())); __ li(a0, Operand(Smi::FromInt(kNonStrictMode))); __ Push(a2, a1, a0); @@ -4032,7 +4038,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { VariableProxy* proxy = expr->AsVariableProxy(); if (proxy != NULL && proxy->var()->IsUnallocated()) { Comment cmnt(masm_, "Global variable"); - __ lw(a0, GlobalObjectOperand()); + __ lw(a0, proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); __ li(a2, 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/3rdparty/v8/src/mips/macro-assembler-mips.h b/src/3rdparty/v8/src/mips/macro-assembler-mips.h index 84c55f7..5224db9 100644 --- a/src/3rdparty/v8/src/mips/macro-assembler-mips.h +++ b/src/3rdparty/v8/src/mips/macro-assembler-mips.h @@ -112,6 +112,11 @@ static inline MemOperand GlobalObjectOperand() { } +static inline MemOperand QmlGlobalObjectOperand() { + return ContextOperand(cp, Context::QML_GLOBAL_INDEX); +} + + // Generate a MemOperand for loading a field from an object. static inline MemOperand FieldMemOperand(Register object, int offset) { return MemOperand(object, offset - kHeapObjectTag); diff --git a/src/3rdparty/v8/src/objects-inl.h b/src/3rdparty/v8/src/objects-inl.h index 6a80c9c..2e83fb7 100644 --- a/src/3rdparty/v8/src/objects-inl.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/objects.h b/src/3rdparty/v8/src/objects.h index c38d461..b71eaac 100644 --- a/src/3rdparty/v8/src/objects.h +++ b/src/3rdparty/v8/src/objects.h @@ -3120,6 +3120,9 @@ class SerializedScopeInfo : public FixedArray { // Is this scope a strict mode scope? bool IsStrictMode(); + // Is this scope a qml mode scope? + bool IsQmlMode(); + // Return the number of stack slots for code. int NumberOfStackSlots(); @@ -4929,6 +4932,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 +5156,7 @@ class SharedFunctionInfo: public HeapObject { kCodeAgeShift, kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize, kStrictModeFunction, + kQmlModeFunction, kUsesArguments, kHasDuplicateParameters, kNative, diff --git a/src/3rdparty/v8/src/parser.cc b/src/3rdparty/v8/src/parser.cc index 37204c9..357d340 100644 --- a/src/3rdparty/v8/src/parser.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/parser.h b/src/3rdparty/v8/src/parser.h index eaae6f7..a60951d 100644 --- a/src/3rdparty/v8/src/parser.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/prettyprinter.cc b/src/3rdparty/v8/src/prettyprinter.cc index 37c76ce..73812fd 100644 --- a/src/3rdparty/v8/src/prettyprinter.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/runtime.cc b/src/3rdparty/v8/src/runtime.cc index 0e256c1..b64e66b 100644 --- a/src/3rdparty/v8/src/runtime.cc +++ b/src/3rdparty/v8/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()); } @@ -11220,10 +11239,12 @@ class ScopeIterator { ZoneScope zone_scope(isolate, DELETE_ON_EXIT); Handle<Script> script(Script::cast(shared_info->script())); Scope* scope; - if (index >= 0) { + if (index >= 0 || shared_info->qml_mode()) { // Global code CompilationInfo info(script); info.MarkAsGlobal(); + if (shared_info->qml_mode()) + info.MarkAsQmlMode(); bool result = ParserApi::Parse(&info); ASSERT(result); result = Scope::Analyze(&info); @@ -11253,7 +11274,6 @@ class ScopeIterator { ScopeType scope_type = Type(); if (scope_type == ScopeTypeGlobal) { // The global scope is always the last in the chain. - ASSERT(context_->IsGlobalContext()); context_ = Handle<Context>(); return; } @@ -11277,7 +11297,7 @@ class ScopeIterator { !scope_info->HasContext()); return ScopeTypeLocal; case GLOBAL_SCOPE: - ASSERT(context_->IsGlobalContext()); + ASSERT(context_->IsGlobalContext() || scope_info->IsQmlMode()); return ScopeTypeGlobal; case WITH_SCOPE: ASSERT(context_->IsWithContext()); @@ -11315,10 +11335,15 @@ class ScopeIterator { switch (Type()) { case ScopeIterator::ScopeTypeGlobal: return Handle<JSObject>(CurrentContext()->global()); - case ScopeIterator::ScopeTypeLocal: + case ScopeIterator::ScopeTypeLocal: { + Handle<SerializedScopeInfo> scope_info = nested_scope_chain_.last(); + if (scope_info->IsQmlMode()) + ASSERT(nested_scope_chain_.length() == 2); + else + ASSERT(nested_scope_chain_.length() == 1); // Materialize the content of the local scope into a JSObject. - ASSERT(nested_scope_chain_.length() == 1); return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_); + } case ScopeIterator::ScopeTypeWith: // Return the with object. return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); @@ -12034,6 +12059,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 +12133,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 +12144,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 +12226,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/3rdparty/v8/src/runtime.h b/src/3rdparty/v8/src/runtime.h index 67fc628..aada06d 100644 --- a/src/3rdparty/v8/src/runtime.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/scopeinfo.cc b/src/3rdparty/v8/src/scopeinfo.cc index 8ea5f1e..a61b787 100644 --- a/src/3rdparty/v8/src/scopeinfo.cc +++ b/src/3rdparty/v8/src/scopeinfo.cc @@ -51,6 +51,7 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) : function_name_(FACTORY->empty_symbol()), calls_eval_(scope->calls_eval()), is_strict_mode_(scope->is_strict_mode()), + is_qml_mode_(scope->is_qml_mode()), type_(scope->type()), parameters_(scope->num_parameters()), stack_slots_(scope->num_stack_slots()), @@ -153,6 +154,8 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) // // - is strict mode scope // +// - is qml mode scope +// // - scope type // // - number of variables in the context object (smi) (= function context @@ -252,6 +255,7 @@ ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data) p = ReadObject(p, &function_name_); p = ReadBool(p, &calls_eval_); p = ReadBool(p, &is_strict_mode_); + p = ReadBool(p, &is_qml_mode_); p = ReadInt(p, &type_); p = ReadList<Allocator>(p, &context_slots_, &context_modes_); p = ReadList<Allocator>(p, ¶meters_); @@ -307,9 +311,9 @@ static Object** WriteList(Object** p, template<class Allocator> Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() { - // function name, calls eval, is_strict_mode, scope type, + // function name, calls eval, is_strict_mode, is_qml_mode, scope type, // length for 3 tables: - const int extra_slots = 1 + 1 + 1 + 1 + 3; + const int extra_slots = 1 + 1 + 1 + 1 + 1 + 3; int length = extra_slots + context_slots_.length() * 2 + parameters_.length() + @@ -324,6 +328,7 @@ Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() { p = WriteObject(p, function_name_); p = WriteBool(p, calls_eval_); p = WriteBool(p, is_strict_mode_); + p = WriteBool(p, is_qml_mode_); p = WriteInt(p, type_); p = WriteList(p, &context_slots_, &context_modes_); p = WriteList(p, ¶meters_); @@ -372,8 +377,8 @@ SerializedScopeInfo* SerializedScopeInfo::Empty() { Object** SerializedScopeInfo::ContextEntriesAddr() { ASSERT(length() > 0); - // +4 for function name, calls eval, strict mode, scope type. - return data_start() + 4; + // +5 for function name, calls eval, strict mode, qml mode, scope type. + return data_start() + 5; } @@ -417,10 +422,21 @@ bool SerializedScopeInfo::IsStrictMode() { } +bool SerializedScopeInfo::IsQmlMode() { + if (length() > 0) { + Object** p = data_start() + 3; // +3 for function name, calls eval, strict mode. + bool qml_mode; + p = ReadBool(p, &qml_mode); + return qml_mode; + } + return false; +} + + ScopeType SerializedScopeInfo::Type() { ASSERT(length() > 0); - // +3 for function name, calls eval, strict mode. - Object** p = data_start() + 3; + // +4 for function name, calls eval, strict mode, qml mode. + Object** p = data_start() + 4; ScopeType type; p = ReadInt(p, &type); return type; diff --git a/src/3rdparty/v8/src/scopeinfo.h b/src/3rdparty/v8/src/scopeinfo.h index eeb3047..2ca4503 100644 --- a/src/3rdparty/v8/src/scopeinfo.h +++ b/src/3rdparty/v8/src/scopeinfo.h @@ -88,6 +88,7 @@ class ScopeInfo BASE_EMBEDDED { Handle<String> function_name_; bool calls_eval_; bool is_strict_mode_; + bool is_qml_mode_; ScopeType type_; List<Handle<String>, Allocator > parameters_; List<Handle<String>, Allocator > stack_slots_; diff --git a/src/3rdparty/v8/src/scopes.cc b/src/3rdparty/v8/src/scopes.cc index 3167c4d..6503d07 100644 --- a/src/3rdparty/v8/src/scopes.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/scopes.h b/src/3rdparty/v8/src/scopes.h index a141887..41e5f5c 100644 --- a/src/3rdparty/v8/src/scopes.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/variables.cc b/src/3rdparty/v8/src/variables.cc index d85e1b2..1887935 100644 --- a/src/3rdparty/v8/src/variables.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/variables.h b/src/3rdparty/v8/src/variables.h index 8b2d869..33561b0 100644 --- a/src/3rdparty/v8/src/variables.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/x64/code-stubs-x64.cc b/src/3rdparty/v8/src/x64/code-stubs-x64.cc index f62c517..f30221f 100644 --- a/src/3rdparty/v8/src/x64/code-stubs-x64.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/x64/full-codegen-x64.cc b/src/3rdparty/v8/src/x64/full-codegen-x64.cc index bf640db..b1e5d35 100644 --- a/src/3rdparty/v8/src/x64/full-codegen-x64.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/x64/lithium-codegen-x64.cc b/src/3rdparty/v8/src/x64/lithium-codegen-x64.cc index 38a8c18..2a95fee 100644 --- a/src/3rdparty/v8/src/x64/lithium-codegen-x64.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/x64/lithium-x64.cc b/src/3rdparty/v8/src/x64/lithium-x64.cc index 0af2ce4..9e2731f 100644 --- a/src/3rdparty/v8/src/x64/lithium-x64.cc +++ b/src/3rdparty/v8/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/3rdparty/v8/src/x64/lithium-x64.h b/src/3rdparty/v8/src/x64/lithium-x64.h index 20a6937..8f1a3d8 100644 --- a/src/3rdparty/v8/src/x64/lithium-x64.h +++ b/src/3rdparty/v8/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/3rdparty/v8/src/x64/macro-assembler-x64.h b/src/3rdparty/v8/src/x64/macro-assembler-x64.h index f5f81b1..5caa6cf 100644 --- a/src/3rdparty/v8/src/x64/macro-assembler-x64.h +++ b/src/3rdparty/v8/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 |