summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-10-27 13:34:16 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-01-09 13:06:01 +0100
commit194da71eed49e4d5e904e8c28cb510fb85b95912 (patch)
tree4bb40c02292e8fe51c1e975b09727b710748668c
parent504ef4cafdbc0c927d9f86ef21d9e7db757fd110 (diff)
downloadqtjsbackend-194da71eed49e4d5e904e8c28cb510fb85b95912.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: I75d6f8173260e0d4933fd33ad16a277542048f09 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r--src/3rdparty/v8/include/v8.h19
-rw-r--r--src/3rdparty/v8/src/api.cc47
-rw-r--r--src/3rdparty/v8/src/arm/code-stubs-arm.cc8
-rw-r--r--src/3rdparty/v8/src/arm/full-codegen-arm.cc26
-rw-r--r--src/3rdparty/v8/src/arm/lithium-arm.cc4
-rw-r--r--src/3rdparty/v8/src/arm/lithium-arm.h13
-rw-r--r--src/3rdparty/v8/src/arm/lithium-codegen-arm.cc9
-rw-r--r--src/3rdparty/v8/src/arm/macro-assembler-arm.h5
-rw-r--r--src/3rdparty/v8/src/ast.cc10
-rw-r--r--src/3rdparty/v8/src/ast.h2
-rw-r--r--src/3rdparty/v8/src/bootstrapper.cc2
-rw-r--r--src/3rdparty/v8/src/code-stubs.h4
-rw-r--r--src/3rdparty/v8/src/compiler.cc15
-rw-r--r--src/3rdparty/v8/src/compiler.h16
-rw-r--r--src/3rdparty/v8/src/contexts.cc35
-rw-r--r--src/3rdparty/v8/src/contexts.h8
-rw-r--r--src/3rdparty/v8/src/execution.cc32
-rw-r--r--src/3rdparty/v8/src/execution.h8
-rw-r--r--src/3rdparty/v8/src/full-codegen.h1
-rw-r--r--src/3rdparty/v8/src/globals.h6
-rw-r--r--src/3rdparty/v8/src/heap.cc4
-rw-r--r--src/3rdparty/v8/src/hydrogen-instructions.cc5
-rw-r--r--src/3rdparty/v8/src/hydrogen-instructions.h19
-rw-r--r--src/3rdparty/v8/src/hydrogen.cc6
-rw-r--r--src/3rdparty/v8/src/ia32/code-stubs-ia32.cc9
-rw-r--r--src/3rdparty/v8/src/ia32/full-codegen-ia32.cc25
-rw-r--r--src/3rdparty/v8/src/ia32/lithium-codegen-ia32.cc9
-rw-r--r--src/3rdparty/v8/src/ia32/lithium-ia32.cc4
-rw-r--r--src/3rdparty/v8/src/ia32/lithium-ia32.h14
-rw-r--r--src/3rdparty/v8/src/ia32/macro-assembler-ia32.h3
-rw-r--r--src/3rdparty/v8/src/ic.cc2
-rw-r--r--src/3rdparty/v8/src/ic.h8
-rw-r--r--src/3rdparty/v8/src/mips/code-stubs-mips.cc9
-rw-r--r--src/3rdparty/v8/src/mips/full-codegen-mips.cc26
-rw-r--r--src/3rdparty/v8/src/mips/lithium-codegen-mips.cc9
-rw-r--r--src/3rdparty/v8/src/mips/lithium-mips.cc4
-rw-r--r--src/3rdparty/v8/src/mips/lithium-mips.h14
-rw-r--r--src/3rdparty/v8/src/mips/macro-assembler-mips.h5
-rw-r--r--src/3rdparty/v8/src/objects-inl.h2
-rw-r--r--src/3rdparty/v8/src/objects.h19
-rw-r--r--src/3rdparty/v8/src/parser.cc37
-rw-r--r--src/3rdparty/v8/src/prettyprinter.cc3
-rw-r--r--src/3rdparty/v8/src/runtime.cc70
-rw-r--r--src/3rdparty/v8/src/runtime.h6
-rw-r--r--src/3rdparty/v8/src/scopeinfo.cc11
-rw-r--r--src/3rdparty/v8/src/scopes.cc81
-rw-r--r--src/3rdparty/v8/src/scopes.h11
-rw-r--r--src/3rdparty/v8/src/stub-cache.cc13
-rw-r--r--src/3rdparty/v8/src/stub-cache.h5
-rw-r--r--src/3rdparty/v8/src/variables.cc3
-rw-r--r--src/3rdparty/v8/src/variables.h6
-rw-r--r--src/3rdparty/v8/src/x64/code-stubs-x64.cc8
-rw-r--r--src/3rdparty/v8/src/x64/full-codegen-x64.cc25
-rw-r--r--src/3rdparty/v8/src/x64/lithium-codegen-x64.cc7
-rw-r--r--src/3rdparty/v8/src/x64/lithium-x64.cc4
-rw-r--r--src/3rdparty/v8/src/x64/lithium-x64.h12
-rw-r--r--src/3rdparty/v8/src/x64/macro-assembler-x64.h5
-rw-r--r--src/3rdparty/v8/test/cctest/test-api.cc13
-rw-r--r--src/3rdparty/v8/test/cctest/test-heap-profiler.cc38
-rw-r--r--src/3rdparty/v8/test/cctest/test-heap.cc21
60 files changed, 692 insertions, 153 deletions
diff --git a/src/3rdparty/v8/include/v8.h b/src/3rdparty/v8/include/v8.h
index 87ba6ab..8fb22f8 100644
--- a/src/3rdparty/v8/include/v8.h
+++ b/src/3rdparty/v8/include/v8.h
@@ -611,6 +611,11 @@ class ScriptOrigin {
*/
class V8EXPORT Script {
public:
+ enum CompileFlags {
+ Default = 0x00,
+ QmlMode = 0x01
+ };
+
/**
* Compiles the specified script (context-independent).
*
@@ -629,7 +634,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
@@ -642,7 +648,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).
@@ -663,7 +670,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
@@ -680,7 +688,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
@@ -690,6 +699,7 @@ class V8EXPORT Script {
* compiled.
*/
Local<Value> Run();
+ Local<Value> Run(Handle<Object> qml);
/**
* Returns the script id value.
@@ -3815,6 +3825,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 6d3b319..f0e0810 100644
--- a/src/3rdparty/v8/src/api.cc
+++ b/src/3rdparty/v8/src/api.cc
@@ -1600,7 +1600,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");
@@ -1642,7 +1643,8 @@ Local<Script> Script::New(v8::Handle<String> source,
NULL,
pre_data_impl,
Utils::OpenHandle(*script_data, true),
- i::NOT_NATIVES_CODE);
+ i::NOT_NATIVES_CODE,
+ compile_flags);
has_pending_exception = result.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
raw_result = *result;
@@ -1653,21 +1655,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);
@@ -1683,13 +1687,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");
@@ -1708,10 +1717,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, true);
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_DO_CALLBACK(isolate, Local<Value>());
raw_result = *result;
}
@@ -4746,6 +4756,25 @@ 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();
+ i::JavaScriptFrameIterator it;
+ if (it.done()) return Local<Object>();
+ context = i::Context::cast(it.frame()->context());
+ if (!context->qml_global_object()->IsUndefined()) {
+ i::Handle<i::Object> qmlglobal(context->qml_global_object());
+ 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 1e73a55..cecc9d1 100644
--- a/src/3rdparty/v8/src/arm/code-stubs-arm.cc
+++ b/src/3rdparty/v8/src/arm/code-stubs-arm.cc
@@ -249,6 +249,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
__ str(r1, MemOperand(r0, Context::SlotOffset(Context::EXTENSION_INDEX)));
__ str(r2, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+ // Copy the qml global object from the surrounding context.
+ __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::QML_GLOBAL_OBJECT_INDEX)));
+ __ str(r1, MemOperand(r0, Context::SlotOffset(Context::QML_GLOBAL_OBJECT_INDEX)));
+
// Initialize the rest of the slots to undefined.
__ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
@@ -313,6 +317,10 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
__ str(r1, ContextOperand(r0, Context::EXTENSION_INDEX));
__ str(r2, ContextOperand(r0, Context::GLOBAL_OBJECT_INDEX));
+ // Copy the qml global object from the surrounding context.
+ __ ldr(r1, ContextOperand(cp, Context::QML_GLOBAL_OBJECT_INDEX));
+ __ str(r1, ContextOperand(r0, Context::QML_GLOBAL_OBJECT_INDEX));
+
// Initialize the rest of the slots to the hole value.
__ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
for (int i = 0; i < slots_; i++) {
diff --git a/src/3rdparty/v8/src/arm/full-codegen-arm.cc b/src/3rdparty/v8/src/arm/full-codegen-arm.cc
index 03d5067..9a7b116 100644
--- a/src/3rdparty/v8/src/arm/full-codegen-arm.cc
+++ b/src/3rdparty/v8/src/arm/full-codegen-arm.cc
@@ -186,7 +186,8 @@ void FullCodeGenerator::Generate() {
// 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())) {
// Argument to NewContext is the function, which is still in r1.
Comment cmnt(masm_, "[ Allocate context");
__ push(r1);
@@ -194,7 +195,7 @@ void FullCodeGenerator::Generate() {
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
- FastNewContextStub stub(heap_slots);
+ FastNewContextStub stub((heap_slots < 0) ? 0 : heap_slots);
__ CallStub(&stub);
} else {
__ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -812,6 +813,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
? isolate()->factory()->the_hole_value()
: isolate()->factory()->undefined_value(),
zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
break;
case Variable::PARAMETER:
@@ -872,6 +874,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
// Check for stack-overflow exception.
if (function.is_null()) return SetStackOverflow();
globals_->Add(function, zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
break;
}
@@ -927,6 +930,7 @@ void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
Comment cmnt(masm_, "[ ModuleDeclaration");
globals_->Add(variable->name(), zone());
globals_->Add(instance, zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
Visit(declaration->module());
break;
}
@@ -1337,7 +1341,7 @@ 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::CODE_TARGET
@@ -1424,7 +1428,7 @@ 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();
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
@@ -2092,7 +2096,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_classic_mode()
? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict();
@@ -2360,8 +2364,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
__ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
__ push(r1);
+ // Push the qml mode flag.
+ __ mov(r1, Operand(Smi::FromInt(is_qml_mode())));
+ __ push(r1);
+
// Do the runtime call.
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
}
@@ -2418,7 +2426,7 @@ 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);
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
@@ -3845,7 +3853,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// but "delete this" is allowed.
ASSERT(language_mode() == CLASSIC_MODE || 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);
@@ -4149,7 +4157,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 17f3325..b492d48 100644
--- a/src/3rdparty/v8/src/arm/lithium-arm.cc
+++ b/src/3rdparty/v8/src/arm/lithium-arm.cc
@@ -994,7 +994,7 @@ LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LGlobalObject(context));
+ return DefineAsRegister(new(zone()) LGlobalObject(context, instr->qml_global()));
}
@@ -1068,7 +1068,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) 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 0ba5e45..2c289dd 100644
--- a/src/3rdparty/v8/src/arm/lithium-arm.h
+++ b/src/3rdparty/v8/src/arm/lithium-arm.h
@@ -1542,13 +1542,18 @@ class LDeclareGlobals: public LTemplateInstruction<0, 0, 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 inputs_[0]; }
+ bool qml_global() { return qml_global_; }
+
+ private:
+ bool qml_global_;
};
@@ -1644,10 +1649,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 7615134..392c18e 100644
--- a/src/3rdparty/v8/src/arm/lithium-codegen-arm.cc
+++ b/src/3rdparty/v8/src/arm/lithium-codegen-arm.cc
@@ -175,12 +175,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);
@@ -3343,7 +3344,9 @@ void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
Register result = ToRegister(instr->result());
- __ ldr(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+ __ ldr(result, ContextOperand(cp, instr->qml_global()
+ ? Context::QML_GLOBAL_OBJECT_INDEX
+ : Context::GLOBAL_OBJECT_INDEX));
}
diff --git a/src/3rdparty/v8/src/arm/macro-assembler-arm.h b/src/3rdparty/v8/src/arm/macro-assembler-arm.h
index 1d97a6c..0ff8579 100644
--- a/src/3rdparty/v8/src/arm/macro-assembler-arm.h
+++ b/src/3rdparty/v8/src/arm/macro-assembler-arm.h
@@ -1414,6 +1414,11 @@ inline MemOperand GlobalObjectOperand() {
}
+static inline MemOperand QmlGlobalObjectOperand() {
+ return ContextOperand(cp, Context::QML_GLOBAL_OBJECT_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.cc b/src/3rdparty/v8/src/ast.cc
index 52990b8..3015b1e 100644
--- a/src/3rdparty/v8/src/ast.cc
+++ b/src/3rdparty/v8/src/ast.cc
@@ -173,6 +173,11 @@ LanguageMode FunctionLiteral::language_mode() const {
}
+QmlModeFlag FunctionLiteral::qml_mode_flag() const {
+ return scope()->qml_mode_flag();
+}
+
+
ObjectLiteral::Property::Property(Literal* key,
Expression* value,
Isolate* isolate) {
@@ -560,6 +565,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 802ac65..d3f90b2 100644
--- a/src/3rdparty/v8/src/ast.h
+++ b/src/3rdparty/v8/src/ast.h
@@ -1961,6 +1961,8 @@ class FunctionLiteral: public Expression {
bool is_anonymous() const { return IsAnonymous::decode(bitfield_); }
bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
LanguageMode language_mode() const;
+ bool qml_mode() const { return qml_mode_flag() == kQmlMode; }
+ QmlModeFlag qml_mode_flag() const;
int materialized_literal_count() { return materialized_literal_count_; }
int expected_property_count() { return expected_property_count_; }
diff --git a/src/3rdparty/v8/src/bootstrapper.cc b/src/3rdparty/v8/src/bootstrapper.cc
index ffa5283..c06d73d 100644
--- a/src/3rdparty/v8/src/bootstrapper.cc
+++ b/src/3rdparty/v8/src/bootstrapper.cc
@@ -807,6 +807,7 @@ void Genesis::HookUpInnerGlobal(Handle<GlobalObject> inner_global) {
Handle<JSBuiltinsObject> builtins_global(native_context_->builtins());
native_context_->set_extension(*inner_global);
native_context_->set_global_object(*inner_global);
+ native_context_->set_qml_global_object(*inner_global);
native_context_->set_security_token(*inner_global);
static const PropertyAttributes attributes =
static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
@@ -832,6 +833,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
// Set extension and global object.
native_context()->set_extension(*inner_global);
native_context()->set_global_object(*inner_global);
+ native_context()->set_qml_global_object(*inner_global);
// Security setup: Set the security token of the global object to
// its the inner global. This makes the security check between two
// different contexts fail by default even in case of global
diff --git a/src/3rdparty/v8/src/code-stubs.h b/src/3rdparty/v8/src/code-stubs.h
index e4384e7..8288f4d 100644
--- a/src/3rdparty/v8/src/code-stubs.h
+++ b/src/3rdparty/v8/src/code-stubs.h
@@ -344,7 +344,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);
@@ -362,7 +362,7 @@ class FastNewBlockContextStub : public CodeStub {
static const int kMaximumSlots = 64;
explicit FastNewBlockContextStub(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 710c61e..810794c 100644
--- a/src/3rdparty/v8/src/compiler.cc
+++ b/src/3rdparty/v8/src/compiler.cc
@@ -547,7 +547,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
v8::Extension* extension,
ScriptDataImpl* 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);
@@ -601,6 +602,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
if (FLAG_use_strict) {
info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE);
}
+ if (compile_flags & v8::Script::QmlMode) info.MarkAsQmlMode();
result = MakeFunctionInfo(&info);
if (extension == NULL && !result.is_null() && !result->dont_cache()) {
compilation_cache->PutScript(source, context, result);
@@ -621,7 +623,8 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
Handle<Context> context,
bool is_global,
LanguageMode language_mode,
- int scope_position) {
+ int scope_position,
+ bool qml_mode) {
Isolate* isolate = source->GetIsolate();
int source_length = source->length();
isolate->counters()->total_eval_size()->Increment(source_length);
@@ -647,6 +650,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
info.MarkAsEval();
if (is_global) info.MarkAsGlobal();
info.SetLanguageMode(language_mode);
+ if (qml_mode) info.MarkAsQmlMode();
info.SetContext(context);
result = MakeFunctionInfo(&info);
if (!result.is_null()) {
@@ -813,6 +817,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
info->SetLanguageMode(language_mode);
shared->set_language_mode(language_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()) {
@@ -1006,6 +1016,7 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
function_info->set_allows_lazy_compilation_without_context(
lit->AllowsLazyCompilationWithoutContext());
function_info->set_language_mode(lit->language_mode());
+ function_info->set_qml_mode(lit->qml_mode());
function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
function_info->set_ast_node_count(lit->ast_node_count());
diff --git a/src/3rdparty/v8/src/compiler.h b/src/3rdparty/v8/src/compiler.h
index af94595..b119775 100644
--- a/src/3rdparty/v8/src/compiler.h
+++ b/src/3rdparty/v8/src/compiler.h
@@ -63,6 +63,7 @@ class CompilationInfo {
return LanguageModeField::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_; }
Scope* global_scope() const { return global_scope_; }
@@ -93,6 +94,9 @@ class CompilationInfo {
ASSERT(is_lazy());
flags_ |= IsInLoop::encode(true);
}
+ void MarkAsQmlMode() {
+ flags_ |= IsQmlMode::encode(true);
+ }
void MarkAsNative() {
flags_ |= IsNative::encode(true);
}
@@ -210,6 +214,9 @@ class CompilationInfo {
ASSERT(language_mode() == CLASSIC_MODE);
SetLanguageMode(shared_info_->language_mode());
}
+ if (!shared_info_.is_null() && shared_info_->qml_mode()) {
+ MarkAsQmlMode();
+ }
set_bailout_reason("unknown");
}
@@ -237,7 +244,8 @@ class CompilationInfo {
// 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_;
@@ -434,14 +442,16 @@ 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,
LanguageMode language_mode,
- int scope_position);
+ int scope_position,
+ 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 fbb2f1a..662e326 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_object()->IsUndefined()) {
+ qml_global = Handle<JSObject>(context->qml_global_object(), isolate);
+ qml_global_global = Handle<JSObject>(context->global_object(), isolate);
+ }
+
// 1. Check global objects, subjects of with, and extension objects.
if (context->IsNativeContext() ||
context->IsWithContext() ||
@@ -233,6 +241,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 f44d15d..61e6c66 100644
--- a/src/3rdparty/v8/src/contexts.h
+++ b/src/3rdparty/v8/src/contexts.h
@@ -226,6 +226,7 @@ class Context: public FixedArray {
// (with contexts), or the variable name (catch contexts), the serialized
// scope info (block contexts), or the module instance (module contexts).
EXTENSION_INDEX,
+ QML_GLOBAL_OBJECT_INDEX,
GLOBAL_OBJECT_INDEX,
MIN_CONTEXT_SLOTS,
@@ -338,6 +339,13 @@ class Context: public FixedArray {
set(GLOBAL_OBJECT_INDEX, object);
}
+ JSObject* qml_global_object() {
+ return reinterpret_cast<JSObject *>(get(QML_GLOBAL_OBJECT_INDEX));
+ }
+ void set_qml_global_object(JSObject *qml_global) {
+ set(QML_GLOBAL_OBJECT_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 89091ba..913bf64 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_object()->IsGlobalObject());
+ Handle<JSObject> oldqml;
+ if (!qml.is_null()) {
+ oldqml = Handle<JSObject>(function->context()->qml_global_object());
+ function->context()->set_qml_global_object(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_object(*oldqml);
+
#ifdef VERIFY_HEAP
value->Verify();
#endif
@@ -152,7 +162,19 @@ 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()) {
@@ -176,7 +198,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);
}
@@ -185,7 +207,7 @@ Handle<Object> Execution::New(Handle<JSFunction> func,
Handle<Object> argv[],
bool* pending_exception) {
return Invoke(true, func, Isolate::Current()->global_object(), argc, argv,
- pending_exception);
+ pending_exception, Handle<Object>());
}
@@ -204,7 +226,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 9f5d9ff..90219f5 100644
--- a/src/3rdparty/v8/src/execution.h
+++ b/src/3rdparty/v8/src/execution.h
@@ -70,6 +70,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.h b/src/3rdparty/v8/src/full-codegen.h
index 89b51f9..972839e 100644
--- a/src/3rdparty/v8/src/full-codegen.h
+++ b/src/3rdparty/v8/src/full-codegen.h
@@ -572,6 +572,7 @@ class FullCodeGenerator: public AstVisitor {
bool is_native() { return info_->is_native(); }
bool is_classic_mode() { return language_mode() == CLASSIC_MODE; }
LanguageMode language_mode() { return function()->language_mode(); }
+ bool is_qml_mode() { return function()->qml_mode(); }
FunctionLiteral* function() { return info_->function(); }
Scope* scope() { return scope_; }
diff --git a/src/3rdparty/v8/src/globals.h b/src/3rdparty/v8/src/globals.h
index babffbf..e8c323c 100644
--- a/src/3rdparty/v8/src/globals.h
+++ b/src/3rdparty/v8/src/globals.h
@@ -399,6 +399,12 @@ enum StrictModeFlag {
kStrictMode
};
+// The QML Compilation Mode
+enum QmlModeFlag {
+ kNonQmlMode,
+ kQmlMode
+};
+
} } // namespace v8::internal
diff --git a/src/3rdparty/v8/src/heap.cc b/src/3rdparty/v8/src/heap.cc
index d56f01b..ebf3ccd 100644
--- a/src/3rdparty/v8/src/heap.cc
+++ b/src/3rdparty/v8/src/heap.cc
@@ -5149,6 +5149,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
context->set_previous(function->context());
context->set_extension(Smi::FromInt(0));
context->set_global_object(function->context()->global_object());
+ context->set_qml_global_object(function->context()->qml_global_object());
return context;
}
@@ -5169,6 +5170,7 @@ MaybeObject* Heap::AllocateCatchContext(JSFunction* function,
context->set_previous(previous);
context->set_extension(name);
context->set_global_object(previous->global_object());
+ context->set_qml_global_object(previous->qml_global_object());
context->set(Context::THROWN_OBJECT_INDEX, thrown_object);
return context;
}
@@ -5187,6 +5189,7 @@ MaybeObject* Heap::AllocateWithContext(JSFunction* function,
context->set_previous(previous);
context->set_extension(extension);
context->set_global_object(previous->global_object());
+ context->set_qml_global_object(previous->qml_global_object());
return context;
}
@@ -5205,6 +5208,7 @@ MaybeObject* Heap::AllocateBlockContext(JSFunction* function,
context->set_previous(previous);
context->set_extension(scope_info);
context->set_global_object(previous->global_object());
+ context->set_qml_global_object(previous->qml_global_object());
return context;
}
diff --git a/src/3rdparty/v8/src/hydrogen-instructions.cc b/src/3rdparty/v8/src/hydrogen-instructions.cc
index f93b930..c8edcff 100644
--- a/src/3rdparty/v8/src/hydrogen-instructions.cc
+++ b/src/3rdparty/v8/src/hydrogen-instructions.cc
@@ -700,6 +700,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 d118354..7136657 100644
--- a/src/3rdparty/v8/src/hydrogen-instructions.h
+++ b/src/3rdparty/v8/src/hydrogen-instructions.h
@@ -1602,22 +1602,31 @@ class HDeclareGlobals: 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:
virtual bool IsDeletable() const { return true; }
+ bool qml_global_;
};
@@ -1812,7 +1821,7 @@ class HCallFunction: public HBinaryCall {
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);
@@ -1824,10 +1833,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 51ae7f5..043d567 100644
--- a/src/3rdparty/v8/src/hydrogen.cc
+++ b/src/3rdparty/v8/src/hydrogen.cc
@@ -4823,6 +4823,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,
@@ -5596,6 +5597,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,
@@ -7662,11 +7664,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);
}
@@ -8824,6 +8828,7 @@ void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* declaration) {
globals_.Add(variable->binding_needs_init()
? isolate()->factory()->the_hole_value()
: isolate()->factory()->undefined_value(), zone());
+ globals_.Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
return;
case Variable::PARAMETER:
case Variable::LOCAL:
@@ -8859,6 +8864,7 @@ void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) {
// Check for stack-overflow exception.
if (function.is_null()) return SetStackOverflow();
globals_.Add(function, zone());
+ globals_.Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
return;
}
case Variable::PARAMETER:
diff --git a/src/3rdparty/v8/src/ia32/code-stubs-ia32.cc b/src/3rdparty/v8/src/ia32/code-stubs-ia32.cc
index 7ea71e4..5791095 100644
--- a/src/3rdparty/v8/src/ia32/code-stubs-ia32.cc
+++ b/src/3rdparty/v8/src/ia32/code-stubs-ia32.cc
@@ -220,6 +220,11 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
__ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)), ebx);
+ // Copy the qml global object from the previous context.
+ __ mov(ebx, Operand(esi, Context::SlotOffset(Context::QML_GLOBAL_OBJECT_INDEX)));
+ __ mov(Operand(eax, Context::SlotOffset(Context::QML_GLOBAL_OBJECT_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++) {
@@ -286,6 +291,10 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
__ mov(ebx, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX));
__ mov(ContextOperand(eax, Context::GLOBAL_OBJECT_INDEX), ebx);
+ // Copy the qml global object from the previous context.
+ __ mov(ebx, ContextOperand(esi, Context::QML_GLOBAL_OBJECT_INDEX));
+ __ mov(ContextOperand(eax, Context::QML_GLOBAL_OBJECT_INDEX), ebx);
+
// Initialize the rest of the slots to the hole value.
if (slots_ == 1) {
__ mov(ContextOperand(eax, Context::MIN_CONTEXT_SLOTS),
diff --git a/src/3rdparty/v8/src/ia32/full-codegen-ia32.cc b/src/3rdparty/v8/src/ia32/full-codegen-ia32.cc
index 159c2ca..c58f242 100644
--- a/src/3rdparty/v8/src/ia32/full-codegen-ia32.cc
+++ b/src/3rdparty/v8/src/ia32/full-codegen-ia32.cc
@@ -181,7 +181,8 @@ void FullCodeGenerator::Generate() {
// 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 context");
// Argument to NewContext is the function, which is still in edi.
__ push(edi);
@@ -189,7 +190,7 @@ void FullCodeGenerator::Generate() {
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
- FastNewContextStub stub(heap_slots);
+ FastNewContextStub stub((heap_slots < 0) ? 0 : heap_slots);
__ CallStub(&stub);
} else {
__ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -787,6 +788,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
globals_->Add(variable->binding_needs_init()
? isolate()->factory()->the_hole_value()
: isolate()->factory()->undefined_value(), zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
break;
case Variable::PARAMETER:
@@ -846,6 +848,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
// Check for stack-overflow exception.
if (function.is_null()) return SetStackOverflow();
globals_->Add(function, zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
break;
}
@@ -898,6 +901,7 @@ void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
Comment cmnt(masm_, "[ ModuleDeclaration");
globals_->Add(variable->name(), zone());
globals_->Add(instance, zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
Visit(declaration->module());
break;
}
@@ -1295,7 +1299,7 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
// All extension objects were empty and it is safe to use a global
// load IC call.
- __ mov(edx, GlobalObjectOperand());
+ __ mov(edx, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
__ mov(ecx, var->name());
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
@@ -1379,7 +1383,7 @@ 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(edx, GlobalObjectOperand());
+ __ mov(edx, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
__ mov(ecx, var->name());
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
@@ -2048,7 +2052,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_classic_mode()
? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict();
@@ -2312,8 +2316,11 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
// Push the start position of the scope the calls resides in.
__ push(Immediate(Smi::FromInt(scope()->start_position())));
+ // Push the qml mode flag
+ __ push(Immediate(Smi::FromInt(is_qml_mode())));
+
// Do the runtime call.
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
}
@@ -2366,7 +2373,7 @@ 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());
EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
@@ -3823,7 +3830,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// but "delete this" is allowed.
ASSERT(language_mode() == CLASSIC_MODE || 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);
@@ -4145,7 +4152,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
if (proxy != NULL && proxy->var()->IsUnallocated()) {
Comment cmnt(masm_, "Global variable");
- __ mov(edx, GlobalObjectOperand());
+ __ mov(edx, 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 676e73e..34ce1cd 100644
--- a/src/3rdparty/v8/src/ia32/lithium-codegen-ia32.cc
+++ b/src/3rdparty/v8/src/ia32/lithium-codegen-ia32.cc
@@ -241,12 +241,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);
@@ -3126,7 +3127,9 @@ void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result());
__ mov(result,
- Operand(context, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+ Operand(context, Context::SlotOffset(instr->qml_global()
+ ? Context::QML_GLOBAL_OBJECT_INDEX
+ : Context::GLOBAL_OBJECT_INDEX)));
}
diff --git a/src/3rdparty/v8/src/ia32/lithium-ia32.cc b/src/3rdparty/v8/src/ia32/lithium-ia32.cc
index ba9c97e..dcc5b77 100644
--- a/src/3rdparty/v8/src/ia32/lithium-ia32.cc
+++ b/src/3rdparty/v8/src/ia32/lithium-ia32.cc
@@ -1035,7 +1035,7 @@ LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LGlobalObject(context));
+ return DefineAsRegister(new(zone()) LGlobalObject(context, instr->qml_global()));
}
@@ -1125,7 +1125,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(zone()) LCallGlobal(context);
+ LCallGlobal* result = new(zone()) 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 18741d1..a1adb01 100644
--- a/src/3rdparty/v8/src/ia32/lithium-ia32.h
+++ b/src/3rdparty/v8/src/ia32/lithium-ia32.h
@@ -1603,13 +1603,19 @@ class LDeclareGlobals: public LTemplateInstruction<0, 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;
}
LOperand* context() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
+
+ bool qml_global() { return qml_global_; }
+
+ private:
+ bool qml_global_;
};
@@ -1713,7 +1719,7 @@ class LCallFunction: public LTemplateInstruction<1, 2, 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;
}
@@ -1726,6 +1732,10 @@ class LCallGlobal: public LTemplateInstruction<1, 1, 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 e48d0e7..b91cfcd 100644
--- a/src/3rdparty/v8/src/ia32/macro-assembler-ia32.h
+++ b/src/3rdparty/v8/src/ia32/macro-assembler-ia32.h
@@ -975,6 +975,9 @@ inline Operand GlobalObjectOperand() {
return ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX);
}
+static inline Operand QmlGlobalObjectOperand() {
+ return ContextOperand(esi, Context::QML_GLOBAL_OBJECT_INDEX);
+}
// Generates an Operand for saving parameters after PrepareCallApiFunction.
Operand ApiParameterOperand(int index);
diff --git a/src/3rdparty/v8/src/ic.cc b/src/3rdparty/v8/src/ic.cc
index 5cc213f..354ed64 100644
--- a/src/3rdparty/v8/src/ic.cc
+++ b/src/3rdparty/v8/src/ic.cc
@@ -677,7 +677,7 @@ Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
// applicable.
if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
return isolate()->stub_cache()->ComputeCallNormal(
- argc, kind_, extra_state);
+ argc, kind_, extra_state, IsQmlGlobal(holder));
}
break;
}
diff --git a/src/3rdparty/v8/src/ic.h b/src/3rdparty/v8/src/ic.h
index 8767f98..389c845 100644
--- a/src/3rdparty/v8/src/ic.h
+++ b/src/3rdparty/v8/src/ic.h
@@ -110,10 +110,16 @@ class IC {
// object that contains this IC site.
RelocInfo::Mode ComputeMode();
+ bool IsQmlGlobal(Handle<Object> receiver) {
+ JSObject* qml_global = isolate_->context()->qml_global_object();
+ return !qml_global->IsUndefined() && qml_global == *receiver;
+ }
+
// Returns if this IC is for contextual (no explicit receiver)
// access to properties.
bool IsContextual(Handle<Object> receiver) {
- if (receiver->IsGlobalObject()) {
+ if (receiver->IsGlobalObject() ||
+ IsQmlGlobal(receiver)) {
return SlowIsContextual();
} else {
ASSERT(!SlowIsContextual());
diff --git a/src/3rdparty/v8/src/mips/code-stubs-mips.cc b/src/3rdparty/v8/src/mips/code-stubs-mips.cc
index 7f7d70e..f122d14 100644
--- a/src/3rdparty/v8/src/mips/code-stubs-mips.cc
+++ b/src/3rdparty/v8/src/mips/code-stubs-mips.cc
@@ -251,6 +251,11 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
__ sw(a1, MemOperand(v0, Context::SlotOffset(Context::EXTENSION_INDEX)));
__ sw(a2, MemOperand(v0, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+ // Copy the qml global object from the surrounding context.
+ __ lw(a1, MemOperand(cp, Context::SlotOffset(Context::QML_GLOBAL_OBJECT_INDEX)));
+ __ sw(a1, MemOperand(v0, Context::SlotOffset(Context::QML_GLOBAL_OBJECT_INDEX)));
+
+
// Initialize the rest of the slots to undefined.
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
@@ -313,6 +318,10 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
__ sw(a1, ContextOperand(v0, Context::EXTENSION_INDEX));
__ sw(a2, ContextOperand(v0, Context::GLOBAL_OBJECT_INDEX));
+ // Copy the qml global object from the surrounding context.
+ __ lw(a1, ContextOperand(cp, Context::QML_GLOBAL_OBJECT_INDEX));
+ __ sw(a1, ContextOperand(v0, Context::QML_GLOBAL_OBJECT_INDEX));
+
// Initialize the rest of the slots to the hole value.
__ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
for (int i = 0; i < slots_; i++) {
diff --git a/src/3rdparty/v8/src/mips/full-codegen-mips.cc b/src/3rdparty/v8/src/mips/full-codegen-mips.cc
index 3e89fb4..46c9ecb 100644
--- a/src/3rdparty/v8/src/mips/full-codegen-mips.cc
+++ b/src/3rdparty/v8/src/mips/full-codegen-mips.cc
@@ -191,7 +191,8 @@ void FullCodeGenerator::Generate() {
// 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 context");
// Argument to NewContext is the function, which is still in a1.
__ push(a1);
@@ -199,7 +200,7 @@ void FullCodeGenerator::Generate() {
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
- FastNewContextStub stub(heap_slots);
+ FastNewContextStub stub((heap_slots < 0) ? 0 : heap_slots);
__ CallStub(&stub);
} else {
__ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -823,6 +824,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
? isolate()->factory()->the_hole_value()
: isolate()->factory()->undefined_value(),
zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
break;
case Variable::PARAMETER:
@@ -884,6 +886,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
// Check for stack-overflow exception.
if (function.is_null()) return SetStackOverflow();
globals_->Add(function, zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
break;
}
@@ -939,6 +942,7 @@ void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
Comment cmnt(masm_, "[ ModuleDeclaration");
globals_->Add(variable->name(), zone());
globals_->Add(instance, zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
Visit(declaration->module());
break;
}
@@ -1344,7 +1348,7 @@ 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::CODE_TARGET
@@ -1431,7 +1435,7 @@ 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();
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
@@ -2111,7 +2115,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_classic_mode()
? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict();
@@ -2385,8 +2389,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
__ li(a1, Operand(Smi::FromInt(scope()->start_position())));
__ push(a1);
+ // Push the qml mode flag.
+ __ li(a1, Operand(Smi::FromInt(is_qml_mode())));
+ __ push(a1);
+
// Do the runtime call.
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
}
@@ -2442,7 +2450,7 @@ 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);
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
@@ -3881,7 +3889,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// but "delete this" is allowed.
ASSERT(language_mode() == CLASSIC_MODE || 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);
@@ -4188,7 +4196,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/lithium-codegen-mips.cc b/src/3rdparty/v8/src/mips/lithium-codegen-mips.cc
index f79208e..b268fb3 100644
--- a/src/3rdparty/v8/src/mips/lithium-codegen-mips.cc
+++ b/src/3rdparty/v8/src/mips/lithium-codegen-mips.cc
@@ -165,12 +165,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 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);
@@ -3039,7 +3040,9 @@ void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
Register result = ToRegister(instr->result());
- __ lw(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+ __ lw(result, ContextOperand(cp, instr->qml_global()
+ ? Context::QML_GLOBAL_OBJECT_INDEX
+ : Context::GLOBAL_OBJECT_INDEX));
}
diff --git a/src/3rdparty/v8/src/mips/lithium-mips.cc b/src/3rdparty/v8/src/mips/lithium-mips.cc
index b5eb128..7b71758 100644
--- a/src/3rdparty/v8/src/mips/lithium-mips.cc
+++ b/src/3rdparty/v8/src/mips/lithium-mips.cc
@@ -992,7 +992,7 @@ LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LGlobalObject(context));
+ return DefineAsRegister(new(zone()) LGlobalObject(context, instr->qml_global()));
}
@@ -1067,7 +1067,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallGlobal(instr->qml_global()), v0), instr);
}
diff --git a/src/3rdparty/v8/src/mips/lithium-mips.h b/src/3rdparty/v8/src/mips/lithium-mips.h
index 3ea0aef..00e21fd 100644
--- a/src/3rdparty/v8/src/mips/lithium-mips.h
+++ b/src/3rdparty/v8/src/mips/lithium-mips.h
@@ -1522,13 +1522,19 @@ class LDeclareGlobals: public LTemplateInstruction<0, 0, 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;
}
LOperand* context() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
+
+ bool qml_global() { return qml_global_; }
+
+ private:
+ bool qml_global_;
};
@@ -1624,10 +1630,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/mips/macro-assembler-mips.h b/src/3rdparty/v8/src/mips/macro-assembler-mips.h
index b57e514..8b7d7c1 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 @@ inline MemOperand GlobalObjectOperand() {
}
+static inline MemOperand QmlGlobalObjectOperand() {
+ return ContextOperand(cp, Context::QML_GLOBAL_OBJECT_INDEX);
+}
+
+
// Generate a MemOperand for loading a field from an object.
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 d0c225f..27a56dd 100644
--- a/src/3rdparty/v8/src/objects-inl.h
+++ b/src/3rdparty/v8/src/objects-inl.h
@@ -4170,6 +4170,8 @@ bool SharedFunctionInfo::is_classic_mode() {
BOOL_GETTER(SharedFunctionInfo, compiler_hints, is_extended_mode,
kExtendedModeFunction)
+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 17ebc97..4854989 100644
--- a/src/3rdparty/v8/src/objects.h
+++ b/src/3rdparty/v8/src/objects.h
@@ -3469,6 +3469,9 @@ class ScopeInfo : public FixedArray {
// Return the language mode of this scope.
LanguageMode language_mode();
+ // Is this scope a qml mode scope?
+ bool IsQmlMode();
+
// Does this scope make a non-strict eval call?
bool CallsNonStrictEval() {
return CallsEval() && (language_mode() == CLASSIC_MODE);
@@ -3491,7 +3494,7 @@ class ScopeInfo : public FixedArray {
// 3. One context slot for the function name if it is context allocated.
// Parameters allocated in the context count as context allocated locals. If
// no contexts are allocated for this scope ContextLength returns 0.
- int ContextLength();
+ int ContextLength(bool qml_function = false);
// Is this scope the scope of a named function expression?
bool HasFunctionName();
@@ -3566,11 +3569,14 @@ class ScopeInfo : public FixedArray {
// 3. The number of non-parameter variables allocated on the stack.
// 4. The number of non-parameter and parameter variables allocated in the
// context.
+ // 5. The number of non-parameter and parameter variables allocated in the
+ // QML context. (technically placeholder)
#define FOR_EACH_NUMERIC_FIELD(V) \
V(Flags) \
V(ParameterCount) \
V(StackLocalCount) \
- V(ContextLocalCount)
+ V(ContextLocalCount) \
+ V(QmlContextLocalCount)
#define FIELD_ACCESSORS(name) \
void Set##name(int value) { \
@@ -3640,8 +3646,9 @@ class ScopeInfo : public FixedArray {
class TypeField: public BitField<ScopeType, 0, 3> {};
class CallsEvalField: public BitField<bool, 3, 1> {};
class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
- class FunctionVariableField: public BitField<FunctionVariableInfo, 6, 2> {};
- class FunctionVariableMode: public BitField<VariableMode, 8, 3> {};
+ class QmlModeField: public BitField<bool, 6, 1> {};
+ class FunctionVariableField: public BitField<FunctionVariableInfo, 7, 2> {};
+ class FunctionVariableMode: public BitField<VariableMode, 9, 3> {};
// BitFields representing the encoded information for context locals in the
// ContextLocalInfoEntries part.
@@ -5756,6 +5763,9 @@ class SharedFunctionInfo: public HeapObject {
// Indicates whether the language mode of this function is EXTENDED_MODE.
inline bool is_extended_mode();
+ // Indicates whether the function is a qml mode function.
+ DECL_BOOLEAN_ACCESSORS(qml_mode)
+
// False if the function definitely does not allocate an arguments object.
DECL_BOOLEAN_ACCESSORS(uses_arguments)
@@ -6015,6 +6025,7 @@ class SharedFunctionInfo: public HeapObject {
kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize,
kStrictModeFunction,
kExtendedModeFunction,
+ kQmlModeFunction,
kUsesArguments,
kHasDuplicateParameters,
kNative,
diff --git a/src/3rdparty/v8/src/parser.cc b/src/3rdparty/v8/src/parser.cc
index 129bd95..da4685f 100644
--- a/src/3rdparty/v8/src/parser.cc
+++ b/src/3rdparty/v8/src/parser.cc
@@ -639,6 +639,9 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
FunctionState function_state(this, scope, isolate()); // Enters 'scope'.
top_scope_->SetLanguageMode(info->language_mode());
+ if (info->is_qml_mode()) {
+ scope->EnableQmlModeFlag();
+ }
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
bool ok = true;
int beg_loc = scanner().location().beg_pos;
@@ -745,6 +748,9 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source,
info()->is_extended_mode());
ASSERT(info()->language_mode() == shared_info->language_mode());
scope->SetLanguageMode(shared_info->language_mode());
+ if (shared_info->qml_mode()) {
+ top_scope_->EnableQmlModeFlag();
+ }
FunctionLiteral::Type type = shared_info->is_expression()
? (shared_info->is_anonymous()
? FunctionLiteral::ANONYMOUS_EXPRESSION
@@ -1782,6 +1788,25 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
// both access to the static and the dynamic context chain; the
// runtime needs to provide both.
if (resolve && var != NULL) {
+ if (declaration_scope->is_qml_mode()) {
+ Handle<GlobalObject> global = isolate_->global_object();
+
+#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_object());
+ }
+#endif
+
+ if (!global->HasProperty(*(proxy->name()))) {
+ var->set_is_qml_global(true);
+ }
+ }
+
proxy->BindTo(var);
if (FLAG_harmony_modules) {
@@ -2219,6 +2244,12 @@ Block* Parser::ParseVariableDeclarations(
arguments->Add(value, zone());
value = NULL; // zap the value to avoid the unnecessary assignment
+ int qml_mode = 0;
+ if (top_scope_->is_qml_mode()
+ && !Isolate::Current()->global_object()->HasProperty(*name))
+ qml_mode = 1;
+ arguments->Add(factory()->NewNumberLiteral(qml_mode), zone());
+
// Construct the call to Runtime_InitializeConstGlobal
// and add it to the initialization statement block.
// Note that the function does different things depending on
@@ -2233,6 +2264,12 @@ Block* Parser::ParseVariableDeclarations(
LanguageMode language_mode = initialization_scope->language_mode();
arguments->Add(factory()->NewNumberLiteral(language_mode), zone());
+ int qml_mode = 0;
+ if (top_scope_->is_qml_mode()
+ && !Isolate::Current()->global_object()->HasProperty(*name))
+ qml_mode = 1;
+ arguments->Add(factory()->NewNumberLiteral(qml_mode), zone());
+
// 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,
diff --git a/src/3rdparty/v8/src/prettyprinter.cc b/src/3rdparty/v8/src/prettyprinter.cc
index 0d8dadc..16eb85a 100644
--- a/src/3rdparty/v8/src/prettyprinter.cc
+++ b/src/3rdparty/v8/src/prettyprinter.cc
@@ -672,6 +672,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 a0d8326..088c939 100644
--- a/src/3rdparty/v8/src/runtime.cc
+++ b/src/3rdparty/v8/src/runtime.cc
@@ -1357,19 +1357,24 @@ 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_object());
Handle<Context> context = args.at<Context>(0);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
CONVERT_SMI_ARG_CHECKED(flags, 2);
+ Handle<JSObject> js_global = Handle<JSObject>(isolate->context()->global_object());
+ Handle<JSObject> qml_global = Handle<JSObject>(isolate->context()->qml_global_object());
+
// 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<Object> is_qml_global(pairs->get(i + 2));
+ ASSERT(is_qml_global->IsBoolean());
+
+ Handle<JSObject> global = is_qml_global->IsTrue() ? 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 =
@@ -1569,20 +1574,26 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
NoHandleAllocation nha;
// args[0] == name
// args[1] == language_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_HANDLE_CHECKED(String, name, 0);
- GlobalObject* global = isolate->context()->global_object();
RUNTIME_ASSERT(args[1]->IsSmi());
CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
? kNonStrictMode : kStrictMode;
+ RUNTIME_ASSERT(args[2]->IsSmi());
+ int qml_mode = Smi::cast(args[2])->value();
+
+ JSObject* global = qml_mode ? isolate->context()->qml_global_object()
+ : isolate->context()->global_object();
+
// According to ECMA-262, section 12.2, page 62, the property must
// not be deletable.
PropertyAttributes attributes = DONT_DELETE;
@@ -1610,7 +1621,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_flag);
+ &lookup, *name, args[3], attributes, strict_mode_flag);
} else {
return isolate->heap()->undefined_value();
}
@@ -1620,10 +1631,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
}
// Reload global in case the loop above performed a GC.
- global = isolate->context()->global_object();
+ global = qml_mode ? isolate->context()->qml_global_object()
+ : isolate->context()->global_object();
if (assign) {
return global->SetProperty(
- *name, args[2], attributes, strict_mode_flag, JSReceiver::MAY_BE_STORE_FROM_KEYED, true);
+ *name, args[3], attributes, strict_mode_flag, JSReceiver::MAY_BE_STORE_FROM_KEYED, true);
}
return isolate->heap()->undefined_value();
}
@@ -1633,12 +1645,16 @@ 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_HANDLE_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_object();
+ JSObject* global = qml_mode ? isolate->context()->qml_global_object()
+ : isolate->context()->global_object();
// 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.
@@ -1662,7 +1678,8 @@ 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_object());
+ Handle<JSObject> global(qml_mode ? isolate->context()->qml_global_object()
+ : isolate->context()->global_object());
// BUG 1213575: Handle the case where we have to set a read-only
// property through an interceptor and only do it if it's
@@ -8420,7 +8437,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, function, 0);
- int length = function->shared()->scope_info()->ContextLength();
+ SharedFunctionInfo* shared = function->shared();
+ // TODO: The QML mode should be checked in the ContextLength function.
+ int length = shared->scope_info()->ContextLength(shared->qml_mode());
Context* result;
MaybeObject* maybe_result =
isolate->heap()->AllocateFunctionContext(length, function);
@@ -9116,7 +9135,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
// Compile source string in the native context.
Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
- source, context, true, CLASSIC_MODE, RelocInfo::kNoPosition);
+ source, context, true, CLASSIC_MODE, RelocInfo::kNoPosition, false);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> fun =
isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
@@ -9130,7 +9149,8 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
Handle<String> source,
Handle<Object> receiver,
LanguageMode language_mode,
- int scope_position) {
+ int scope_position,
+ bool qml_mode) {
Handle<Context> context = Handle<Context>(isolate->context());
Handle<Context> native_context = Handle<Context>(context->native_context());
@@ -9152,7 +9172,8 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
Handle<Context>(isolate->context()),
context->IsNativeContext(),
language_mode,
- scope_position);
+ scope_position,
+ qml_mode);
if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
Handle<JSFunction> compiled =
isolate->factory()->NewFunctionFromSharedFunctionInfo(
@@ -9162,7 +9183,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
- ASSERT(args.length() == 5);
+ ASSERT(args.length() == 6);
HandleScope scope(isolate);
Handle<Object> callee = args.at<Object>(0);
@@ -9183,7 +9204,8 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
args.at<String>(1),
args.at<Object>(2),
language_mode,
- args.smi_at(4));
+ args.smi_at(4),
+ Smi::cast(args[5])->value());
}
@@ -11749,6 +11771,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
Handle<ScopeInfo> scope_info(function->shared()->scope_info());
+ bool qml_mode = function->shared()->qml_mode();
// Traverse the saved contexts chain to find the active context for the
// selected frame.
@@ -11830,7 +11853,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
context,
context->IsNativeContext(),
CLASSIC_MODE,
- RelocInfo::kNoPosition);
+ RelocInfo::kNoPosition,
+ qml_mode);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
@@ -11840,7 +11864,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_object()));
if (has_pending_exception) return Failure::Exception();
Handle<Object> arguments = GetArgumentsObject(isolate,
@@ -11936,7 +11961,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
context,
is_global,
CLASSIC_MODE,
- RelocInfo::kNoPosition);
+ RelocInfo::kNoPosition,
+ 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 f63844c..9c3e541 100644
--- a/src/3rdparty/v8/src/runtime.h
+++ b/src/3rdparty/v8/src/runtime.h
@@ -261,7 +261,7 @@ namespace internal {
\
/* Eval */ \
F(GlobalReceiver, 1, 1) \
- F(ResolvePossiblyDirectEval, 5, 2) \
+ F(ResolvePossiblyDirectEval, 6, 2) \
\
F(SetProperty, -1 /* 4 or 5 */, 1) \
F(DefineOrRedefineDataProperty, 4, 1) \
@@ -358,8 +358,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 02b4323..66e2013 100644
--- a/src/3rdparty/v8/src/scopeinfo.cc
+++ b/src/3rdparty/v8/src/scopeinfo.cc
@@ -80,6 +80,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Scope* scope, Zone* zone) {
int flags = TypeField::encode(scope->type()) |
CallsEvalField::encode(scope->calls_eval()) |
LanguageModeField::encode(scope->language_mode()) |
+ QmlModeField::encode(scope->is_qml_mode()) |
FunctionVariableField::encode(function_name_info) |
FunctionVariableMode::encode(function_variable_mode);
scope_info->SetFlags(flags);
@@ -170,6 +171,11 @@ LanguageMode ScopeInfo::language_mode() {
}
+bool ScopeInfo::IsQmlMode() {
+ return length() > 0 && QmlModeField::decode(Flags());
+}
+
+
int ScopeInfo::LocalCount() {
return StackLocalCount() + ContextLocalCount();
}
@@ -185,7 +191,7 @@ int ScopeInfo::StackSlotCount() {
}
-int ScopeInfo::ContextLength() {
+int ScopeInfo::ContextLength(bool qml_function) {
if (length() > 0) {
int context_locals = ContextLocalCount();
bool function_name_context_slot =
@@ -195,7 +201,8 @@ int ScopeInfo::ContextLength() {
Type() == WITH_SCOPE ||
(Type() == FUNCTION_SCOPE && CallsEval()) ||
Type() == MODULE_SCOPE;
- if (has_context) {
+ // TODO: The QML mode should be checked in the has_context expression.
+ if (has_context || qml_function) {
return Context::MIN_CONTEXT_SLOTS + context_locals +
(function_name_context_slot ? 1 : 0);
}
diff --git a/src/3rdparty/v8/src/scopes.cc b/src/3rdparty/v8/src/scopes.cc
index c961257..d2a919a 100644
--- a/src/3rdparty/v8/src/scopes.cc
+++ b/src/3rdparty/v8/src/scopes.cc
@@ -37,6 +37,8 @@
#include "allocation-inl.h"
+#include "debug.h"
+
namespace v8 {
namespace internal {
@@ -191,6 +193,8 @@ void Scope::SetDefaults(ScopeType type,
// Inherit the strict mode from the parent scope.
language_mode_ = (outer_scope != NULL)
? outer_scope->language_mode_ : CLASSIC_MODE;
+ qml_mode_flag_ = (outer_scope != NULL)
+ ? outer_scope->qml_mode_flag_ : kNonQmlMode;
outer_scope_calls_non_strict_eval_ = false;
inner_scope_calls_eval_ = false;
force_eager_compilation_ = false;
@@ -1029,6 +1033,24 @@ bool Scope::ResolveVariable(CompilationInfo* info,
switch (binding_kind) {
case BOUND:
// We found a variable binding.
+ if (is_qml_mode()) {
+ Handle<GlobalObject> global = isolate_->global_object();
+
+#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_object());
+ }
+#endif
+
+ if (!global->HasProperty(*(proxy->name()))) {
+ var->set_is_qml_global(true);
+ }
+ }
break;
case BOUND_EVAL_SHADOWED:
@@ -1038,6 +1060,25 @@ bool Scope::ResolveVariable(CompilationInfo* info,
// debugger to evaluate arbitrary expressions at a break point).
if (var->IsGlobalObjectProperty()) {
var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
+
+ if (is_qml_mode()) {
+ Handle<GlobalObject> global = isolate_->global_object();
+
+#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_object());
+ }
+#endif
+
+ if (!global->HasProperty(*(proxy->name()))) {
+ var->set_is_qml_global(true);
+ }
+ }
} else if (var->is_dynamic()) {
var = NonLocal(proxy->name(), DYNAMIC);
} else {
@@ -1050,12 +1091,52 @@ bool Scope::ResolveVariable(CompilationInfo* info,
case UNBOUND:
// No binding has been found. Declare a variable on the global object.
var = info->global_scope()->DeclareDynamicGlobal(proxy->name());
+
+ if (is_qml_mode()) {
+ Handle<GlobalObject> global = isolate_->global_object();
+
+#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_object());
+ }
+#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 (is_qml_mode()) {
+ Handle<GlobalObject> global = isolate_->global_object();
+
+#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_object());
+ }
+#endif
+
+ if (!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 b9d151c..e9425f0 100644
--- a/src/3rdparty/v8/src/scopes.h
+++ b/src/3rdparty/v8/src/scopes.h
@@ -237,6 +237,11 @@ class Scope: public ZoneObject {
language_mode_ = language_mode;
}
+ // Enable qml mode for this scope
+ void EnableQmlModeFlag() {
+ qml_mode_flag_ = kQmlMode;
+ }
+
// Position in the source where this scope begins and ends.
//
// * For the scope of a with statement
@@ -292,6 +297,7 @@ class Scope: public ZoneObject {
bool is_strict_or_extended_eval_scope() const {
return is_eval_scope() && !is_classic_mode();
}
+ bool is_qml_mode() const { return qml_mode_flag() == kQmlMode; }
// Information about which scopes calls eval.
bool calls_eval() const { return scope_calls_eval_; }
@@ -316,6 +322,9 @@ class Scope: public ZoneObject {
// The language mode of this scope.
LanguageMode language_mode() const { return language_mode_; }
+ // The strict mode of this scope.
+ QmlModeFlag qml_mode_flag() const { return qml_mode_flag_; }
+
// The variable corresponding the 'this' value.
Variable* receiver() { return receiver_; }
@@ -474,6 +483,8 @@ class Scope: public ZoneObject {
bool scope_calls_eval_;
// The language mode of this scope.
LanguageMode language_mode_;
+ // This scope is a qml mode scope.
+ QmlModeFlag qml_mode_flag_;
// Source positions.
int start_position_;
int end_position_;
diff --git a/src/3rdparty/v8/src/stub-cache.cc b/src/3rdparty/v8/src/stub-cache.cc
index 5eb0cba..3885462 100644
--- a/src/3rdparty/v8/src/stub-cache.cc
+++ b/src/3rdparty/v8/src/stub-cache.cc
@@ -809,7 +809,8 @@ Handle<Code> StubCache::ComputeCallPreMonomorphic(
Handle<Code> StubCache::ComputeCallNormal(int argc,
Code::Kind kind,
- Code::ExtraICState extra_state) {
+ Code::ExtraICState extra_state,
+ bool has_qml_global_receiver) {
Code::Flags flags =
Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc);
Handle<UnseededNumberDictionary> cache =
@@ -818,7 +819,7 @@ Handle<Code> StubCache::ComputeCallNormal(int argc,
if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
StubCompiler compiler(isolate_);
- Handle<Code> code = compiler.CompileCallNormal(flags);
+ Handle<Code> code = compiler.CompileCallNormal(flags, has_qml_global_receiver);
FillCache(isolate_, code);
return code;
}
@@ -1234,13 +1235,15 @@ Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
}
-Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
+Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags, bool has_qml_global_receiver) {
int argc = Code::ExtractArgumentsCountFromFlags(flags);
Code::Kind kind = Code::ExtractKindFromFlags(flags);
if (kind == Code::CALL_IC) {
- // Call normal is always with a explict receiver.
+ // Call normal is always with a explict receiver,
+ // or with an implicit qml global receiver.
ASSERT(!CallIC::Contextual::decode(
- Code::ExtractExtraICStateFromFlags(flags)));
+ Code::ExtractExtraICStateFromFlags(flags)) ||
+ has_qml_global_receiver);
CallIC::GenerateNormal(masm(), argc);
} else {
KeyedCallIC::GenerateNormal(masm(), argc);
diff --git a/src/3rdparty/v8/src/stub-cache.h b/src/3rdparty/v8/src/stub-cache.h
index 005c537..ec9274b 100644
--- a/src/3rdparty/v8/src/stub-cache.h
+++ b/src/3rdparty/v8/src/stub-cache.h
@@ -231,7 +231,8 @@ class StubCache {
Handle<Code> ComputeCallNormal(int argc,
Code::Kind kind,
- Code::ExtraICState state);
+ Code::ExtraICState state,
+ bool has_qml_global_receiver);
Handle<Code> ComputeCallArguments(int argc, Code::Kind kind);
@@ -423,7 +424,7 @@ class StubCompiler BASE_EMBEDDED {
// is extracted from the code flags.
Handle<Code> CompileCallInitialize(Code::Flags flags);
Handle<Code> CompileCallPreMonomorphic(Code::Flags flags);
- Handle<Code> CompileCallNormal(Code::Flags flags);
+ Handle<Code> CompileCallNormal(Code::Flags flags, bool has_qml_global_receiver);
Handle<Code> CompileCallMegamorphic(Code::Flags flags);
Handle<Code> CompileCallArguments(Code::Flags flags);
Handle<Code> CompileCallMiss(Code::Flags flags);
diff --git a/src/3rdparty/v8/src/variables.cc b/src/3rdparty/v8/src/variables.cc
index 0416f3a..3e735d6 100644
--- a/src/3rdparty/v8/src/variables.cc
+++ b/src/3rdparty/v8/src/variables.cc
@@ -73,7 +73,8 @@ Variable::Variable(Scope* scope,
force_context_allocation_(false),
is_used_(false),
initialization_flag_(initialization_flag),
- interface_(interface) {
+ interface_(interface),
+ is_qml_global_(false) {
// Names must be canonicalized for fast equality checks.
ASSERT(name->IsSymbol());
// Var declared variables never need initialization.
diff --git a/src/3rdparty/v8/src/variables.h b/src/3rdparty/v8/src/variables.h
index ba26b80..d4e851b 100644
--- a/src/3rdparty/v8/src/variables.h
+++ b/src/3rdparty/v8/src/variables.h
@@ -157,6 +157,9 @@ class Variable: public ZoneObject {
static int CompareIndex(Variable* const* v, Variable* const* w);
+ 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_;
@@ -182,6 +185,9 @@ class Variable: public ZoneObject {
// Module type info.
Interface* interface_;
+
+ // 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 a8e52e9..8543094 100644
--- a/src/3rdparty/v8/src/x64/code-stubs-x64.cc
+++ b/src/3rdparty/v8/src/x64/code-stubs-x64.cc
@@ -220,6 +220,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
__ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)), rbx);
+ // Copy the qmlglobal object from the previous context.
+ __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::QML_GLOBAL_OBJECT_INDEX)));
+ __ movq(Operand(rax, Context::SlotOffset(Context::QML_GLOBAL_OBJECT_INDEX)), rbx);
+
// Initialize the rest of the slots to undefined.
__ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
@@ -284,6 +288,10 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
__ movq(rbx, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX));
__ movq(ContextOperand(rax, Context::GLOBAL_OBJECT_INDEX), rbx);
+ // Copy the qmlglobal object from the previous context.
+ __ movq(rbx, ContextOperand(rsi, Context::QML_GLOBAL_OBJECT_INDEX));
+ __ movq(ContextOperand(rax, Context::QML_GLOBAL_OBJECT_INDEX), rbx);
+
// Initialize the rest of the slots to the hole value.
__ LoadRoot(rbx, Heap::kTheHoleValueRootIndex);
for (int i = 0; i < slots_; i++) {
diff --git a/src/3rdparty/v8/src/x64/full-codegen-x64.cc b/src/3rdparty/v8/src/x64/full-codegen-x64.cc
index a198739..a71c9b1 100644
--- a/src/3rdparty/v8/src/x64/full-codegen-x64.cc
+++ b/src/3rdparty/v8/src/x64/full-codegen-x64.cc
@@ -177,7 +177,8 @@ void FullCodeGenerator::Generate() {
// 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 context");
// Argument to NewContext is the function, which is still in rdi.
__ push(rdi);
@@ -185,7 +186,7 @@ void FullCodeGenerator::Generate() {
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
- FastNewContextStub stub(heap_slots);
+ FastNewContextStub stub((heap_slots < 0) ? 0 : heap_slots);
__ CallStub(&stub);
} else {
__ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -793,6 +794,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
? isolate()->factory()->the_hole_value()
: isolate()->factory()->undefined_value(),
zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
break;
case Variable::PARAMETER:
@@ -852,6 +854,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
// Check for stack-overflow exception.
if (function.is_null()) return SetStackOverflow();
globals_->Add(function, zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
break;
}
@@ -905,6 +908,7 @@ void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
Comment cmnt(masm_, "[ ModuleDeclaration");
globals_->Add(variable->name(), zone());
globals_->Add(instance, zone());
+ globals_->Add(isolate()->factory()->ToBoolean(variable->is_qml_global()), zone());
Visit(declaration->module());
break;
}
@@ -1317,7 +1321,7 @@ 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)
@@ -1402,7 +1406,7 @@ 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();
CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
context()->Plug(rax);
@@ -2031,7 +2035,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_classic_mode()
? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict();
@@ -2287,8 +2291,11 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
// Push the start position of the scope the calls resides in.
__ Push(Smi::FromInt(scope()->start_position()));
+ // Push the qml mode flag
+ __ Push(Smi::FromInt(is_qml_mode()));
+
// Do the runtime call.
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
}
@@ -2341,7 +2348,7 @@ 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());
+ __ push(proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
// Call to a lookup slot (dynamically introduced variable).
@@ -3818,7 +3825,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// but "delete this" is allowed.
ASSERT(language_mode() == CLASSIC_MODE || 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);
@@ -4141,7 +4148,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 4596aca..a948ccc 100644
--- a/src/3rdparty/v8/src/x64/lithium-codegen-x64.cc
+++ b/src/3rdparty/v8/src/x64/lithium-codegen-x64.cc
@@ -181,12 +181,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);
@@ -2988,7 +2989,7 @@ void LCodeGen::DoDeclareGlobals(LDeclareGlobals* 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/3rdparty/v8/src/x64/lithium-x64.cc b/src/3rdparty/v8/src/x64/lithium-x64.cc
index c6004e5..3985dc0 100644
--- a/src/3rdparty/v8/src/x64/lithium-x64.cc
+++ b/src/3rdparty/v8/src/x64/lithium-x64.cc
@@ -999,7 +999,7 @@ LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
- return DefineAsRegister(new(zone()) LGlobalObject);
+ return DefineAsRegister(new(zone()) LGlobalObject(instr->qml_global()));
}
@@ -1069,7 +1069,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) 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 5439028..a437a2b 100644
--- a/src/3rdparty/v8/src/x64/lithium-x64.h
+++ b/src/3rdparty/v8/src/x64/lithium-x64.h
@@ -1546,7 +1546,13 @@ class LDeclareGlobals: public LTemplateInstruction<0, 0, 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_;
};
@@ -1640,10 +1646,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 cc057ac..fdddc13 100644
--- a/src/3rdparty/v8/src/x64/macro-assembler-x64.h
+++ b/src/3rdparty/v8/src/x64/macro-assembler-x64.h
@@ -1467,6 +1467,11 @@ inline Operand GlobalObjectOperand() {
}
+static inline Operand QmlGlobalObjectOperand() {
+ return ContextOperand(rsi, Context::QML_GLOBAL_OBJECT_INDEX);
+}
+
+
// Provides access to exit frame stack space (not GCed).
inline Operand StackSpaceOperand(int index) {
#ifdef _WIN64
diff --git a/src/3rdparty/v8/test/cctest/test-api.cc b/src/3rdparty/v8/test/cctest/test-api.cc
index 41eb68f..f7325df 100644
--- a/src/3rdparty/v8/test/cctest/test-api.cc
+++ b/src/3rdparty/v8/test/cctest/test-api.cc
@@ -15155,6 +15155,7 @@ TEST(Regress528) {
v8::Persistent<Context> context;
v8::Persistent<Context> other_context;
int gc_count;
+ bool snapshot_enabled = i::Snapshot::IsEnabled();
// Create a context used to keep the code from aging in the compilation
// cache.
@@ -15180,10 +15181,10 @@ TEST(Regress528) {
CompileRun(source_simple);
other_context->Exit();
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
- if (GetGlobalObjectsCount() == 1) break;
+ if (GetGlobalObjectsCount() == (snapshot_enabled ? 2 : 1)) break;
}
CHECK_GE(2, gc_count);
- CHECK_EQ(1, GetGlobalObjectsCount());
+ CHECK_EQ((snapshot_enabled ? 2 : 1), GetGlobalObjectsCount());
// Eval in a function creates reference from the compilation cache to the
// global object.
@@ -15203,10 +15204,10 @@ TEST(Regress528) {
CompileRun(source_eval);
other_context->Exit();
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
- if (GetGlobalObjectsCount() == 1) break;
+ if (GetGlobalObjectsCount() == (snapshot_enabled ? 2 : 1)) break;
}
CHECK_GE(2, gc_count);
- CHECK_EQ(1, GetGlobalObjectsCount());
+ CHECK_EQ((snapshot_enabled ? 2 : 1), GetGlobalObjectsCount());
// Looking up the line number for an exception creates reference from the
// compilation cache to the global object.
@@ -15231,10 +15232,10 @@ TEST(Regress528) {
CompileRun(source_exception);
other_context->Exit();
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
- if (GetGlobalObjectsCount() == 1) break;
+ if (GetGlobalObjectsCount() == (snapshot_enabled ? 2 : 1)) break;
}
CHECK_GE(2, gc_count);
- CHECK_EQ(1, GetGlobalObjectsCount());
+ CHECK_EQ((snapshot_enabled ? 2 : 1), GetGlobalObjectsCount());
other_context.Dispose();
v8::V8::ContextDisposedNotification();
diff --git a/src/3rdparty/v8/test/cctest/test-heap-profiler.cc b/src/3rdparty/v8/test/cctest/test-heap-profiler.cc
index 5235971..2a60785 100644
--- a/src/3rdparty/v8/test/cctest/test-heap-profiler.cc
+++ b/src/3rdparty/v8/test/cctest/test-heap-profiler.cc
@@ -66,9 +66,11 @@ class NamedEntriesDetector {
static const v8::HeapGraphNode* GetGlobalObject(
const v8::HeapSnapshot* snapshot) {
- CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount());
+ bool snapshot_enabled = i::Snapshot::IsEnabled();
+
+ CHECK_EQ((snapshot_enabled ? 3 : 2), snapshot->GetRoot()->GetChildrenCount());
const v8::HeapGraphNode* global_obj =
- snapshot->GetRoot()->GetChild(0)->GetToNode();
+ snapshot->GetRoot()->GetChild(snapshot_enabled ? 1 : 0)->GetToNode();
CHECK_EQ(0, strncmp("Object", const_cast<i::HeapEntry*>(
reinterpret_cast<const i::HeapEntry*>(global_obj))->name(), 6));
return global_obj;
@@ -601,14 +603,28 @@ TEST(HeapSnapshotJSONSerialization) {
" return null;\n"
"}\n");
// Get the string index using the path: <root> -> <global>.b.x.s
- v8::Local<v8::Value> string_obj_pos_val = CompileRun(
- "GetChildPosByProperty(\n"
- " GetChildPosByProperty(\n"
- " GetChildPosByProperty("
- " parsed.edges[edge_to_node_offset],"
- " \"b\", property_type),\n"
- " \"x\", property_type),"
- " \"s\", property_type)");
+ v8::Local<v8::Value> string_obj_pos_val;
+ if (i::Snapshot::IsEnabled()) {
+ // TODO(pvarga): Check shortcut_type issue at b when QML global object is used.
+ string_obj_pos_val = CompileRun(
+ "GetChildPosByProperty(\n"
+ " GetChildPosByProperty(\n"
+ " GetChildPosByProperty("
+ " parsed.edges[edge_to_node_offset"
+ " + edge_fields_count],"
+ " \"b\", property_type),\n"
+ " \"x\", property_type),"
+ " \"s\", property_type)");
+ } else {
+ string_obj_pos_val = CompileRun(
+ "GetChildPosByProperty(\n"
+ " GetChildPosByProperty(\n"
+ " GetChildPosByProperty("
+ " parsed.edges[edge_to_node_offset],"
+ " \"b\", property_type),\n"
+ " \"x\", property_type),"
+ " \"s\", property_type)");
+ }
CHECK(!string_obj_pos_val.IsEmpty());
int string_obj_pos =
static_cast<int>(string_obj_pos_val->ToNumber()->Value());
@@ -1571,6 +1587,8 @@ TEST(NoDebugObjectInSnapshot) {
const v8::HeapGraphNode* root = snapshot->GetRoot();
int globals_count = 0;
for (int i = 0; i < root->GetChildrenCount(); ++i) {
+ // QML global object should be skipped here when snapshot is enabled.
+ if (i::Snapshot::IsEnabled() && i % 2 == 0) continue;
const v8::HeapGraphEdge* edge = root->GetChild(i);
if (edge->GetType() == v8::HeapGraphEdge::kShortcut) {
++globals_count;
diff --git a/src/3rdparty/v8/test/cctest/test-heap.cc b/src/3rdparty/v8/test/cctest/test-heap.cc
index 2bb3af6..0d72ff7 100644
--- a/src/3rdparty/v8/test/cctest/test-heap.cc
+++ b/src/3rdparty/v8/test/cctest/test-heap.cc
@@ -11,6 +11,7 @@
#include "global-handles.h"
#include "stub-cache.h"
#include "cctest.h"
+#include "snapshot.h"
using namespace v8::internal;
@@ -1577,13 +1578,14 @@ static int NumberOfGlobalObjects() {
// optimized code.
TEST(LeakNativeContextViaMap) {
i::FLAG_allow_natives_syntax = true;
+ bool snapshot_enabled = i::Snapshot::IsEnabled();
v8::HandleScope outer_scope;
v8::Persistent<v8::Context> ctx1 = v8::Context::New();
v8::Persistent<v8::Context> ctx2 = v8::Context::New();
ctx1->Enter();
HEAP->CollectAllAvailableGarbage();
- CHECK_EQ(4, NumberOfGlobalObjects());
+ CHECK_EQ((snapshot_enabled ? 6 : 4), NumberOfGlobalObjects());
{
v8::HandleScope inner_scope;
@@ -1604,7 +1606,7 @@ TEST(LeakNativeContextViaMap) {
v8::V8::ContextDisposedNotification();
}
HEAP->CollectAllAvailableGarbage();
- CHECK_EQ(2, NumberOfGlobalObjects());
+ CHECK_EQ((snapshot_enabled ? 3 : 2), NumberOfGlobalObjects());
ctx2.Dispose();
HEAP->CollectAllAvailableGarbage();
CHECK_EQ(0, NumberOfGlobalObjects());
@@ -1615,13 +1617,14 @@ TEST(LeakNativeContextViaMap) {
// optimized code.
TEST(LeakNativeContextViaFunction) {
i::FLAG_allow_natives_syntax = true;
+ bool snapshot_enabled = i::Snapshot::IsEnabled();
v8::HandleScope outer_scope;
v8::Persistent<v8::Context> ctx1 = v8::Context::New();
v8::Persistent<v8::Context> ctx2 = v8::Context::New();
ctx1->Enter();
HEAP->CollectAllAvailableGarbage();
- CHECK_EQ(4, NumberOfGlobalObjects());
+ CHECK_EQ((snapshot_enabled ? 6 : 4), NumberOfGlobalObjects());
{
v8::HandleScope inner_scope;
@@ -1642,7 +1645,7 @@ TEST(LeakNativeContextViaFunction) {
v8::V8::ContextDisposedNotification();
}
HEAP->CollectAllAvailableGarbage();
- CHECK_EQ(2, NumberOfGlobalObjects());
+ CHECK_EQ((snapshot_enabled ? 3 : 2), NumberOfGlobalObjects());
ctx2.Dispose();
HEAP->CollectAllAvailableGarbage();
CHECK_EQ(0, NumberOfGlobalObjects());
@@ -1651,13 +1654,14 @@ TEST(LeakNativeContextViaFunction) {
TEST(LeakNativeContextViaMapKeyed) {
i::FLAG_allow_natives_syntax = true;
+ bool snapshot_enabled = i::Snapshot::IsEnabled();
v8::HandleScope outer_scope;
v8::Persistent<v8::Context> ctx1 = v8::Context::New();
v8::Persistent<v8::Context> ctx2 = v8::Context::New();
ctx1->Enter();
HEAP->CollectAllAvailableGarbage();
- CHECK_EQ(4, NumberOfGlobalObjects());
+ CHECK_EQ((snapshot_enabled ? 6 : 4), NumberOfGlobalObjects());
{
v8::HandleScope inner_scope;
@@ -1678,7 +1682,7 @@ TEST(LeakNativeContextViaMapKeyed) {
v8::V8::ContextDisposedNotification();
}
HEAP->CollectAllAvailableGarbage();
- CHECK_EQ(2, NumberOfGlobalObjects());
+ CHECK_EQ((snapshot_enabled ? 3 : 2), NumberOfGlobalObjects());
ctx2.Dispose();
HEAP->CollectAllAvailableGarbage();
CHECK_EQ(0, NumberOfGlobalObjects());
@@ -1687,13 +1691,14 @@ TEST(LeakNativeContextViaMapKeyed) {
TEST(LeakNativeContextViaMapProto) {
i::FLAG_allow_natives_syntax = true;
+ bool snapshot_enabled = i::Snapshot::IsEnabled();
v8::HandleScope outer_scope;
v8::Persistent<v8::Context> ctx1 = v8::Context::New();
v8::Persistent<v8::Context> ctx2 = v8::Context::New();
ctx1->Enter();
HEAP->CollectAllAvailableGarbage();
- CHECK_EQ(4, NumberOfGlobalObjects());
+ CHECK_EQ((snapshot_enabled ? 6 : 4), NumberOfGlobalObjects());
{
v8::HandleScope inner_scope;
@@ -1718,7 +1723,7 @@ TEST(LeakNativeContextViaMapProto) {
v8::V8::ContextDisposedNotification();
}
HEAP->CollectAllAvailableGarbage();
- CHECK_EQ(2, NumberOfGlobalObjects());
+ CHECK_EQ((snapshot_enabled ? 3 : 2), NumberOfGlobalObjects());
ctx2.Dispose();
HEAP->CollectAllAvailableGarbage();
CHECK_EQ(0, NumberOfGlobalObjects());