[V8] Introduce a QML compilation mode
authorAaron Kennedy <aaron.kennedy@nokia.com>
Thu, 27 Oct 2011 12:34:16 +0000 (13:34 +0100)
committerQt by Nokia <qt-info@nokia.com>
Thu, 1 Mar 2012 11:03:42 +0000 (12:03 +0100)
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: Ib6b4ed363b7e8089d38a9cdcfb0d3b314dc333ca
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
53 files changed:
src/3rdparty/v8/include/v8.h
src/3rdparty/v8/src/api.cc
src/3rdparty/v8/src/arm/code-stubs-arm.cc
src/3rdparty/v8/src/arm/full-codegen-arm.cc
src/3rdparty/v8/src/arm/lithium-arm.cc
src/3rdparty/v8/src/arm/lithium-arm.h
src/3rdparty/v8/src/arm/lithium-codegen-arm.cc
src/3rdparty/v8/src/arm/macro-assembler-arm.h
src/3rdparty/v8/src/ast-inl.h
src/3rdparty/v8/src/ast.cc
src/3rdparty/v8/src/ast.h
src/3rdparty/v8/src/bootstrapper.cc
src/3rdparty/v8/src/code-stubs.h
src/3rdparty/v8/src/compiler.cc
src/3rdparty/v8/src/compiler.h
src/3rdparty/v8/src/contexts.cc
src/3rdparty/v8/src/contexts.h
src/3rdparty/v8/src/execution.cc
src/3rdparty/v8/src/execution.h
src/3rdparty/v8/src/full-codegen.cc
src/3rdparty/v8/src/full-codegen.h
src/3rdparty/v8/src/heap.cc
src/3rdparty/v8/src/hydrogen-instructions.cc
src/3rdparty/v8/src/hydrogen-instructions.h
src/3rdparty/v8/src/hydrogen.cc
src/3rdparty/v8/src/ia32/code-stubs-ia32.cc
src/3rdparty/v8/src/ia32/full-codegen-ia32.cc
src/3rdparty/v8/src/ia32/lithium-codegen-ia32.cc
src/3rdparty/v8/src/ia32/lithium-ia32.cc
src/3rdparty/v8/src/ia32/lithium-ia32.h
src/3rdparty/v8/src/ia32/macro-assembler-ia32.h
src/3rdparty/v8/src/mips/code-stubs-mips.cc
src/3rdparty/v8/src/mips/full-codegen-mips.cc
src/3rdparty/v8/src/mips/macro-assembler-mips.h
src/3rdparty/v8/src/objects-inl.h
src/3rdparty/v8/src/objects.h
src/3rdparty/v8/src/parser.cc
src/3rdparty/v8/src/parser.h
src/3rdparty/v8/src/prettyprinter.cc
src/3rdparty/v8/src/runtime.cc
src/3rdparty/v8/src/runtime.h
src/3rdparty/v8/src/scopeinfo.cc
src/3rdparty/v8/src/scopeinfo.h
src/3rdparty/v8/src/scopes.cc
src/3rdparty/v8/src/scopes.h
src/3rdparty/v8/src/variables.cc
src/3rdparty/v8/src/variables.h
src/3rdparty/v8/src/x64/code-stubs-x64.cc
src/3rdparty/v8/src/x64/full-codegen-x64.cc
src/3rdparty/v8/src/x64/lithium-codegen-x64.cc
src/3rdparty/v8/src/x64/lithium-x64.cc
src/3rdparty/v8/src/x64/lithium-x64.h
src/3rdparty/v8/src/x64/macro-assembler-x64.h

index 3ef4dd6..193e2fe 100644 (file)
@@ -587,6 +587,11 @@ class ScriptOrigin {
  */
 class V8EXPORT Script {
  public:
+  enum CompileFlags {
+      Default = 0x00,
+      QmlMode = 0x01
+  };
+
   /**
    * Compiles the specified script (context-independent).
    *
@@ -605,7 +610,8 @@ class V8EXPORT Script {
   static Local<Script> New(Handle<String> source,
                            ScriptOrigin* origin = NULL,
                            ScriptData* pre_data = NULL,
-                           Handle<String> script_data = Handle<String>());
+                           Handle<String> script_data = Handle<String>(),
+                           CompileFlags = Default);
 
   /**
    * Compiles the specified script using the specified file name
@@ -618,7 +624,8 @@ class V8EXPORT Script {
    *   will use the currently entered context).
    */
   static Local<Script> New(Handle<String> source,
-                           Handle<Value> file_name);
+                           Handle<Value> file_name,
+                           CompileFlags = Default);
 
   /**
    * Compiles the specified script (bound to current context).
@@ -639,7 +646,8 @@ class V8EXPORT Script {
   static Local<Script> Compile(Handle<String> source,
                                ScriptOrigin* origin = NULL,
                                ScriptData* pre_data = NULL,
-                               Handle<String> script_data = Handle<String>());
+                               Handle<String> script_data = Handle<String>(),
+                               CompileFlags = Default);
 
   /**
    * Compiles the specified script using the specified file name
@@ -656,7 +664,8 @@ class V8EXPORT Script {
    */
   static Local<Script> Compile(Handle<String> source,
                                Handle<Value> file_name,
-                               Handle<String> script_data = Handle<String>());
+                               Handle<String> script_data = Handle<String>(),
+                               CompileFlags = Default);
 
   /**
    * Runs the script returning the resulting value.  If the script is
@@ -666,6 +675,7 @@ class V8EXPORT Script {
    * compiled.
    */
   Local<Value> Run();
+  Local<Value> Run(Handle<Object> qml);
 
   /**
    * Returns the script id value.
@@ -3506,6 +3516,7 @@ class V8EXPORT Context {
    * JavaScript frames an empty handle is returned.
    */
   static Local<Context> GetCalling();
