Fix logic error in assert in IsUndeclaredGlobal()
authormvstanton@chromium.org <mvstanton@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 17 Jan 2014 11:08:24 +0000 (11:08 +0000)
committermvstanton@chromium.org <mvstanton@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 17 Jan 2014 11:08:24 +0000 (11:08 +0000)
Recent changes in IC logic meant that CallStubs no longer use the Contextual bit. IsUndeclaredGlobal() needed to adjust for that.

In fact, now the CL has morphed to remove the notion of storing contextual state in the IC at all, it just becomes some extra ic state of the load ic. This took some adjustment in harmony code to use the global receiver for certain stores.

Now it's clearer that only LoadICs actually record any information about contextual or not.

R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/140943002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18660 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

31 files changed:
src/arm/ic-arm.cc
src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/code-stubs.h
src/disassembler.cc
src/full-codegen.cc
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/ia32/ic-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
src/ic.cc
src/ic.h
src/mips/ic-mips.cc
src/mips/lithium-codegen-mips.cc
src/mips/lithium-mips.cc
src/mips/lithium-mips.h
src/objects.cc
src/objects.h
src/promise.js
src/proxy.js
src/stub-cache.cc
src/stub-cache.h
src/x64/ic-x64.cc
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.cc
src/x64/lithium-x64.h
test/mjsunit/regress/regress-is-contextual.js [new file with mode: 0644]

index c43012a7b130dbc4f460152edec9bb6b48a2d3f5..5ccbd734358a240fc9e6b3b88977032cd243d4ea 100644 (file)
@@ -647,7 +647,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
   // -----------------------------------
 
   // Probe the stub cache.
-  ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
+  ExtraICState extra_ic_state = LoadIC::ComputeExtraICState(mode);
   Code::Flags flags = Code::ComputeFlags(
       Code::HANDLER, MONOMORPHIC, extra_ic_state,
       Code::NORMAL, Code::LOAD_IC);
index a8602937c50fed4750c830b4f2e27cf41035bc81..3002ba95bdea57d120c45729d55e244bd30e745a 100644 (file)
@@ -2037,16 +2037,6 @@ LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
-  LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* global_object = UseFixed(instr->global_object(), r1);
-  LOperand* value = UseFixed(instr->value(), r0);
-  LStoreGlobalGeneric* result =
-      new(zone()) LStoreGlobalGeneric(context, global_object, value);
-  return MarkAsCall(result, instr);
-}
-
-
 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   LOperand* context = UseRegisterAtStart(instr->value());
   LInstruction* result =
index ddff815c3f8aeda13c58fae7e2102d896e103be7..91cbc7156c201735515e55e9d7ea88aace3deb18 100644 (file)
@@ -160,7 +160,6 @@ class LCodeGen;
   V(StoreCodeEntry)                             \
   V(StoreContextSlot)                           \
   V(StoreGlobalCell)                            \
-  V(StoreGlobalGeneric)                         \
   V(StoreKeyed)                                 \
   V(StoreKeyedGeneric)                          \
   V(StoreNamedField)                            \
@@ -1666,28 +1665,6 @@ class LStoreGlobalCell V8_FINAL : public LTemplateInstruction<0, 1, 1> {
 };
 
 
-class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
- public:
-  LStoreGlobalGeneric(LOperand* context,
-                      LOperand* global_object,
-                      LOperand* value) {
-    inputs_[0] = context;
-    inputs_[1] = global_object;
-    inputs_[2] = value;
-  }
-
-  LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
-  DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
-
-  Handle<Object> name() const { return hydrogen()->name(); }
-  StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
-};
-
-
 class LLoadContextSlot V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LLoadContextSlot(LOperand* context) {
index 2ea6f7c6a18736808ead7df6f210ed934375467d..7c3db27b51da796f74c38d8675e3e3232bf8713c 100644 (file)
@@ -3001,19 +3001,6 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
 }
 
 
-void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
-  ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->global_object()).is(r1));
-  ASSERT(ToRegister(instr->value()).is(r0));
-
-  __ mov(r2, Operand(instr->name()));
-  Handle<Code> ic = StoreIC::initialize_stub(isolate(),
-                                             instr->strict_mode_flag(),
-                                             CONTEXTUAL);
-  CallCode(ic, RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
   Register context = ToRegister(instr->context());
   Register result = ToRegister(instr->result());
@@ -4229,8 +4216,7 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   // Name is always in r2.
   __ mov(r2, Operand(instr->name()));
   Handle<Code> ic = StoreIC::initialize_stub(isolate(),
-                                             instr->strict_mode_flag(),
-                                             NOT_CONTEXTUAL);
+                                             instr->strict_mode_flag());
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
 }
 