+  static Local<Object> GetCallingQmlGlobal();
 
   /**
    * Sets the security token for the context.  To access an object in
index a373d78..780d1bb 100644 (file)
@@ -1514,7 +1514,8 @@ ScriptData* ScriptData::New(const char* data, int length) {
 Local<Script> Script::New(v8::Handle<String> source,
                           v8::ScriptOrigin* origin,
                           v8::ScriptData* pre_data,
-                          v8::Handle<String> script_data) {
+                          v8::Handle<String> script_data,
+                          v8::Script::CompileFlags compile_flags) {
   i::Isolate* isolate = i::Isolate::Current();
   ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>());
   LOG_API(isolate, "Script::New");
@@ -1551,7 +1552,8 @@ Local<Script> Script::New(v8::Handle<String> source,
                            NULL,
                            pre_data_impl,
                            Utils::OpenHandle(*script_data),
-                           i::NOT_NATIVES_CODE);
+                           i::NOT_NATIVES_CODE,
+                           compile_flags);
   has_pending_exception = result.is_null();
   EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
   return Local<Script>(ToApi<Script>(result));
@@ -1559,21 +1561,23 @@ Local<Script> Script::New(v8::Handle<String> source,
 
 
 Local<Script> Script::New(v8::Handle<String> source,
-                          v8::Handle<Value> file_name) {
+                          v8::Handle<Value> file_name,
+                          v8::Script::CompileFlags compile_flags) {
   ScriptOrigin origin(file_name);
-  return New(source, &origin);
+  return New(source, &origin, 0, Handle<String>(), compile_flags);
 }
 
 
 Local<Script> Script::Compile(v8::Handle<String> source,
                               v8::ScriptOrigin* origin,
                               v8::ScriptData* pre_data,
-                              v8::Handle<String> script_data) {
+                              v8::Handle<String> script_data,
+                              v8::Script::CompileFlags compile_flags) {
   i::Isolate* isolate = i::Isolate::Current();
   ON_BAILOUT(isolate, "v8::Script::Compile()", return Local<Script>());
   LOG_API(isolate, "Script::Compile");
   ENTER_V8(isolate);
-  Local<Script> generic = New(source, origin, pre_data, script_data);
+  Local<Script> generic = New(source, origin, pre_data, script_data, compile_flags);
   if (generic.IsEmpty())
     return generic;
   i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
@@ -1589,13 +1593,18 @@ Local<Script> Script::Compile(v8::Handle<String> source,
 
 Local<Script> Script::Compile(v8::Handle<String> source,
                               v8::Handle<Value> file_name,
-                              v8::Handle<String> script_data) {
+                              v8::Handle<String> script_data,
+                              v8::Script::CompileFlags compile_flags) {
   ScriptOrigin origin(file_name);
-  return Compile(source, &origin, 0, script_data);
+  return Compile(source, &origin, 0, script_data, compile_flags);
 }
 
 
 Local<Value> Script::Run() {
+    return Run(Handle<Object>());
+}
+
+Local<Value> Script::Run(Handle<Object> qml) {
   i::Isolate* isolate = i::Isolate::Current();
   ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>());
   LOG_API(isolate, "Script::Run");
@@ -1614,10 +1623,11 @@ Local<Value> Script::Run() {
       fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate);
     }
     EXCEPTION_PREAMBLE(isolate);
+    i::Handle<i::Object> qmlglobal = Utils::OpenHandle(*qml);
     i::Handle<i::Object> receiver(
         isolate->context()->global_proxy(), isolate);
     i::Handle<i::Object> result =
-        i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
+        i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception, false, qmlglobal);
     EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
     raw_result = *result;
   }
@@ -4337,6 +4347,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()->IsUndefined()) {
+    i::Handle<i::Object> qmlglobal(context->qml_global());
+    return Utils::ToLocal(i::Handle<i::JSObject>::cast(qmlglobal));
+  } else {
+      return Local<Object>();
+  }
+}
+
+
 v8::Local<v8::Object> Context::Global() {
   if (IsDeadCheck(i::Isolate::Current(), "v8::Context::Global()")) {
     return Local<v8::Object>();
index 7a541f5..b962bc7 100644 (file)
@@ -172,6 +172,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
   __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ str(r1, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX)));
 
+  // Copy the qml global object from the surrounding context.
+  __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
+  __ str(r1, MemOperand(r0, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
+
   // Initialize the rest of the slots to undefined.
   __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
   for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
@@ -238,6 +242,10 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
   __ ldr(r1, ContextOperand(cp, Context::GLOBAL_INDEX));
   __ str(r1, ContextOperand(r0, Context::GLOBAL_INDEX));
 
+  // Copy the qml global object from the surrounding context.
+  __ ldr(r1, ContextOperand(cp, Context::QML_GLOBAL_INDEX));
+  __ str(r1, ContextOperand(r0, Context::QML_GLOBAL_INDEX));
+
   // Initialize the rest of the slots to the hole value.
   __ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
   for (int i = 0; i < slots_; i++) {
index d0c663b..a2fa27a 100644 (file)
@@ -177,12 +177,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
 
   // Possibly allocate a local context.
   int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
-  if (heap_slots > 0) {
+  if (heap_slots > 0 ||
+      (scope()->is_qml_mode() && scope()->is_global_scope())) {
     Comment cmnt(masm_, "[ Allocate local context");
     // Argument to NewContext is the function, which is in r1.
     __ push(r1);
     if (heap_slots <= FastNewContextStub::kMaximumSlots) {
-      FastNewContextStub stub(heap_slots);
+      FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
       __ CallStub(&stub);
     } else {
       __ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -1182,9 +1183,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
     __ bind(&fast);
   }
 
-  __ ldr(r0, GlobalObjectOperand());
+  __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
   __ mov(r2, Operand(var->name()));
-  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
+  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || var->is_qml_global())
       ? RelocInfo::CODE_TARGET
       : RelocInfo::CODE_TARGET_CONTEXT;
   Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
@@ -1269,10 +1270,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       Comment cmnt(masm_, "Global variable");
       // Use inline caching. Variable name is passed in r2 and the global
       // object (receiver) in r0.
-      __ ldr(r0, GlobalObjectOperand());
+      __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
       __ mov(r2, Operand(var->name()));
       Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
-      __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+      __ Call(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
       context()->Plug(r0);
       break;
     }
@@ -1909,7 +1910,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
   if (var->IsUnallocated()) {
     // Global var, const, or let.
     __ mov(r2, Operand(var->name()));
-    __ ldr(r1, GlobalObjectOperand());
+    __ ldr(r1, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
     Handle<Code> ic = is_strict_mode()
         ? isolate()->builtins()->StoreIC_Initialize_Strict()
         : isolate()->builtins()->StoreIC_Initialize();
@@ -2208,8 +2209,11 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
       FLAG_harmony_scoping ? kStrictMode : strict_mode_flag();
   __ mov(r1, Operand(Smi::FromInt(strict_mode)));
   __ push(r1);
+  // Push the qml mode flag.
+  __ mov(r1, Operand(Smi::FromInt(is_qml_mode())));
+  __ push(r1);
 
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
 }
 
 
@@ -2265,9 +2269,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
     context()->DropAndPlug(1, r0);
   } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
     // Push global object as receiver for the call IC.
-    __ ldr(r0, GlobalObjectOperand());
+    __ ldr(r0, proxy->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
     __ push(r0);
-    EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
+    EmitCallWithIC(expr, proxy->name(), proxy->var()->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
   } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
     // Call to a lookup slot (dynamically introduced variable).
     Label slow, done;
@@ -3703,7 +3707,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // but "delete this" is allowed.
         ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
         if (var->IsUnallocated()) {
-          __ ldr(r2, GlobalObjectOperand());
+          __ ldr(r2, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
           __ mov(r1, Operand(var->name()));
           __ mov(r0, Operand(Smi::FromInt(kNonStrictMode)));
           __ Push(r2, r1, r0);
@@ -4006,7 +4010,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
index ffb7457..b1cd8d8 100644 (file)
@@ -1107,7 +1107,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
 
 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
   LOperand* context = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new LGlobalObject(context));
+  return DefineAsRegister(new LGlobalObject(context, instr->qml_global()));
 }
 
 
@@ -1177,7 +1177,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
 
 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
   argument_count_ -= instr->argument_count();
-  return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr);
+  return MarkAsCall(DefineFixed(new LCallGlobal(instr->qml_global()), r0), instr);
 }
 
 
index 1452e53..8f4e97d 100644 (file)
@@ -1300,13 +1300,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> {
 
 class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LGlobalObject(LOperand* context) {
+  explicit LGlobalObject(LOperand* context, bool qml_global) {
     inputs_[0] = context;
+    qml_global_ = qml_global;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
 
   LOperand* context() { return InputAt(0); }
+  bool qml_global() { return qml_global_; }
+ private:
+  bool qml_global_;
 };
 
 
@@ -1393,10 +1397,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_;
 };
 
 
index 4cf7df4..2e1e6fa 100644 (file)
@@ -190,12 +190,13 @@ bool LCodeGen::GeneratePrologue() {
 
   // Possibly allocate a local context.
   int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
-  if (heap_slots > 0) {
+  if (heap_slots > 0 ||
+      (scope()->is_qml_mode() && scope()->is_global_scope())) {
     Comment(";;; Allocate local context");
     // Argument to NewContext is the function, which is in r1.
     __ push(r1);
     if (heap_slots <= FastNewContextStub::kMaximumSlots) {
-      FastNewContextStub stub(heap_slots);
+      FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
       __ CallStub(&stub);
     } else {
       __ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -2826,7 +2827,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
 
 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
   Register result = ToRegister(instr->result());
-  __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX));
+  __ ldr(result, ContextOperand(cp, instr->qml_global()?Context::QML_GLOBAL_INDEX:Context::GLOBAL_INDEX));
 }
 
 
@@ -3280,7 +3281,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
   ASSERT(ToRegister(instr->result()).is(r0));
 
   int arity = instr->arity();
-  RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
+  RelocInfo::Mode mode = instr->qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT;
   Handle<Code> ic =
       isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
   __ mov(r2, Operand(instr->name()));
index 8f6803e..6692199 100644 (file)
@@ -1306,6 +1306,11 @@ static inline MemOperand GlobalObjectOperand()  {
 }
 
 
+static inline MemOperand QmlGlobalObjectOperand()  {
+  return ContextOperand(cp, Context::QML_GLOBAL_INDEX);
+}
+
+
 #ifdef GENERATED_CODE_COVERAGE
 #define CODE_COVERAGE_STRINGIFY(x) #x
 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
index f8b460d..217c71f 100644 (file)
@@ -126,6 +126,11 @@ StrictModeFlag FunctionLiteral::strict_mode_flag() const {
 }
 
 
+bool FunctionLiteral::qml_mode() const {
+  return scope()->is_qml_mode();
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_AST_INL_H_
index d5282d2..3be53ac 100644 (file)
@@ -767,6 +767,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 {
index 295257a..7d50430 100644 (file)
@@ -1633,6 +1633,7 @@ class FunctionLiteral: public Expression {
   bool is_anonymous() const { return is_anonymous_; }
   bool strict_mode() const { return strict_mode_flag() == kStrictMode; }
   StrictModeFlag strict_mode_flag() const;
+  bool qml_mode() const;
 
   int materialized_literal_count() { return materialized_literal_count_; }
   int expected_property_count() { return expected_property_count_; }
index 6735ff4..b6ffbc2 100644 (file)
@@ -808,6 +808,7 @@ void Genesis::HookUpInnerGlobal(Handle<GlobalObject> inner_global) {
   Handle<JSBuiltinsObject> builtins_global(global_context_->builtins());
   global_context_->set_extension(*inner_global);
   global_context_->set_global(*inner_global);
+  global_context_->set_qml_global(*inner_global);
   global_context_->set_security_token(*inner_global);
   static const PropertyAttributes attributes =
       static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
@@ -833,6 +834,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
   // Set extension and global object.
   global_context()->set_extension(*inner_global);
   global_context()->set_global(*inner_global);
+  global_context()->set_qml_global(*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
index d49ff1d..1c5747a 100644 (file)
@@ -325,7 +325,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);
@@ -343,7 +343,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);
index 88db467..4902e72 100644 (file)
@@ -447,7 +447,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
                                              v8::Extension* extension,
                                              ScriptDataImpl* input_pre_data,
                                              Handle<Object> script_data,
-                                             NativesFlag natives) {
+                                             NativesFlag natives,
+                                             v8::Script::CompileFlags compile_flags) {
   Isolate* isolate = source->GetIsolate();
   int source_length = source->length();
   isolate->counters()->total_load_size()->Increment(source_length);
@@ -515,6 +516,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
     info.MarkAsGlobal();
     info.SetExtension(extension);
     info.SetPreParseData(pre_data);
+    if (compile_flags & v8::Script::QmlMode) info.MarkAsQmlMode();
     result = MakeFunctionInfo(&info);
     if (extension == NULL && !result.is_null()) {
       compilation_cache->PutScript(source, result);
@@ -534,7 +536,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
                                                  Handle<Context> context,
                                                  bool is_global,
-                                                 StrictModeFlag strict_mode) {
+                                                 StrictModeFlag strict_mode,
+                                                 bool qml_mode) {
   Isolate* isolate = source->GetIsolate();
   int source_length = source->length();
   isolate->counters()->total_eval_size()->Increment(source_length);
@@ -559,6 +562,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
     info.MarkAsEval();
     if (is_global) info.MarkAsGlobal();
     info.SetStrictModeFlag(strict_mode);
+    if (qml_mode) info.MarkAsQmlMode();
     info.SetCallingContext(context);
     result = MakeFunctionInfo(&info);
     if (!result.is_null()) {
@@ -606,6 +610,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
     info->SetStrictModeFlag(strict_mode);
     shared->set_strict_mode_flag(strict_mode);
 
+    // After parsing we know function's qml mode. Remember it.
+    if (info->function()->qml_mode()) {
+      shared->set_qml_mode(true);
+      info->MarkAsQmlMode();
+    }
+
     // Compile the code.
     if (!MakeCode(info)) {
       if (!isolate->has_pending_exception()) {
@@ -751,6 +761,7 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
       *lit->this_property_assignments());
   function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
   function_info->set_strict_mode_flag(lit->strict_mode_flag());
+  function_info->set_qml_mode(lit->qml_mode());
   function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
   function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
 }
index bedf5ee..054e3b9 100644 (file)
@@ -57,6 +57,7 @@ class CompilationInfo BASE_EMBEDDED {
     return StrictModeFlagField::decode(flags_);
   }
   bool is_in_loop() const { return IsInLoop::decode(flags_); }
+  bool is_qml_mode() const { return IsQmlMode::decode(flags_); }
   FunctionLiteral* function() const { return function_; }
   Scope* scope() const { return scope_; }
   Handle<Code> code() const { return code_; }
@@ -85,6 +86,9 @@ class CompilationInfo BASE_EMBEDDED {
     ASSERT(is_lazy());
     flags_ |= IsInLoop::encode(true);
   }
+  void MarkAsQmlMode() {
+    flags_ |= IsQmlMode::encode(true);
+  }
   void MarkAsNative() {
     flags_ |= IsNative::encode(true);
   }
@@ -192,6 +196,9 @@ class CompilationInfo BASE_EMBEDDED {
       ASSERT(strict_mode_flag() == kNonStrictMode);
       SetStrictModeFlag(shared_info_->strict_mode_flag());
     }
+    if (!shared_info_.is_null() && shared_info_->qml_mode()) {
+      MarkAsQmlMode();
+    }
   }
 
   void SetMode(Mode mode) {
@@ -218,7 +225,8 @@ class CompilationInfo BASE_EMBEDDED {
   // If compiling for debugging produce just full code matching the
   // initial mode setting.
   class IsCompilingForDebugging: public BitField<bool, 8, 1> {};
-
+  // Qml mode
+  class IsQmlMode: public BitField<bool, 9, 1> {};
 
   unsigned flags_;
 
@@ -283,13 +291,15 @@ class Compiler : public AllStatic {
                                             v8::Extension* extension,
                                             ScriptDataImpl* pre_data,
                                             Handle<Object> script_data,
-                                            NativesFlag is_natives_code);
+                                            NativesFlag is_natives_code,
+                                            v8::Script::CompileFlags = v8::Script::Default);
 
   // Compile a String source within a context for Eval.
   static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
                                                 Handle<Context> context,
                                                 bool is_global,
-                                                StrictModeFlag strict_mode);
+                                                StrictModeFlag strict_mode,
+                                                bool qml_mode);
 
   // Compile from function info (used for lazy compilation). Returns true on
   // success and false if the compilation resulted in a stack overflow.
index b25ffac..3129af0 100644 (file)
@@ -103,6 +103,9 @@ Handle<Object> Context::Lookup(Handle<String> name,
     PrintF(")\n");
   }
 
+  Handle<JSObject> qml_global;
+  Handle<JSObject> qml_global_global;
+
   do {
     if (FLAG_trace_contexts) {
       PrintF(" - looking in context %p", reinterpret_cast<void*>(*context));
@@ -110,6 +113,11 @@ Handle<Object> Context::Lookup(Handle<String> name,
       PrintF("\n");
     }
 
+    if (qml_global.is_null() && !context->qml_global()->IsUndefined()) {
+      qml_global = Handle<JSObject>(context->qml_global(), isolate);
+      qml_global_global = Handle<JSObject>(context->global(), isolate);
+    }
+
     // 1. Check global objects, subjects of with, and extension objects.
     if (context->IsGlobalContext() ||
         context->IsWithContext() ||
@@ -228,6 +236,33 @@ Handle<Object> Context::Lookup(Handle<String> name,
     }
   } while (follow_context_chain);
 
+  if (!qml_global.is_null()) {
+    if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0) {
+      *attributes = qml_global_global->GetLocalPropertyAttribute(*name);
+    } else {
+      *attributes = qml_global_global->GetPropertyAttribute(*name);
+    }
+
+    if (*attributes != ABSENT) {
+      *attributes = ABSENT;
+    } else {
+      if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0) {
+        *attributes = qml_global->GetLocalPropertyAttribute(*name);
+      } else {
+        *attributes = qml_global->GetPropertyAttribute(*name);
+      }
+
+      if (*attributes != ABSENT) {
+        // property found
+        if (FLAG_trace_contexts) {
+          PrintF("=> found property in qml global object %p\n",
+                 reinterpret_cast<void*>(*qml_global));
+        }
+        return qml_global;
+      }
+    }
+  }
+
   if (FLAG_trace_contexts) {
     PrintF("=> no property/slot found\n");
   }
index 7021ff8..c3cfeee 100644 (file)
@@ -218,6 +218,7 @@ class Context: public FixedArray {
     // (with contexts), or the variable name (catch contexts), the serialized
     // scope info (block contexts).
     EXTENSION_INDEX,
+    QML_GLOBAL_INDEX,
     GLOBAL_INDEX,
     MIN_CONTEXT_SLOTS,
 
@@ -321,6 +322,9 @@ class Context: public FixedArray {
   }
   void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); }
 
+  JSObject *qml_global() { return reinterpret_cast<JSObject *>(get(QML_GLOBAL_INDEX)); }
+  void set_qml_global(JSObject *qml_global) { set(QML_GLOBAL_INDEX, qml_global); }
+
   // Returns a JSGlobalProxy object or null.
   JSObject* global_proxy();
   void set_global_proxy(JSObject* global);
index 29955fa..9d26526 100644 (file)
@@ -71,7 +71,8 @@ static Handle<Object> Invoke(bool is_construct,
                              Handle<Object> receiver,
                              int argc,
                              Handle<Object> args[],
-                             bool* has_pending_exception) {
+                             bool* has_pending_exception,
+                             Handle<Object> qml) {
   Isolate* isolate = function->GetIsolate();
 
   // Entering JavaScript.
@@ -102,6 +103,12 @@ static Handle<Object> Invoke(bool is_construct,
   // make the current one is indeed a global object.
   ASSERT(function->context()->global()->IsGlobalObject());
 
+  Handle<JSObject> oldqml;
+  if (!qml.is_null()) {
+    oldqml = Handle<JSObject>(function->context()->qml_global());
+    function->context()->set_qml_global(JSObject::cast(*qml));
+  }
+
   {
     // Save and restore context around invocation and block the
     // allocation of handles without explicit handle scopes.
@@ -118,6 +125,9 @@ static Handle<Object> Invoke(bool is_construct,
         CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
   }
 
+  if (!qml.is_null())
+    function->context()->set_qml_global(*oldqml);
+
 #ifdef DEBUG
   value->Verify();
 #endif
@@ -146,7 +156,18 @@ Handle<Object> Execution::Call(Handle<Object> callable,
                                int argc,
                                Handle<Object> argv[],
                                bool* pending_exception,
-                               bool convert_receiver) {
+                               bool convert_receiver)
+{
+    return Call(callable, receiver, argc, argv, pending_exception, convert_receiver, Handle<Object>());
+}
+
+Handle<Object> Execution::Call(Handle<Object> callable,
+                               Handle<Object> receiver,
+                               int argc,
+                               Handle<Object> argv[],
+                               bool* pending_exception,
+                               bool convert_receiver,
+                               Handle<Object> qml) {
   *pending_exception = false;
 
   if (!callable->IsJSFunction()) {
@@ -170,7 +191,7 @@ Handle<Object> Execution::Call(Handle<Object> callable,
     if (*pending_exception) return callable;
   }
 
-  return Invoke(false, func, receiver, argc, argv, pending_exception);
+  return Invoke(false, func, receiver, argc, argv, pending_exception, qml);
 }
 
 
@@ -179,7 +200,7 @@ Handle<Object> Execution::New(Handle<JSFunction> func,
                               Handle<Object> argv[],
                               bool* pending_exception) {
   return Invoke(true, func, Isolate::Current()->global(), argc, argv,
-                pending_exception);
+                pending_exception, Handle<Object>());
 }
 
 
@@ -198,7 +219,7 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func,
   *caught_exception = false;
 
   Handle<Object> result = Invoke(false, func, receiver, argc, args,
-                                 caught_exception);
+                                 caught_exception, Handle<Object>());
 
   if (*caught_exception) {
     ASSERT(catcher.HasCaught());
index f2d17d0..532e5d8 100644 (file)
@@ -65,6 +65,14 @@ class Execution : public AllStatic {
                              bool* pending_exception,
                              bool convert_receiver = false);
 
+  static Handle<Object> Call(Handle<Object> callable,
+                             Handle<Object> receiver,
+                             int argc,
+                             Handle<Object> argv[],
+                             bool* pending_exception,
+                             bool convert_receiver,
+                             Handle<Object> qml);
+
   // Construct object from function, the caller supplies an array of
   // arguments. Arguments are Object* type. After function returns,
   // pointers in 'args' might be invalid.
index e6fac19..effa4b9 100644 (file)
@@ -509,7 +509,7 @@ void FullCodeGenerator::VisitDeclarations(
   // Batch declare global functions and variables.
   if (global_count > 0) {
     Handle<FixedArray> array =
-        isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
+        isolate()->factory()->NewFixedArray(3 * global_count, TENURED);
     for (int j = 0, i = 0; i < length; i++) {
       Declaration* decl = declarations->at(i);
       Variable* var = decl->proxy()->var();
@@ -533,6 +533,7 @@ void FullCodeGenerator::VisitDeclarations(
           }
           array->set(j++, *function);
         }
+        array->set(j++, Smi::FromInt(var->is_qml_global()));
       }
     }
     // Invoke the platform-dependent code generator to do the actual
index 799f96d..4818040 100644 (file)
@@ -533,6 +533,7 @@ class FullCodeGenerator: public AstVisitor {
   StrictModeFlag strict_mode_flag() {
     return function()->strict_mode_flag();
   }
+  bool is_qml_mode() { return function()->qml_mode(); }
   FunctionLiteral* function() { return info_->function(); }
   Scope* scope() { return scope_; }
 
index 0b39198..de3187e 100644 (file)
@@ -4353,6 +4353,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
   context->set_previous(function->context());
   context->set_extension(NULL);
   context->set_global(function->context()->global());
+  context->set_qml_global(function->context()->qml_global());
   return context;
 }
 
@@ -4373,6 +4374,7 @@ MaybeObject* Heap::AllocateCatchContext(JSFunction* function,
   context->set_previous(previous);
   context->set_extension(name);
   context->set_global(previous->global());
+  context->set_qml_global(previous->qml_global());
   context->set(Context::THROWN_OBJECT_INDEX, thrown_object);
   return context;
 }
@@ -4391,6 +4393,7 @@ MaybeObject* Heap::AllocateWithContext(JSFunction* function,
   context->set_previous(previous);
   context->set_extension(extension);
   context->set_global(previous->global());
+  context->set_qml_global(previous->qml_global());
   return context;
 }
 
@@ -4409,6 +4412,7 @@ MaybeObject* Heap::AllocateBlockContext(JSFunction* function,
   context->set_previous(previous);
   context->set_extension(scope_info);
   context->set_global(previous->global());
+  context->set_qml_global(previous->qml_global());
   return context;
 }
 
index ae62367..7979726 100644 (file)
@@ -646,6 +646,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);
index 101d62a..2143533 100644 (file)
@@ -1422,19 +1422,30 @@ class HOuterContext: public HUnaryOperation {
 
 class HGlobalObject: public HUnaryOperation {
  public:
-  explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
+  explicit HGlobalObject(HValue* context) : HUnaryOperation(context), qml_global_(false) {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
   }
 
+  virtual void PrintDataTo(StringStream* stream);
+
   DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
   }
 
+  bool qml_global() { return qml_global_; }
+  void set_qml_global(bool v) { qml_global_ = v; }
+
  protected:
-  virtual bool DataEquals(HValue* other) { return true; }
+  virtual bool DataEquals(HValue* other) {
+      HGlobalObject* o = HGlobalObject::cast(other);
+      return o->qml_global_ == qml_global_;
+  }
+
+ private:
+  bool qml_global_;
 };
 
 
@@ -1613,7 +1624,7 @@ class HCallFunction: public HUnaryCall {
 class HCallGlobal: public HUnaryCall {
  public:
   HCallGlobal(HValue* context, Handle<String> name, int argument_count)
-      : HUnaryCall(context, argument_count), name_(name) {
+      : HUnaryCall(context, argument_count), name_(name), qml_global_(false) {
   }
 
   virtual void PrintDataTo(StringStream* stream);
@@ -1625,10 +1636,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_;
 };
 
 
index a7a022d..4c716ef 100644 (file)
@@ -3197,6 +3197,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,
@@ -3656,6 +3657,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,
@@ -5122,11 +5124,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);
       }
 
index 50cddca..d32a9e3 100644 (file)
@@ -144,6 +144,11 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
   __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx);
 
+  // Copy the qml global object from the previous context.
+  __ mov(ebx, Operand(esi, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
+  __ mov(Operand(eax, Context::SlotOffset(Context::QML_GLOBAL_INDEX)), ebx);
+
+
   // Initialize the rest of the slots to undefined.
   __ mov(ebx, factory->undefined_value());
   for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
@@ -210,6 +215,10 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
   __ mov(ebx, ContextOperand(esi, Context::GLOBAL_INDEX));
   __ mov(ContextOperand(eax, Context::GLOBAL_INDEX), ebx);
 
+  // Copy the qml global object from the previous context.
+  __ mov(ebx, ContextOperand(esi, Context::QML_GLOBAL_INDEX));
+  __ mov(ContextOperand(eax, Context::QML_GLOBAL_INDEX), ebx);
+
   // Initialize the rest of the slots to the hole value.
   if (slots_ == 1) {
     __ mov(ContextOperand(eax, Context::MIN_CONTEXT_SLOTS),
index 0af30f0..18ecb2b 100644 (file)
@@ -168,12 +168,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
 
   // Possibly allocate a local context.
   int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
-  if (heap_slots > 0) {
+  if (heap_slots > 0 ||
+      (scope()->is_qml_mode() && scope()->is_global_scope())) {
     Comment cmnt(masm_, "[ Allocate local context");
     // Argument to NewContext is the function, which is still in edi.
     __ push(edi);
     if (heap_slots <= FastNewContextStub::kMaximumSlots) {
-      FastNewContextStub stub(heap_slots);
+      FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
       __ CallStub(&stub);
     } else {
       __ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -1136,10 +1137,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
 
   // All extension objects were empty and it is safe to use a global
   // load IC call.
-  __ mov(eax, GlobalObjectOperand());
+  __ mov(eax, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
   __ mov(ecx, var->name());
   Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
-  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
+  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || var->is_qml_global())
       ? RelocInfo::CODE_TARGET
       : RelocInfo::CODE_TARGET_CONTEXT;
   __ call(ic, mode);
@@ -1220,10 +1221,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       Comment cmnt(masm_, "Global variable");
       // Use inline caching. Variable name is passed in ecx and the global
       // object in eax.
-      __ mov(eax, GlobalObjectOperand());
+      __ mov(eax, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
       __ mov(ecx, var->name());
       Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
-      __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+      __ call(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
       context()->Plug(eax);
       break;
     }
@@ -1806,7 +1807,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
   if (var->IsUnallocated()) {
     // Global var, const, or let.
     __ mov(ecx, var->name());
-    __ mov(edx, GlobalObjectOperand());
+    __ mov(edx, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
     Handle<Code> ic = is_strict_mode()
         ? isolate()->builtins()->StoreIC_Initialize_Strict()
         : isolate()->builtins()->StoreIC_Initialize();
@@ -2109,7 +2110,10 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
       FLAG_harmony_scoping ? kStrictMode : strict_mode_flag();
   __ push(Immediate(Smi::FromInt(strict_mode)));
 
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+  // Push the qml mode flag
+  __ push(Immediate(Smi::FromInt(is_qml_mode())));
+
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
 }
 
 
@@ -2161,8 +2165,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
 
   } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
     // Push global object as receiver for the call IC.
-    __ push(GlobalObjectOperand());
-    EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
+    __ push(proxy->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+    EmitCallWithIC(expr, proxy->name(), proxy->var()->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
 
   } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
     // Call to a lookup slot (dynamically introduced variable).
@@ -3633,7 +3637,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // but "delete this" is allowed.
         ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
         if (var->IsUnallocated()) {
-          __ push(GlobalObjectOperand());
+          __ push(var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
           __ push(Immediate(var->name()));
           __ push(Immediate(Smi::FromInt(kNonStrictMode)));
           __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
@@ -3953,7 +3957,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
 
   if (proxy != NULL && proxy->var()->IsUnallocated()) {
     Comment cmnt(masm_, "Global variable");
-    __ mov(eax, GlobalObjectOperand());
+    __ mov(eax, proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
     __ mov(ecx, Immediate(proxy->name()));
     Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
     // Use a regular load, not a contextual load, to avoid a reference
index d4cbbce..b381227 100644 (file)
@@ -211,12 +211,13 @@ bool LCodeGen::GeneratePrologue() {
 
   // Possibly allocate a local context.
   int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
-  if (heap_slots > 0) {
+  if (heap_slots > 0 ||
+      (scope()->is_qml_mode() && scope()->is_global_scope())) {
     Comment(";;; Allocate local context");
     // Argument to NewContext is the function, which is still in edi.
     __ push(edi);
     if (heap_slots <= FastNewContextStub::kMaximumSlots) {
-      FastNewContextStub stub(heap_slots);
+      FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
       __ CallStub(&stub);
     } else {
       __ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -2661,7 +2662,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
   Register context = ToRegister(instr->context());
   Register result = ToRegister(instr->result());
-  __ mov(result, Operand(context, Context::SlotOffset(Context::GLOBAL_INDEX)));
+  __ mov(result, Operand(context, Context::SlotOffset(instr->qml_global()?Context::QML_GLOBAL_INDEX:Context::GLOBAL_INDEX)));
 }
 
 
@@ -3131,7 +3132,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
   ASSERT(ToRegister(instr->result()).is(eax));
 
   int arity = instr->arity();
-  RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
+  RelocInfo::Mode mode = instr->qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT;
   Handle<Code> ic =
       isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
   __ mov(ecx, instr->name());
index 227d0b5..bce3fc8 100644 (file)
@@ -1124,7 +1124,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* 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()));
 }
 
 
@@ -1211,7 +1211,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);
 }
 
index 98487b4..820d188 100644 (file)
@@ -1332,13 +1332,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> {
 
 class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LGlobalObject(LOperand* context) {
+  explicit LGlobalObject(LOperand* context, bool qml_global) {
     inputs_[0] = context;
+    qml_global_ = qml_global;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
 
   LOperand* context() { return InputAt(0); }
+  bool qml_global() { return qml_global_; }
+ private:
+  bool qml_global_;
 };
 
 
@@ -1437,7 +1441,7 @@ class LCallFunction: public LTemplateInstruction<1, 1, 0> {
 
 class LCallGlobal: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LCallGlobal(LOperand* context) {
+  explicit LCallGlobal(LOperand* context, bool qml_global) : qml_global_(qml_global) {
     inputs_[0] = context;
   }
 
@@ -1449,6 +1453,10 @@ class LCallGlobal: public LTemplateInstruction<1, 1, 0> {
   LOperand* context() { return inputs_[0]; }
   Handle<String> name() const {return hydrogen()->name(); }
   int arity() const { return hydrogen()->argument_count() - 1; }
+
+  bool qml_global() { return qml_global_; }
+ private:
+  bool qml_global_;
 };
 
 
index 68a14bb..92378e4 100644 (file)
@@ -899,6 +899,9 @@ static inline Operand GlobalObjectOperand() {
   return ContextOperand(esi, Context::GLOBAL_INDEX);
 }
 
+static inline Operand QmlGlobalObjectOperand() {
+  return ContextOperand(esi, Context::QML_GLOBAL_INDEX);
+}
 
 // Generates an Operand for saving parameters after PrepareCallApiFunction.
 Operand ApiParameterOperand(int index);
index 8ff39c5..4a7058b 100644 (file)
@@ -173,6 +173,11 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
   __ lw(a1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ sw(a1, MemOperand(v0, Context::SlotOffset(Context::GLOBAL_INDEX)));
 
+  // Copy the qml global object from the surrounding context.
+  __ lw(a1, MemOperand(cp, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
+  __ sw(a1, MemOperand(v0, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
+
+
   // Initialize the rest of the slots to undefined.
   __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
   for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
@@ -238,6 +243,10 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
   __ lw(a1, ContextOperand(cp, Context::GLOBAL_INDEX));
   __ sw(a1, ContextOperand(v0, Context::GLOBAL_INDEX));
 
+  // Copy the qml global object from the surrounding context.
+  __ lw(a1, ContextOperand(cp, Context::QML_GLOBAL_INDEX));
+  __ sw(a1, ContextOperand(v0, Context::QML_GLOBAL_INDEX));
+
   // Initialize the rest of the slots to the hole value.
   __ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
   for (int i = 0; i < slots_; i++) {
index 5bb9b35..a4cfefd 100644 (file)
@@ -186,12 +186,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
 
   // Possibly allocate a local context.
   int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
-  if (heap_slots > 0) {
+  if (heap_slots > 0 ||
+      (scope()->is_qml_mode() && scope()->is_global_scope())) {
     Comment cmnt(masm_, "[ Allocate local context");
     // Argument to NewContext is the function, which is in a1.
     __ push(a1);
     if (heap_slots <= FastNewContextStub::kMaximumSlots) {
-      FastNewContextStub stub(heap_slots);
+      FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
       __ CallStub(&stub);
     } else {
       __ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -1188,9 +1189,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
     __ bind(&fast);
   }
 
-  __ lw(a0, GlobalObjectOperand());
+  __ lw(a0, var->is_qml_global() ? QmlGlobalObjectOperand():GlobalObjectOperand());
   __ li(a2, Operand(var->name()));
-  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
+  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || var->is_qml_global())
       ? RelocInfo::CODE_TARGET
       : RelocInfo::CODE_TARGET_CONTEXT;
   Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
@@ -1275,10 +1276,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       Comment cmnt(masm_, "Global variable");
       // Use inline caching. Variable name is passed in a2 and the global
       // object (receiver) in a0.
-      __ lw(a0, GlobalObjectOperand());
+      __ lw(a0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
       __ li(a2, Operand(var->name()));
       Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
-      __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+      __ Call(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
       context()->Plug(v0);
       break;
     }
@@ -1926,7 +1927,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
     // Global var, const, or let.
     __ mov(a0, result_register());
     __ li(a2, Operand(var->name()));
-    __ lw(a1, GlobalObjectOperand());
+    __ lw(a1, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
     Handle<Code> ic = is_strict_mode()
         ? isolate()->builtins()->StoreIC_Initialize_Strict()
         : isolate()->builtins()->StoreIC_Initialize();
@@ -2234,7 +2235,11 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
   __ li(a1, Operand(Smi::FromInt(strict_mode)));
   __ push(a1);
 
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+  // Push the qml mode flag.
+  __ li(a1, Operand(Smi::FromInt(is_qml_mode())));
+  __ push(a1);
+
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
 }
 
 
@@ -2289,9 +2294,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
     context()->DropAndPlug(1, v0);
   } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
     // Push global object as receiver for the call IC.
-    __ lw(a0, GlobalObjectOperand());
+    __ lw(a0, proxy->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
     __ push(a0);
-    EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
+    EmitCallWithIC(expr, proxy->name(), proxy->var()->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT);
   } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
     // Call to a lookup slot (dynamically introduced variable).
     Label slow, done;
@@ -3743,7 +3748,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // but "delete this" is allowed.
         ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
         if (var->IsUnallocated()) {
-          __ lw(a2, GlobalObjectOperand());
+          __ lw(a2, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
           __ li(a1, Operand(var->name()));
           __ li(a0, Operand(Smi::FromInt(kNonStrictMode)));
           __ Push(a2, a1, a0);
@@ -4049,7 +4054,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
index b9bd2f3..0a78f6d 100644 (file)
@@ -112,6 +112,11 @@ static inline MemOperand GlobalObjectOperand()  {
 }
 
 
+static inline MemOperand QmlGlobalObjectOperand()  {
+  return ContextOperand(cp, Context::QML_GLOBAL_INDEX);
+}
+
+
 // Generate a MemOperand for loading a field from an object.
 static inline MemOperand FieldMemOperand(Register object, int offset) {
   return MemOperand(object, offset - kHeapObjectTag);
index 13f26c9..4322742 100644 (file)
@@ -3535,6 +3535,8 @@ void SharedFunctionInfo::set_strict_mode_flag(StrictModeFlag strict_mode_flag) {
 
 BOOL_GETTER(SharedFunctionInfo, compiler_hints, strict_mode,
             kStrictModeFunction)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, qml_mode,
+               kQmlModeFunction)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
                name_should_print_as_anonymous,
index 7902d18..7240b55 100644 (file)
@@ -3120,6 +3120,9 @@ class SerializedScopeInfo : public FixedArray {
   // Is this scope a strict mode scope?
   bool IsStrictMode();
 
+  // Is this scope a qml mode scope?
+  bool IsQmlMode();
+
   // Return the number of stack slots for code.
   int NumberOfStackSlots();
 
@@ -4929,6 +4932,9 @@ class SharedFunctionInfo: public HeapObject {
   inline StrictModeFlag strict_mode_flag();
   inline void set_strict_mode_flag(StrictModeFlag strict_mode_flag);
 
+  // Indicates whether the function is a qml mode function.
+  DECL_BOOLEAN_ACCESSORS(qml_mode)
+
   // False if the function definitely does not allocate an arguments object.
   DECL_BOOLEAN_ACCESSORS(uses_arguments)
 
@@ -5150,6 +5156,7 @@ class SharedFunctionInfo: public HeapObject {
     kCodeAgeShift,
     kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize,
     kStrictModeFunction,
+    kQmlModeFunction,
     kUsesArguments,
     kHasDuplicateParameters,
     kNative,
index 0a635fc..8e55fe6 100644 (file)
@@ -607,7 +607,8 @@ Parser::Parser(Handle<Script> script,
 
 FunctionLiteral* Parser::ParseProgram(Handle<String> source,
                                       bool in_global_context,
-                                      StrictModeFlag strict_mode) {
+                                      StrictModeFlag strict_mode,
+                                      bool qml_mode) {
   ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
 
   HistogramTimerScope timer(isolate()->counters()->parse());
@@ -623,11 +624,11 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
     ExternalTwoByteStringUC16CharacterStream stream(
         Handle<ExternalTwoByteString>::cast(source), 0, source->length());
     scanner_.Initialize(&stream);
-    return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
+    return DoParseProgram(source, in_global_context, strict_mode, qml_mode, &zone_scope);
   } else {
     GenericStringUC16CharacterStream stream(source, 0, source->length());
     scanner_.Initialize(&stream);
-    return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
+    return DoParseProgram(source, in_global_context, strict_mode, qml_mode, &zone_scope);
   }
 }
 
@@ -635,6 +636,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
 FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
                                         bool in_global_context,
                                         StrictModeFlag strict_mode,
+                                        bool qml_mode,
                                         ZoneScope* zone_scope) {
   ASSERT(top_scope_ == NULL);
   ASSERT(target_stack_ == NULL);
@@ -654,6 +656,9 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
     LexicalScope lexical_scope(this, scope, isolate());
     ASSERT(top_scope_->strict_mode_flag() == kNonStrictMode);
     top_scope_->SetStrictModeFlag(strict_mode);
+    if (qml_mode) {
+      scope->EnableQmlMode();
+    }
     ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
     bool ok = true;
     int beg_loc = scanner().location().beg_pos;
@@ -747,6 +752,10 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
            scope->strict_mode_flag() == info->strict_mode_flag());
     ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag());
     scope->SetStrictModeFlag(shared_info->strict_mode_flag());
+    if (shared_info->qml_mode()) {
+      top_scope_->EnableQmlMode();
+    }
+
     FunctionLiteral::Type type = shared_info->is_expression()
         ? (shared_info->is_anonymous()
               ? FunctionLiteral::ANONYMOUS_EXPRESSION
@@ -1856,6 +1865,11 @@ Block* Parser::ParseVariableDeclarations(
         arguments->Add(value);
         value = NULL;  // zap the value to avoid the unnecessary assignment
 
+        int qml_mode = 0;
+        if (top_scope_->is_qml_mode() && !Isolate::Current()->global()->HasProperty(*name))
+          qml_mode = 1;
+        arguments->Add(NewNumberLiteral(qml_mode));
+
         // Construct the call to Runtime_InitializeConstGlobal
         // and add it to the initialization statement block.
         // Note that the function does different things depending on
@@ -1872,6 +1886,11 @@ Block* Parser::ParseVariableDeclarations(
         StrictModeFlag flag = initialization_scope->strict_mode_flag();
         arguments->Add(NewNumberLiteral(flag));
 
+        int qml_mode = 0;
+        if (top_scope_->is_qml_mode() && !Isolate::Current()->global()->HasProperty(*name))
+          qml_mode = 1;
+        arguments->Add(NewNumberLiteral(qml_mode));
+
         // Be careful not to assign a value to the global variable if
         // we're in a with. The initialization value should not
         // necessarily be stored in the global object in that case,
@@ -5409,7 +5428,8 @@ bool ParserApi::Parse(CompilationInfo* info) {
       Handle<String> source = Handle<String>(String::cast(script->source()));
       result = parser.ParseProgram(source,
                                    info->is_global(),
-                                   info->strict_mode_flag());
+                                   info->strict_mode_flag(),
+                                   info->is_qml_mode());
     }
   }
   info->SetFunction(result);
index 9624301..407d75f 100644 (file)
@@ -432,7 +432,8 @@ class Parser {
   // Returns NULL if parsing failed.
   FunctionLiteral* ParseProgram(Handle<String> source,
                                 bool in_global_context,
-                                StrictModeFlag strict_mode);
+                                StrictModeFlag strict_mode,
+                                bool qml_mode = false);
 
   FunctionLiteral* ParseLazy(CompilationInfo* info);
 
@@ -478,6 +479,7 @@ class Parser {
   FunctionLiteral* DoParseProgram(Handle<String> source,
                                   bool in_global_context,
                                   StrictModeFlag strict_mode,
+                                  bool qml_mode,
                                   ZoneScope* zone_scope);
 
   // Report syntax error
index 37c76ce..73812fd 100644 (file)
@@ -618,6 +618,9 @@ void AstPrinter::PrintLiteralWithModeIndented(const char* info,
     EmbeddedVector<char, 256> buf;
     int pos = OS::SNPrintF(buf, "%s (mode = %s", info,
                            Variable::Mode2String(var->mode()));
+    if (var->is_qml_global()) {
+      pos += OS::SNPrintF(buf + pos, ":QML");
+    }
     OS::SNPrintF(buf + pos, ")");
     PrintLiteralIndented(buf.start(), value, true);
   }
index 6112f41..a9a705f 100644 (file)
@@ -1317,19 +1317,23 @@ static Failure* ThrowRedeclarationError(Isolate* isolate,
 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
   ASSERT(args.length() == 3);
   HandleScope scope(isolate);
-  Handle<GlobalObject> global = Handle<GlobalObject>(
-      isolate->context()->global());
 
   Handle<Context> context = args.at<Context>(0);
   CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
   CONVERT_SMI_ARG_CHECKED(flags, 2);
 
+  Handle<JSObject> js_global = Handle<JSObject>(isolate->context()->global());
+  Handle<JSObject> qml_global = Handle<JSObject>(isolate->context()->qml_global());
+
   // Traverse the name/value pairs and set the properties.
   int length = pairs->length();
-  for (int i = 0; i < length; i += 2) {
+  for (int i = 0; i < length; i += 3) {
     HandleScope scope(isolate);
     Handle<String> name(String::cast(pairs->get(i)));
     Handle<Object> value(pairs->get(i + 1), isolate);
+    Handle<Smi> is_qml_global(Smi::cast(pairs->get(i + 2)));
+
+    Handle<JSObject> global = is_qml_global->value()?qml_global:js_global;
 
     // We have to declare a global const property. To capture we only
     // assign to it when evaluating the assignment for "const x =
@@ -1516,18 +1520,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
   NoHandleAllocation nha;
   // args[0] == name
   // args[1] == strict_mode
-  // args[2] == value (optional)
+  // args[2] == qml_mode
+  // args[3] == value (optional)
 
   // Determine if we need to assign to the variable if it already
   // exists (based on the number of arguments).
-  RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
-  bool assign = args.length() == 3;
+  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
+  bool assign = args.length() == 4;
 
   CONVERT_ARG_CHECKED(String, name, 0);
-  GlobalObject* global = isolate->context()->global();
   RUNTIME_ASSERT(args[1]->IsSmi());
   CONVERT_STRICT_MODE_ARG(strict_mode, 1);
 
+  RUNTIME_ASSERT(args[2]->IsSmi());
+  int qml_mode = Smi::cast(args[2])->value();
+
+  JSObject* global = qml_mode?isolate->context()->qml_global():isolate->context()->global();
+
   // According to ECMA-262, section 12.2, page 62, the property must
   // not be deletable.
   PropertyAttributes attributes = DONT_DELETE;
@@ -1555,7 +1564,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
         // Found an interceptor that's not read only.
         if (assign) {
           return raw_holder->SetProperty(
-              &lookup, *name, args[2], attributes, strict_mode);
+              &lookup, *name, args[3], attributes, strict_mode);
         } else {
           return isolate->heap()->undefined_value();
         }
@@ -1565,9 +1574,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
   }
 
   // Reload global in case the loop above performed a GC.
-  global = isolate->context()->global();
+  global = qml_mode?isolate->context()->qml_global():isolate->context()->global();
   if (assign) {
-    return global->SetProperty(*name, args[2], attributes, strict_mode, true);
+    return global->SetProperty(*name, args[3], attributes, strict_mode, true);
   }
   return isolate->heap()->undefined_value();
 }
@@ -1577,12 +1586,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
   // All constants are declared with an initial value. The name
   // of the constant is the first argument and the initial value
   // is the second.
-  RUNTIME_ASSERT(args.length() == 2);
+  RUNTIME_ASSERT(args.length() == 3);
   CONVERT_ARG_CHECKED(String, name, 0);
   Handle<Object> value = args.at<Object>(1);
 
+  RUNTIME_ASSERT(args[2]->IsSmi());
+  int qml_mode = Smi::cast(args[2])->value();
+
   // Get the current global object from top.
-  GlobalObject* global = isolate->context()->global();
+  JSObject* global = qml_mode?isolate->context()->qml_global():isolate->context()->global();
 
   // According to ECMA-262, section 12.2, page 62, the property must
   // not be deletable. Since it's a const, it must be READ_ONLY too.
@@ -1606,7 +1618,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
     // Restore global object from context (in case of GC) and continue
     // with setting the value.
     HandleScope handle_scope(isolate);
-    Handle<GlobalObject> global(isolate->context()->global());
+    Handle<JSObject> global(qml_mode?isolate->context()->qml_global():isolate->context()->global());
 
     // BUG 1213575: Handle the case where we have to set a read-only
     // property through an interceptor and only do it if it's
@@ -9441,7 +9453,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
                                                             context,
                                                             true,
-                                                            kNonStrictMode);
+                                                            kNonStrictMode,
+                                                            false);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> fun =
       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
@@ -9454,7 +9467,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
 static ObjectPair CompileGlobalEval(Isolate* isolate,
                                     Handle<String> source,
                                     Handle<Object> receiver,
-                                    StrictModeFlag strict_mode) {
+                                    StrictModeFlag strict_mode,
+                                    bool qml_mode) {
   Handle<Context> context = Handle<Context>(isolate->context());
   Handle<Context> global_context = Handle<Context>(context->global_context());
 
@@ -9472,7 +9486,8 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
       source,
       Handle<Context>(isolate->context()),
       context->IsGlobalContext(),
-      strict_mode);
+      strict_mode,
+      qml_mode);
   if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
   Handle<JSFunction> compiled =
       isolate->factory()->NewFunctionFromSharedFunctionInfo(
@@ -9482,7 +9497,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
 
 
 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
-  ASSERT(args.length() == 4);
+  ASSERT(args.length() == 5);
 
   HandleScope scope(isolate);
   Handle<Object> callee = args.at<Object>(0);
@@ -9498,10 +9513,12 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
   }
 
   CONVERT_STRICT_MODE_ARG(strict_mode, 3);
+  ASSERT(args[4]->IsSmi());
   return CompileGlobalEval(isolate,
                            args.at<String>(1),
                            args.at<Object>(2),
-                           strict_mode);
+                           strict_mode,
+                           Smi::cast(args[4])->value());
 }
 
 
@@ -11215,10 +11232,12 @@ class ScopeIterator {
     ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
     Handle<Script> script(Script::cast(shared_info->script()));
     Scope* scope;
-    if (index >= 0) {
+    if (index >= 0 || shared_info->qml_mode()) {
       // Global code
       CompilationInfo info(script);
       info.MarkAsGlobal();
+      if (shared_info->qml_mode())
+          info.MarkAsQmlMode();
       CHECK(ParserApi::Parse(&info));
       CHECK(Scope::Analyze(&info));
       scope = info.function()->scope();
@@ -11244,7 +11263,6 @@ class ScopeIterator {
     ScopeType scope_type = Type();
     if (scope_type == ScopeTypeGlobal) {
       // The global scope is always the last in the chain.
-      ASSERT(context_->IsGlobalContext());
       context_ = Handle<Context>();
       return;
     }
@@ -11268,7 +11286,7 @@ class ScopeIterator {
                  !scope_info->HasContext());
           return ScopeTypeLocal;
         case GLOBAL_SCOPE:
-          ASSERT(context_->IsGlobalContext());
+          ASSERT(context_->IsGlobalContext() || scope_info->IsQmlMode());
           return ScopeTypeGlobal;
         case WITH_SCOPE:
           ASSERT(context_->IsWithContext());
@@ -11306,10 +11324,15 @@ class ScopeIterator {
     switch (Type()) {
       case ScopeIterator::ScopeTypeGlobal:
         return Handle<JSObject>(CurrentContext()->global());
-      case ScopeIterator::ScopeTypeLocal:
+      case ScopeIterator::ScopeTypeLocal: {
+        Handle<SerializedScopeInfo> scope_info = nested_scope_chain_.last();
+        if (scope_info->IsQmlMode())
+            ASSERT(nested_scope_chain_.length() == 2);
+        else
+            ASSERT(nested_scope_chain_.length() == 1);
         // Materialize the content of the local scope into a JSObject.
-        ASSERT(nested_scope_chain_.length() == 1);
         return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_);
+      }
       case ScopeIterator::ScopeTypeWith:
         // Return the with object.
         return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
@@ -12025,6 +12048,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
   Handle<JSFunction> function(JSFunction::cast(frame->function()));
   Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
   ScopeInfo<> sinfo(*scope_info);
+  bool qml_mode = function->shared()->qml_mode();
 
   // Traverse the saved contexts chain to find the active context for the
   // selected frame.
@@ -12095,7 +12119,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
       Compiler::CompileEval(function_source,
                             context,
                             context->IsGlobalContext(),
-                            kNonStrictMode);
+                            kNonStrictMode,
+                            qml_mode);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> compiled_function =
       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
@@ -12105,7 +12130,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
   Handle<Object> receiver(frame->receiver(), isolate);
   Handle<Object> evaluation_function =
       Execution::Call(compiled_function, receiver, 0, NULL,
-                      &has_pending_exception);
+                      &has_pending_exception, false,
+                      Handle<Object>(function->context()->qml_global()));
   if (has_pending_exception) return Failure::Exception();
 
   Handle<Object> arguments = GetArgumentsObject(isolate,
@@ -12186,7 +12212,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
   // Currently, the eval code will be executed in non-strict mode,
   // even in the strict code context.
   Handle<SharedFunctionInfo> shared =
-      Compiler::CompileEval(source, context, is_global, kNonStrictMode);
+      Compiler::CompileEval(source, context, is_global, kNonStrictMode, false);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> compiled_function =
       Handle<JSFunction>(
index c411b30..6d3ec67 100644 (file)
@@ -258,7 +258,7 @@ namespace internal {
   \
   /* Eval */ \
   F(GlobalReceiver, 1, 1) \
-  F(ResolvePossiblyDirectEval, 4, 2) \
+  F(ResolvePossiblyDirectEval, 5, 2) \
   \
   F(SetProperty, -1 /* 4 or 5 */, 1) \
   F(DefineOrRedefineDataProperty, 4, 1) \
@@ -336,8 +336,8 @@ namespace internal {
   /* Declarations and initialization */ \
   F(DeclareGlobals, 3, 1) \
   F(DeclareContextSlot, 4, 1) \
-  F(InitializeVarGlobal, -1 /* 2 or 3 */, 1) \
-  F(InitializeConstGlobal, 2, 1) \
+  F(InitializeVarGlobal, -1 /* 3 or 4 */, 1) \
+  F(InitializeConstGlobal, 3, 1) \
   F(InitializeConstContextSlot, 3, 1) \
   F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
   \
index 8ea5f1e..a61b787 100644 (file)
@@ -51,6 +51,7 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
     : function_name_(FACTORY->empty_symbol()),
       calls_eval_(scope->calls_eval()),
       is_strict_mode_(scope->is_strict_mode()),
+      is_qml_mode_(scope->is_qml_mode()),
       type_(scope->type()),
       parameters_(scope->num_parameters()),
       stack_slots_(scope->num_stack_slots()),
@@ -153,6 +154,8 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
 //
 // - is strict mode scope
 //
+// - is qml mode scope
+//
 // - scope type
 //
 // - number of variables in the context object (smi) (= function context
@@ -252,6 +255,7 @@ ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data)
     p = ReadObject(p, &function_name_);
     p = ReadBool(p, &calls_eval_);
     p = ReadBool(p, &is_strict_mode_);