index f19258bb46c42df3e2647bca0099fafb37f7f8c7..bc4c5cdd18648f5900043079c76df8c9afe323e3 100644 (file)
@@ -1058,7 +1058,7 @@ class KeyedLoadFieldStub: public LoadFieldStub {
 class KeyedArrayCallStub: public HICStub {
  public:
   KeyedArrayCallStub(bool holey, int argc) : HICStub(), argc_(argc) {
-    bit_field_ = ContextualBits::encode(false) | HoleyBits::encode(holey);
+    bit_field_ = HoleyBits::encode(holey);
   }
 
   virtual Code::Kind kind() const { return Code::KEYED_CALL_IC; }
@@ -1087,9 +1087,10 @@ class KeyedArrayCallStub: public HICStub {
     return GetExtraICState() | ArgcBits::encode(argc_);
   }
 
-  class ContextualBits: public BitField<bool, 0, 1> {};
-  STATIC_ASSERT(IC::Contextual::kShift == ContextualBits::kShift);
-  STATIC_ASSERT(IC::Contextual::kSize == ContextualBits::kSize);
+  // We have to start storing extra ic bits at 1, because calls use bit zero
+  // for string stub state.
+  STATIC_ASSERT(CallICBase::StringStubState::kShift == 0);
+  STATIC_ASSERT(CallICBase::StringStubState::kSize == 1);
   class HoleyBits: public BitField<bool, 1, 1> {};
   STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 2);
   class ArgcBits: public BitField<int, 2, Code::kArgumentsBits> {};
index 5a4a93c6eefaedc7f7c3ada65617b7c058209e83..7f3ee19f8410c4f1598f70c780908f4eabe252f3 100644 (file)
@@ -237,7 +237,8 @@ static int DecodeIt(Isolate* isolate,
         Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address());
         Code::Kind kind = code->kind();
         if (code->is_inline_cache_stub()) {
-          if (code->IsContextual()) {
+          if (kind == Code::LOAD_IC &&
+              LoadIC::GetContextualMode(code->extra_ic_state()) == CONTEXTUAL) {
             out.AddFormatted(" contextual,");
           }
           InlineCacheState ic_state = code->ic_state();
index f88c7d42f348303ea1196e6774cb0f2c95465250..ec25b232844916f8eb7b673895ac09b66e4f0e53 100644 (file)
@@ -452,7 +452,7 @@ void FullCodeGenerator::CallLoadIC(ContextualMode mode, TypeFeedbackId id) {
 
 
 void FullCodeGenerator::CallStoreIC(ContextualMode mode, TypeFeedbackId id) {
-  Handle<Code> ic = StoreIC::initialize_stub(isolate(), strict_mode(), mode);
+  Handle<Code> ic = StoreIC::initialize_stub(isolate(), strict_mode());
   CallIC(ic, mode, id);
 }
 
index ae76418484a73b27d2a0a071419e2d8f6247caa6..737ce7339f2702b9ae10c0b61683429fda500dd6 100644 (file)
@@ -3351,12 +3351,6 @@ void HStoreGlobalCell::PrintDataTo(StringStream* stream) {
 }
 
 
-void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
-  stream->Add("%o = ", *name());
-  value()->PrintNameTo(stream);
-}
-
-
 void HLoadContextSlot::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
   stream->Add("[%d]", slot_index());
index beb339b1d6de8061a1f1cb46460e3d5f23a144ab..fdf5953caa9389b8e5d8acbf4a8d93b3678941f1 100644 (file)
@@ -165,7 +165,6 @@ class LChunkBuilder;
   V(StoreCodeEntry)                            \
   V(StoreContextSlot)                          \
   V(StoreGlobalCell)                           \
-  V(StoreGlobalGeneric)                        \
   V(StoreKeyed)                                \
   V(StoreKeyedGeneric)                         \
   V(StoreNamedField)                           \
@@ -5742,52 +5741,6 @@ class HStoreGlobalCell V8_FINAL : public HUnaryOperation {
 };
 
 
-class HStoreGlobalGeneric : public HTemplateInstruction<3> {
- public:
-  inline static HStoreGlobalGeneric* New(Zone* zone,
-                                         HValue* context,
-                                         HValue* global_object,
-                                         Handle<Object> name,
-                                         HValue* value,
-                                         StrictModeFlag strict_mode_flag) {
-    return new(zone) HStoreGlobalGeneric(context, global_object,
-                                         name, value, strict_mode_flag);
-  }
-
-  HValue* context() { return OperandAt(0); }
-  HValue* global_object() { return OperandAt(1); }
-  Handle<Object> name() const { return name_; }
-  HValue* value() { return OperandAt(2); }
-  StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
-
-  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
-
-  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
-    return Representation::Tagged();
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
-
- private:
-  HStoreGlobalGeneric(HValue* context,
-                      HValue* global_object,
-                      Handle<Object> name,
-                      HValue* value,
-                      StrictModeFlag strict_mode_flag)
-      : name_(name),
-        strict_mode_flag_(strict_mode_flag) {
-    SetOperandAt(0, context);
-    SetOperandAt(1, global_object);
-    SetOperandAt(2, value);
-    set_representation(Representation::Tagged());
-    SetAllSideEffects();
-  }
-
-  Handle<Object> name_;
-  StrictModeFlag strict_mode_flag_;
-};
-
-
 class HLoadContextSlot V8_FINAL : public HUnaryOperation {
  public:
   enum Mode {
index 1d068a4e531d0230c6436b90f3a3b7593b3a9b35..8e2ac74c503e6f4099f6eb96b33f8fa0cd5132f0 100644 (file)
@@ -5868,8 +5868,8 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
     }
   } else {
     HGlobalObject* global_object = Add<HGlobalObject>();
-    HStoreGlobalGeneric* instr =
-        Add<HStoreGlobalGeneric>(global_object, var->name(),
+    HStoreNamedGeneric* instr =
+        Add<HStoreNamedGeneric>(global_object, var->name(),
                                  value, function_strict_mode_flag());
     USE(instr);
     ASSERT(instr->HasObservableSideEffects());
index 047e5f7b2980c35ae194c6958703b68343a7735c..53481f25107a3fd8e81233453fa01cd9c88828d5 100644 (file)
@@ -1319,7 +1319,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
   // -----------------------------------
 
   // Probe the stub cache.
-  ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
+  ExtraICState extra_ic_state = LoadIC::ComputeExtraICState(mode);
   Code::Flags flags = Code::ComputeFlags(
       Code::HANDLER, MONOMORPHIC, extra_ic_state,
       Code::NORMAL, Code::LOAD_IC);
index 93f36568d4f27175350c90c4b59f6ad8895a90cf..7b50de78d6f63fbc8e605a28f3fb0b0c69f2c11e 100644 (file)
@@ -3196,19 +3196,6 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
 }
 
 
-void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
-  ASSERT(ToRegister(instr->context()).is(esi));
-  ASSERT(ToRegister(instr->global_object()).is(edx));
-  ASSERT(ToRegister(instr->value()).is(eax));
-
-  __ mov(ecx, instr->name());
-  Handle<Code> ic = StoreIC::initialize_stub(isolate(),
-                                             instr->strict_mode_flag(),
-                                             CONTEXTUAL);
-  CallCode(ic, RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
   Register context = ToRegister(instr->context());
   Register result = ToRegister(instr->result());
@@ -4499,8 +4486,7 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
 
   __ mov(ecx, instr->name());
   Handle<Code> ic = StoreIC::initialize_stub(isolate(),
-                                             instr->strict_mode_flag(),
-                                             NOT_CONTEXTUAL);
+                                             instr->strict_mode_flag());
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index 3f3516d3a0f51dfd796ce54718c56fe43dfdca01..b37589397fc94b4d9853fd7a6472feedb487fa9d 100644 (file)
@@ -2072,16 +2072,6 @@ LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
-  LOperand* context = UseFixed(instr->context(), esi);
-  LOperand* global_object = UseFixed(instr->global_object(), edx);
-  LOperand* value = UseFixed(instr->value(), eax);
-  LStoreGlobalGeneric* result =
-      new(zone()) LStoreGlobalGeneric(context, global_object, value);
-  return MarkAsCall(result, instr);
-}
-
-
 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   LOperand* context = UseRegisterAtStart(instr->value());
   LInstruction* result =
index 680d5c8c80f1e77531b6f81d0d14687bc8023a4a..a505e585ed7abc79a091a33d0ee8668109fd0c6a 100644 (file)
@@ -160,7 +160,6 @@ class LCodeGen;
   V(StoreCodeEntry)                             \
   V(StoreContextSlot)                           \
   V(StoreGlobalCell)                            \
-  V(StoreGlobalGeneric)                         \
   V(StoreKeyed)                                 \
   V(StoreKeyedGeneric)                          \
   V(StoreNamedField)                            \
@@ -1669,28 +1668,6 @@ class LStoreGlobalCell V8_FINAL : public LTemplateInstruction<0, 1, 0> {
 };
 
 
-class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
- public:
-  LStoreGlobalGeneric(LOperand* context,
-                      LOperand* global_object,
-                      LOperand* value) {
-    inputs_[0] = context;
-    inputs_[1] = global_object;
-    inputs_[2] = value;
-  }
-
-  LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
-  DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
-
-  Handle<Object> name() const { return hydrogen()->name(); }
-  StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
-};
-
-
 class LLoadContextSlot V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LLoadContextSlot(LOperand* context) {
index 07be39af92e8130921869f4a799603d324e9ed5b..e817394e0bd80efda34317a0bb93e96f8312141d 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -626,7 +626,7 @@ MaybeObject* CallICBase::LoadFunction(Handle<Object> object,
   if (!lookup.IsFound()) {
     // If the object does not have the requested property, check which
     // exception we need to throw.
-    return IsUndeclaredGlobal(object)
+    return object->IsGlobalObject()
         ? ReferenceError("not_defined", name)
         : TypeError("undefined_method", object, name);
   }
@@ -643,7 +643,7 @@ MaybeObject* CallICBase::LoadFunction(Handle<Object> object,
   if (lookup.IsInterceptor() && attr == ABSENT) {
     // If the object does not have the requested property, check which
     // exception we need to throw.
-    return IsUndeclaredGlobal(object)
+    return object->IsGlobalObject()
         ? ReferenceError("not_defined", name)
         : TypeError("undefined_method", object, name);
   }
@@ -1102,7 +1102,7 @@ void IC::PatchCache(Handle<Type> type,
 
 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) {
   Handle<Code> ic = isolate->stub_cache()->ComputeLoad(
-      UNINITIALIZED, IC::ComputeExtraICState(mode));
+      UNINITIALIZED, ComputeExtraICState(mode));
   return ic;
 }
 
@@ -1110,7 +1110,7 @@ Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) {
 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate,
                                           ContextualMode mode) {
   return isolate->stub_cache()->ComputeLoad(
-      PREMONOMORPHIC, IC::ComputeExtraICState(mode));
+      PREMONOMORPHIC, ComputeExtraICState(mode));
 }
 
 
@@ -1570,7 +1570,7 @@ MaybeObject* StoreIC::Store(Handle<Object> object,
   if (!can_store &&
       strict_mode() == kStrictMode &&
       !(lookup.IsProperty() && lookup.IsReadOnly()) &&
-      IsUndeclaredGlobal(object)) {
+      object->IsGlobalObject()) {
     // Strict mode doesn't allow setting non-existent global property.
     return ReferenceError("not_defined", name);
   }
@@ -1598,9 +1598,8 @@ MaybeObject* StoreIC::Store(Handle<Object> object,
 
 
 Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
-                                      StrictModeFlag strict_mode,
-                                      ContextualMode mode) {
-  ExtraICState extra_state = ComputeExtraICState(strict_mode, mode);
+                                      StrictModeFlag strict_mode) {
+  ExtraICState extra_state = ComputeExtraICState(strict_mode);
   Handle<Code> ic = isolate->stub_cache()->ComputeStore(
       UNINITIALIZED, extra_state);
   return ic;
@@ -1618,10 +1617,8 @@ Handle<Code> StoreIC::generic_stub() const {
 
 
 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate,
-                                           StrictModeFlag strict_mode,
-                                           ContextualMode contextual_mode) {
-  ExtraICState state = StoreIC::ComputeExtraICState(strict_mode,
-                                                    contextual_mode);
+                                           StrictModeFlag strict_mode) {
+  ExtraICState state = ComputeExtraICState(strict_mode);
   return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state);
 }
 
index 8a32a40447a80f55afd09a39f734a9ff6473b61a..2b258ba2e9e9badedb667bab0b4bb5921f91f88e 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -89,20 +89,6 @@ class IC {
     EXTRA_CALL_FRAME = 1
   };
 
-  // ExtraICState shared by all ICs.
-  class Contextual: public BitField<ContextualMode, 0, 1> {};
-  STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
-  static ExtraICState ComputeExtraICState(ContextualMode mode) {
-    return Contextual::encode(mode);
-  }
-
-  static ContextualMode GetContextualMode(ExtraICState state) {
-    return Contextual::decode(state);
-  }
-
-  static const ExtraICState kContextualState =
-      static_cast<int>(CONTEXTUAL) << Contextual::kShift;
-
   // Construct the IC structure with the given number of extra
   // JavaScript frames on the stack.
   IC(FrameDepth depth, Isolate* isolate);
@@ -120,30 +106,19 @@ class IC {
   // Clear the inline cache to initial state.
   static void Clear(Isolate* isolate, Address address);
 
-  // Returns if this IC is for contextual (no explicit receiver)
-  // access to properties.
-  bool IsUndeclaredGlobal(Handle<Object> receiver) {
-    if (receiver->IsGlobalObject()) {
-      return IsCallStub() || IsContextual();
-    } else {
-      ASSERT(!IsContextual());
-      return false;
-    }
-  }
-
 #ifdef DEBUG
-  bool IsLoadStub() {
+  bool IsLoadStub() const {
     return target()->is_load_stub() || target()->is_keyed_load_stub();
   }
 
-  bool IsStoreStub() {
+  bool IsStoreStub() const {
     return target()->is_store_stub() || target()->is_keyed_store_stub();
   }
 
-#endif
-  bool IsCallStub() {
+  bool IsCallStub() const {
     return target()->is_call_stub() || target()->is_keyed_call_stub();
   }
+#endif
 
   // Determines which map must be used for keeping the code stub.
   // These methods should not be called with undefined or null.
@@ -174,12 +149,6 @@ class IC {
   static Handle<Type> MapToType(Handle<Map> type);
   static Handle<Type> CurrentTypeOf(Handle<Object> object, Isolate* isolate);
 
-  ContextualMode contextual_mode() const {
-    return Contextual::decode(extra_ic_state());
-  }
-
-  bool IsContextual() const { return contextual_mode() == CONTEXTUAL; }
-
  protected:
   // Get the call-site target; used for determining the state.
   Handle<Code> target() const { return target_; }
@@ -439,11 +408,38 @@ class KeyedCallIC: public CallICBase {
 
 class LoadIC: public IC {
  public:
+  // ExtraICState bits
+  class Contextual: public BitField<ContextualMode, 0, 1> {};
+  STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
+
+  static ExtraICState ComputeExtraICState(ContextualMode mode) {
+    return Contextual::encode(mode);
+  }
+
+  static ContextualMode GetContextualMode(ExtraICState state) {
+    return Contextual::decode(state);
+  }
+
+  ContextualMode contextual_mode() const {
+    return Contextual::decode(extra_ic_state());
+  }
+
   explicit LoadIC(FrameDepth depth, Isolate* isolate)
       : IC(depth, isolate) {
     ASSERT(IsLoadStub());
   }
 
+  // Returns if this IC is for contextual (no explicit receiver)
+  // access to properties.
+  bool IsUndeclaredGlobal(Handle<Object> receiver) {
+    if (receiver->IsGlobalObject()) {
+      return contextual_mode() == CONTEXTUAL;
+    } else {
+      ASSERT(contextual_mode() != CONTEXTUAL);
+      return false;
+    }
+  }
+
   // Code generator routines.
   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
   static void GeneratePreMonomorphic(MacroAssembler* masm) {
@@ -462,6 +458,14 @@ class LoadIC: public IC {
  protected:
   virtual Code::Kind kind() const { return Code::LOAD_IC; }
 
+  void set_target(Code* code) {
+    // The contextual mode must be preserved across IC patching.
+    ASSERT(GetContextualMode(code->extra_ic_state()) ==
+           GetContextualMode(target()->extra_ic_state()));
+
+    IC::set_target(code);
+  }
+
   virtual Handle<Code> slow_stub() const {
     return isolate()->builtins()->LoadIC_Slow();
   }
@@ -572,17 +576,11 @@ class KeyedLoadIC: public LoadIC {
 
 class StoreIC: public IC {
  public:
-  // ExtraICState bits
   class StrictModeState: public BitField<StrictModeFlag, 1, 1> {};
   static ExtraICState ComputeExtraICState(StrictModeFlag flag) {
     return StrictModeState::encode(flag);
   }
 
-  static ExtraICState ComputeExtraICState(StrictModeFlag flag,
-                                          ContextualMode mode) {
-    return StrictModeState::encode(flag) | Contextual::encode(mode);
-  }
-
   static StrictModeFlag GetStrictMode(ExtraICState state) {
     return StrictModeState::decode(state);
   }
@@ -615,8 +613,7 @@ class StoreIC: public IC {
                                          StrictModeFlag strict_mode);
 
   static Handle<Code> initialize_stub(Isolate* isolate,
-                                      StrictModeFlag strict_mode,
-                                      ContextualMode mode);
+                                      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT MaybeObject* Store(
       Handle<Object> object,
@@ -637,12 +634,11 @@ class StoreIC: public IC {
   }
 
   virtual Handle<Code> pre_monomorphic_stub() {
-    return pre_monomorphic_stub(isolate(), strict_mode(), contextual_mode());
+    return pre_monomorphic_stub(isolate(), strict_mode());
   }
 
   static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
-                                           StrictModeFlag strict_mode,
-                                           ContextualMode contextual_mode);
+                                           StrictModeFlag strict_mode);
 
   // Update the inline cache and the global stub cache based on the
   // lookup result.
@@ -661,9 +657,6 @@ class StoreIC: public IC {
     // Strict mode must be preserved across IC patching.
     ASSERT(GetStrictMode(code->extra_ic_state()) ==
            GetStrictMode(target()->extra_ic_state()));
-    // As must the contextual mode
-    ASSERT(GetContextualMode(code->extra_ic_state()) ==
-           GetContextualMode(target()->extra_ic_state()));
     IC::set_target(code);
   }
 
index 6c5d7c285022fe06b1336479bddad2e8d53aa5df..68f82253d8249eb356b97a999825a9f613fa6eaf 100644 (file)
@@ -646,7 +646,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
   // -----------------------------------
 
   // Probe the stub cache.
-  ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
+  ExtraICState extra_ic_state = LoadIC::ComputeExtraICState(mode);
   Code::Flags flags = Code::ComputeFlags(
       Code::HANDLER, MONOMORPHIC, extra_ic_state,
       Code::NORMAL, Code::LOAD_IC);
index 9a081238f4d57e58df826089964187bcf59a7106..ab2dcd7c8010b5d088080d69f95cc59b3ba9ecbb 100644 (file)
@@ -2851,18 +2851,6 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
 }
 
 
-void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
-  ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->global_object()).is(a1));
-  ASSERT(ToRegister(instr->value()).is(a0));
-
-  __ li(a2, Operand(instr->name()));
-  Handle<Code> ic = StoreIC::initialize_stub(isolate(),
-                                             instr->strict_mode_flag(),
-                                             CONTEXTUAL);
-  CallCode(ic, RelocInfo::CODE_TARGET, instr);
-}
-
 
 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
   Register context = ToRegister(instr->context());
@@ -4145,8 +4133,7 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   // Name is always in a2.
   __ li(a2, Operand(instr->name()));
   Handle<Code> ic = StoreIC::initialize_stub(isolate(),
-                                             instr->strict_mode_flag(),
-                                             NOT_CONTEXTUAL);
+                                             instr->strict_mode_flag());
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index 2676d43b9ec6abf198b43fdf690b8072fb015ff6..0a14c3ed484ffa89b1b9e46eee5c29e95c75f73c 100644 (file)
@@ -1962,16 +1962,6 @@ LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
-  LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* global_object = UseFixed(instr->global_object(), a1);
-  LOperand* value = UseFixed(instr->value(), a0);
-  LStoreGlobalGeneric* result =
-      new(zone()) LStoreGlobalGeneric(context, global_object, value);
-  return MarkAsCall(result, instr);
-}
-
-
 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   LOperand* context = UseRegisterAtStart(instr->value());
   LInstruction* result =
index 4bda5f7a38038587e9b4f5118fe28df750cf057d..d682748e145076e2241caa4cfbf203756e64762e 100644 (file)
@@ -159,7 +159,6 @@ class LCodeGen;
   V(StoreCodeEntry)                             \
   V(StoreContextSlot)                           \
   V(StoreGlobalCell)                            \
-  V(StoreGlobalGeneric)                         \
   V(StoreKeyed)                                 \
   V(StoreKeyedGeneric)                          \
   V(StoreNamedField)                            \
@@ -1646,28 +1645,6 @@ class LStoreGlobalCell V8_FINAL : public LTemplateInstruction<0, 1, 1> {
 };
 
 
-class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
- public:
-  LStoreGlobalGeneric(LOperand* context,
-                      LOperand* global_object,
-                      LOperand* value) {
-    inputs_[0] = context;
-    inputs_[1] = global_object;
-    inputs_[2] = value;
-  }
-
-  LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
-  DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
-
-  Handle<Object> name() const { return hydrogen()->name(); }
-  StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
-};
-
-
 class LLoadContextSlot V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LLoadContextSlot(LOperand* context) {
index e4763247f587b78f3c40d41ea56547ea4244aeb2..30778e4765232c9414da146cdff5f18d62b8df25 100644 (file)
@@ -10877,17 +10877,6 @@ bool Code::CanDeoptAt(Address pc) {
 }
 
 
-bool Code::IsContextual() {
-  ASSERT(is_inline_cache_stub());
-  Kind kind = this->kind();
-  if (kind == STORE_IC || kind == LOAD_IC || kind == CALL_IC) {
-    ExtraICState extra_state = extra_ic_state();
-    return IC::GetContextualMode(extra_state) == CONTEXTUAL;
-  }
-  return false;
-}
-
-
 // Identify kind of code.
 const char* Code::Kind2String(Kind kind) {
   switch (kind) {
index dd0bb1e2128d4cc5891686bf8ede43cf24b6caf4..85cae02da4b0231dba2f9074abc800319c44058a 100644 (file)
@@ -5234,7 +5234,6 @@ class Code: public HeapObject {
            kind == BINARY_OP_IC;
   }
 
-  bool IsContextual();  // Only valid for IC stubs.
   inline StubType type();  // Only valid for monomorphic IC stubs.
   inline int arguments_count();  // Only valid for call IC stubs.
 
index 2a3f4fd5cfd93f1a396bc362d3bd2a42b09d25cd..db7863f8098f686cab2fc4545eab1429165797fc 100644 (file)
@@ -296,7 +296,8 @@ function PromiseOne(values) {
 
 function SetUpPromise() {
   %CheckIsBootstrapping()
-  global.Promise = $Promise;
+  var global_receiver = %GlobalReceiver(global);
+  global_receiver.Promise = $Promise;
   InstallFunctions($Promise, DONT_ENUM, [
     "defer", PromiseDeferred,
     "resolve", PromiseResolved,
index 4c03f215389cebafaae5713169d399d130258b6a..06be087c718fe8998974655af623233e5be201d2 100644 (file)
@@ -72,7 +72,8 @@ function ProxyCreateFunction(handler, callTrap, constructTrap) {
 function SetUpProxy() {
   %CheckIsBootstrapping()
 
-  global.Proxy = $Proxy;
+  var global_receiver = %GlobalReceiver(global);
+  global_receiver.Proxy = $Proxy;
 
   // Set up non-enumerable properties of the Proxy object.
   InstallFunctions($Proxy, DONT_ENUM, [
index eb422a1046e8f5e6ec77fad801c755662d26cdd2..fa0a04c328e59bb9595b40cc76d61464496212f4 100644 (file)
@@ -884,12 +884,10 @@ RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
 
 static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) {
   // If the load is non-contextual, just return the undefined result.
-  // Note that both keyed and non-keyed loads may end up here, so we
-  // can't use either LoadIC or KeyedLoadIC constructors.
+  // Note that both keyed and non-keyed loads may end up here.
   HandleScope scope(isolate);
-  IC ic(IC::NO_EXTRA_FRAME, isolate);
-  ASSERT(ic.IsLoadStub());
-  if (!ic.IsContextual()) {
+  LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
+  if (ic.contextual_mode() != CONTEXTUAL) {
     return isolate->heap()->undefined_value();
   }
 
@@ -1048,9 +1046,6 @@ Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   if (kind == Code::CALL_IC) {
-    // Call normal is always with a explict receiver.
-    ASSERT(!CallIC::Contextual::decode(
-        Code::ExtractExtraICStateFromFlags(flags)));
     CallIC::GenerateNormal(masm(), argc);
   } else {
     KeyedCallIC::GenerateNormal(masm(), argc);
@@ -1106,7 +1101,7 @@ Handle<Code> StubCompiler::CompileLoadPreMonomorphic(Code::Flags flags) {
 
 Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) {
   ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
-  ContextualMode mode = IC::GetContextualMode(extra_state);
+  ContextualMode mode = LoadIC::GetContextualMode(extra_state);
   LoadIC::GenerateMegamorphic(masm(), mode);
   Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic");
   PROFILE(isolate(),
index 1f3fa9320213c5d2b6b4463ce723287b251449d7..2e89a516aaf420812df2e7eafb4a9816d406ab2d 100644 (file)
@@ -517,9 +517,6 @@ class StubCompiler BASE_EMBEDDED {
   Isolate* isolate() { return isolate_; }
   Heap* heap() { return isolate()->heap(); }
   Factory* factory() { return isolate()->factory(); }
-  ContextualMode contextual_mode() {
-    return IC::GetContextualMode(extra_state());
-  }
 
   static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
 
@@ -687,6 +684,10 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler {
   static Register* registers();
 
  protected:
+  ContextualMode contextual_mode() {
+    return LoadIC::GetContextualMode(extra_state());
+  }
+
   virtual Register HandlerFrontendHeader(Handle<Type> type,
                                          Register object_reg,
                                          Handle<JSObject> holder,
index 7c1d8a4166c0741c46fdc2289697b4006f3b10c8..454e3bdaeb21d5ba8046379d4c0ef77648720043 100644 (file)
@@ -1345,7 +1345,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
   // -----------------------------------
 
   // Probe the stub cache.
-  ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
+  ExtraICState extra_ic_state = LoadIC::ComputeExtraICState(mode);
   Code::Flags flags = Code::ComputeFlags(
       Code::HANDLER, MONOMORPHIC, extra_ic_state,
       Code::NORMAL, Code::LOAD_IC);
index 84e86fe7db1ae3cebc2615d2f8ac714987f5a9cf..6313b4aa4a10c70d922c67a57508dfc316728294 100644 (file)
@@ -2743,19 +2743,6 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
 }
 
 
-void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
-  ASSERT(ToRegister(instr->context()).is(rsi));
-  ASSERT(ToRegister(instr->global_object()).is(rdx));
-  ASSERT(ToRegister(instr->value()).is(rax));
-
-  __ Move(rcx, instr->name());
-  Handle<Code> ic = StoreIC::initialize_stub(isolate(),
-                                             instr->strict_mode_flag(),
-                                             CONTEXTUAL);
-  CallCode(ic, RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
   Register context = ToRegister(instr->context());
   Register result = ToRegister(instr->result());
@@ -4079,8 +4066,7 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
 
   __ Move(rcx, instr->hydrogen()->name());
   Handle<Code> ic = StoreIC::initialize_stub(isolate(),
-                                             instr->strict_mode_flag(),
-                                             NOT_CONTEXTUAL);
+                                             instr->strict_mode_flag());
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index 2e760a3e8c9cc5f7c46920e565fa268e1525771c..d4e29f67054c5263bb6a542587eec1d9aa8b332d 100644 (file)
@@ -1948,16 +1948,6 @@ LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
 }
 
 
-LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
-  LOperand* context = UseFixed(instr->context(), rsi);
-  LOperand* global_object = UseFixed(instr->global_object(), rdx);
-  LOperand* value = UseFixed(instr->value(), rax);
-  LStoreGlobalGeneric* result =
-      new(zone()) LStoreGlobalGeneric(context, global_object, value);
-  return MarkAsCall(result, instr);
-}
-
-
 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   LOperand* context = UseRegisterAtStart(instr->value());
   LInstruction* result =
index 61b49653c7f68136f31aa505456a5db8093dfed2..0aab4431e3532ce041e5c52bcf09ec4b819a4bc0 100644 (file)
@@ -158,7 +158,6 @@ class LCodeGen;
   V(StoreCodeEntry)                             \
   V(StoreContextSlot)                           \
   V(StoreGlobalCell)                            \
-  V(StoreGlobalGeneric)                         \
   V(StoreKeyed)                                 \
   V(StoreKeyedGeneric)                          \
   V(StoreNamedField)                            \
@@ -1611,28 +1610,6 @@ class LStoreGlobalCell V8_FINAL : public LTemplateInstruction<0, 1, 1> {
 };
 
 
-class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
- public:
-  explicit LStoreGlobalGeneric(LOperand* context,
-                               LOperand* global_object,
-                               LOperand* value) {
-    inputs_[0] = context;
-    inputs_[1] = global_object;
-    inputs_[2] = value;
-  }
-
-  LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
-  DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
-
-  Handle<Object> name() const { return hydrogen()->name(); }
-  StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
-};
-
-
 class LLoadContextSlot V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LLoadContextSlot(LOperand* context) {
diff --git a/test/mjsunit/regress/regress-is-contextual.js b/test/mjsunit/regress/regress-is-contextual.js
new file mode 100644 (file)
index 0000000..844f4a2
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// CallIC accumulates feedback that string index is out of bounds, then
+// misses
+function foo(index) {
+  return text.charAt(index);
+}
+
+var text = "hi there";
+foo(0);
+foo(0);
+foo(100);     // Accumulate feedback that index is out of bounds.
+text = false;
+
+// This line ASSERTS in debug without fix.
+assertThrows(function () { foo(); }, TypeError);