+    p = ReadBool(p, &is_qml_mode_);
     p = ReadInt(p, &type_);
     p = ReadList<Allocator>(p, &context_slots_, &context_modes_);
     p = ReadList<Allocator>(p, &parameters_);
@@ -307,9 +311,9 @@ static Object** WriteList(Object** p,
 
 template<class Allocator>
 Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
-  // function name, calls eval, is_strict_mode, scope type,
+  // function name, calls eval, is_strict_mode, is_qml_mode, scope type,
   // length for 3 tables:
-  const int extra_slots = 1 + 1 + 1 + 1 + 3;
+  const int extra_slots = 1 + 1 + 1 + 1 + 1 + 3;
   int length = extra_slots +
                context_slots_.length() * 2 +
                parameters_.length() +
@@ -324,6 +328,7 @@ Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
   p = WriteObject(p, function_name_);
   p = WriteBool(p, calls_eval_);
   p = WriteBool(p, is_strict_mode_);
+  p = WriteBool(p, is_qml_mode_);
   p = WriteInt(p, type_);
   p = WriteList(p, &context_slots_, &context_modes_);
   p = WriteList(p, &parameters_);
@@ -372,8 +377,8 @@ SerializedScopeInfo* SerializedScopeInfo::Empty() {
 
 Object** SerializedScopeInfo::ContextEntriesAddr() {
   ASSERT(length() > 0);
-  // +4 for function name, calls eval, strict mode, scope type.
-  return data_start() + 4;
+  // +5 for function name, calls eval, strict mode, qml mode, scope type.
+  return data_start() + 5;
 }
 
 
@@ -417,10 +422,21 @@ bool SerializedScopeInfo::IsStrictMode() {
 }
 
 
+bool SerializedScopeInfo::IsQmlMode() {
+  if (length() > 0) {
+    Object** p = data_start() + 3;  // +3 for function name, calls eval, strict mode.
+    bool qml_mode;
+    p = ReadBool(p, &qml_mode);
+    return qml_mode;
+  }
+  return false;
+}
+
+
 ScopeType SerializedScopeInfo::Type() {
   ASSERT(length() > 0);
-  // +3 for function name, calls eval, strict mode.
-  Object** p = data_start() + 3;
+  // +4 for function name, calls eval, strict mode, qml mode.
+  Object** p = data_start() + 4;
   ScopeType type;
   p = ReadInt(p, &type);
   return type;
index eeb3047..2ca4503 100644 (file)
@@ -88,6 +88,7 @@ class ScopeInfo BASE_EMBEDDED {
   Handle<String> function_name_;
   bool calls_eval_;
   bool is_strict_mode_;
+  bool is_qml_mode_;
   ScopeType type_;
   List<Handle<String>, Allocator > parameters_;
   List<Handle<String>, Allocator > stack_slots_;
index a199da6..25057e1 100644 (file)
@@ -35,6 +35,8 @@
 
 #include "allocation-inl.h"
 
+#include "debug.h"
+
 namespace v8 {
 namespace internal {
 
@@ -184,6 +186,7 @@ void Scope::SetDefaults(ScopeType type,
   // Inherit the strict mode from the parent scope.
   strict_mode_flag_ = (outer_scope != NULL)
       ? outer_scope->strict_mode_flag_ : kNonStrictMode;
+  qml_mode_ = (outer_scope != NULL) && outer_scope->qml_mode_;
   outer_scope_calls_non_strict_eval_ = false;
   inner_scope_calls_eval_ = false;
   force_eager_compilation_ = false;
@@ -889,6 +892,26 @@ void Scope::ResolveVariable(Scope* global_scope,
       // by 'eval' introduced variable bindings.
       if (var->is_global()) {
         var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
+
+        if (qml_mode_) {
+          Handle<GlobalObject> global = isolate_->global();
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+          if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) {
+            //Get the context before the debugger was entered.
+            SaveContext *save = isolate_->save_context();
+            while (save != NULL && *save->context() == *isolate_->debug()->debug_context())
+              save = save->prev();
+
+            global = Handle<GlobalObject>(save->context()->global());
+          }
+#endif
+
+          if (qml_mode_ && !global->HasProperty(*(proxy->name()))) {
+            var->set_is_qml_global(true);
+          }
+        }
+
       } else {
         Variable* invalidated = var;
         var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
@@ -900,12 +923,52 @@ void Scope::ResolveVariable(Scope* global_scope,
       // No binding has been found. Declare a variable in global scope.
       ASSERT(global_scope != NULL);
       var = global_scope->DeclareGlobal(proxy->name());
+
+      if (qml_mode_) {
+        Handle<GlobalObject> global = isolate_->global();
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+        if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) {
+          //Get the context before the debugger was entered.
+          SaveContext *save = isolate_->save_context();
+          while (save != NULL && *save->context() == *isolate_->debug()->debug_context())
+            save = save->prev();
+
+          global = Handle<GlobalObject>(save->context()->global());
+        }
+#endif
+
+        if (!global->HasProperty(*(proxy->name()))) {
+          var->set_is_qml_global(true);
+        }
+      }
+
       break;
 
     case UNBOUND_EVAL_SHADOWED:
       // No binding has been found. But some scope makes a
       // non-strict 'eval' call.
       var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
+
+      if (qml_mode_) {
+        Handle<GlobalObject> global = isolate_->global();
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+        if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) {
+          //Get the context before the debugger was entered.
+          SaveContext *save = isolate_->save_context();
+          while (save != NULL && *save->context() == *isolate_->debug()->debug_context())
+            save = save->prev();
+
+          global = Handle<GlobalObject>(save->context()->global());
+        }
+#endif
+
+        if (qml_mode_ && !global->HasProperty(*(proxy->name()))) {
+          var->set_is_qml_global(true);
+        }
+      }
+
       break;
 
     case DYNAMIC_LOOKUP:
index 0cd3be5..b04332c 100644 (file)
@@ -224,6 +224,11 @@ class Scope: public ZoneObject {
     end_position_ = statement_pos;
   }
 
+  // Enable qml mode for this scope
+  void EnableQmlMode() {
+    qml_mode_ = true;
+  }
+
   // ---------------------------------------------------------------------------
   // Predicates.
 
@@ -238,6 +243,7 @@ class Scope: public ZoneObject {
     return is_eval_scope() || is_function_scope() || is_global_scope();
   }
   bool is_strict_mode() const { return strict_mode_flag() == kStrictMode; }
+  bool is_qml_mode() const { return qml_mode_; }
   bool is_strict_mode_eval_scope() const {
     return is_eval_scope() && is_strict_mode();
   }
@@ -421,6 +427,8 @@ class Scope: public ZoneObject {
   // Source positions.
   int start_position_;
   int end_position_;
+  // This scope is a qml mode scope.
+  bool qml_mode_;
 
   // Computed via PropagateScopeInfo.
   bool outer_scope_calls_non_strict_eval_;
index d85e1b2..1887935 100644 (file)
@@ -68,7 +68,8 @@ Variable::Variable(Scope* scope,
     local_if_not_shadowed_(NULL),
     is_valid_LHS_(is_valid_LHS),
     is_accessed_from_inner_scope_(false),
-    is_used_(false) {
+    is_used_(false),
+    is_qml_global_(false) {
   // names must be canonicalized for fast equality checks
   ASSERT(name->IsSymbol());
 }
index e23e00b..d1112ff 100644 (file)
@@ -154,6 +154,8 @@ class Variable: public ZoneObject {
     index_ = index;
   }
 
+  bool is_qml_global() const { return is_qml_global_; }
+  void set_is_qml_global(bool is_qml_global) { is_qml_global_ = is_qml_global; }
  private:
   Scope* scope_;
   Handle<String> name_;
@@ -174,6 +176,9 @@ class Variable: public ZoneObject {
   // Usage info.
   bool is_accessed_from_inner_scope_;  // set by variable resolver
   bool is_used_;
+
+  // QML info
+  bool is_qml_global_;
 };
 
 
index 8a00b89..a6f8f8e 100644 (file)
@@ -139,6 +139,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
   __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx);
 
+  // Copy the qmlglobal object from the previous context.
+  __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
+  __ movq(Operand(rax, Context::SlotOffset(Context::QML_GLOBAL_INDEX)), rbx);
+
   // Initialize the rest of the slots to undefined.
   __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
   for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
@@ -203,6 +207,10 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
   __ movq(rbx, ContextOperand(rsi, Context::GLOBAL_INDEX));
   __ movq(ContextOperand(rax, Context::GLOBAL_INDEX), rbx);
 
+  // Copy the qmlglobal object from the previous context.
+  __ movq(rbx, ContextOperand(rsi, Context::QML_GLOBAL_INDEX));
+  __ movq(ContextOperand(rax, Context::QML_GLOBAL_INDEX), rbx);
+
   // Initialize the rest of the slots to the hole value.
   __ LoadRoot(rbx, Heap::kTheHoleValueRootIndex);
   for (int i = 0; i < slots_; i++) {
index e8fdef2..0b1181b 100644 (file)
@@ -168,12 +168,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
 
   // Possibly allocate a local context.
   int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
-  if (heap_slots > 0) {
+  if (heap_slots > 0 ||
+      (scope()->is_qml_mode() && scope()->is_global_scope())) {
     Comment cmnt(masm_, "[ Allocate local context");
     // Argument to NewContext is the function, which is still in rdi.
     __ push(rdi);
     if (heap_slots <= FastNewContextStub::kMaximumSlots) {
-      FastNewContextStub stub(heap_slots);
+      FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
       __ CallStub(&stub);
     } else {
       __ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -1144,10 +1145,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
 
   // All extension objects were empty and it is safe to use a global
   // load IC call.
-  __ movq(rax, GlobalObjectOperand());
+  __ movq(rax, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
   __ Move(rcx, var->name());
   Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
-  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
+  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || var->is_qml_global())
       ? RelocInfo::CODE_TARGET
       : RelocInfo::CODE_TARGET_CONTEXT;
   __ call(ic, mode);
@@ -1229,9 +1230,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
       // Use inline caching. Variable name is passed in rcx and the global
       // object on the stack.
       __ Move(rcx, var->name());
-      __ movq(rax, GlobalObjectOperand());
+      __ movq(rax, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
       Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
-      __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+      __ call(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT);
       context()->Plug(rax);
       break;
     }
@@ -1823,7 +1824,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
   if (var->IsUnallocated()) {
     // Global var, const, or let.
     __ Move(rcx, var->name());
-    __ movq(rdx, GlobalObjectOperand());
+    __ movq(rdx, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
     Handle<Code> ic = is_strict_mode()
         ? isolate()->builtins()->StoreIC_Initialize_Strict()
         : isolate()->builtins()->StoreIC_Initialize();
@@ -2105,7 +2106,9 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
       FLAG_harmony_scoping ? kStrictMode : strict_mode_flag();
   __ Push(Smi::FromInt(strict_mode));
 
-  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+  // Push the qml mode flag
+  __ Push(Smi::FromInt(is_qml_mode()));
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
 }
 
 
@@ -2157,8 +2160,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
   } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
     // Call to a global variable.  Push global object as receiver for the
     // call IC lookup.
-    __ push(GlobalObjectOperand());
-    EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
+    __ push(proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
+    EmitCallWithIC(expr, proxy->name(), proxy->var()->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT);
   } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
     // Call to a lookup slot (dynamically introduced variable).
     Label slow, done;
@@ -3643,7 +3646,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
         // but "delete this" is allowed.
         ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
         if (var->IsUnallocated()) {
-          __ push(GlobalObjectOperand());
+          __ push(var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand());
           __ Push(var->name());
           __ Push(Smi::FromInt(kNonStrictMode));
           __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
@@ -3965,7 +3968,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.
index 38a8c18..2a95fee 100644 (file)
@@ -196,12 +196,13 @@ bool LCodeGen::GeneratePrologue() {
 
   // Possibly allocate a local context.
   int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
-  if (heap_slots > 0) {
+  if (heap_slots > 0 ||
+      (scope()->is_qml_mode() && scope()->is_global_scope())) {
     Comment(";;; Allocate local context");
     // Argument to NewContext is the function, which is still in rdi.
     __ push(rdi);
     if (heap_slots <= FastNewContextStub::kMaximumSlots) {
-      FastNewContextStub stub(heap_slots);
+      FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
       __ CallStub(&stub);
     } else {
       __ CallRuntime(Runtime::kNewFunctionContext, 1);
@@ -2610,7 +2611,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
 
 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
   Register result = ToRegister(instr->result());
-  __ movq(result, GlobalObjectOperand());
+  __ movq(result, instr->qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
 }
 
 
@@ -3049,7 +3050,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
 void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
   ASSERT(ToRegister(instr->result()).is(rax));
   int arity = instr->arity();
-  RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
+  RelocInfo::Mode mode = instr->qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT;
   Handle<Code> ic =
       isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
   __ Move(rcx, instr->name());
index 598f890..fb13cda 100644 (file)
@@ -1102,7 +1102,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
 
 
 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
-  return DefineAsRegister(new LGlobalObject);
+  return DefineAsRegister(new LGlobalObject(instr->qml_global()));
 }
 
 
@@ -1172,7 +1172,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
 
 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
   argument_count_ -= instr->argument_count();
-  return MarkAsCall(DefineFixed(new LCallGlobal, rax), instr);
+  return MarkAsCall(DefineFixed(new LCallGlobal(instr->qml_global()), rax), instr);
 }
 
 
index b542071..9156162 100644 (file)
@@ -1300,7 +1300,13 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> {
 
 class LGlobalObject: public LTemplateInstruction<1, 0, 0> {
  public:
+  explicit LGlobalObject(bool qml_global) : qml_global_(qml_global) {}
+
   DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
+
+  bool qml_global() { return qml_global_; }
+ private:
+  bool qml_global_;
 };
 
 
@@ -1390,10 +1396,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_;
 };
 
 
index 3a655ef..b0563cd 100644 (file)
@@ -1386,6 +1386,11 @@ static inline Operand GlobalObjectOperand() {
 }
 
 
+static inline Operand QmlGlobalObjectOperand() {
+  return ContextOperand(rsi, Context::QML_GLOBAL_INDEX);
+}
+
+
 // Provides access to exit frame stack space (not GCed).
 static inline Operand StackSpaceOperand(int index) {
 #ifdef _WIN64