This adds generic support for ExternalReferences in Hydrogen (and Lithium), as requir...
authorbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 29 Jul 2013 13:56:51 +0000 (13:56 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 29 Jul 2013 13:56:51 +0000 (13:56 +0000)
R=danno@chromium.org, titzer@chromium.org

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

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

19 files changed:
src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/assembler.h
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.h
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
src/mips/lithium-codegen-mips.cc
src/mips/lithium-mips.cc
src/mips/lithium-mips.h
src/x64/lithium-codegen-x64.cc
src/x64/lithium-codegen-x64.h
src/x64/lithium-x64.cc
src/x64/lithium-x64.h

index f54e84b..b55679e 100644 (file)
@@ -2095,6 +2095,8 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
     return DefineAsRegister(new(zone()) LConstantI);
   } else if (r.IsDouble()) {
     return DefineAsRegister(new(zone()) LConstantD);
+  } else if (r.IsExternal()) {
+    return DefineAsRegister(new(zone()) LConstantE);
   } else if (r.IsTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
index 241bba9..eecacec 100644 (file)
@@ -79,6 +79,7 @@ class LCodeGen;
   V(CmpMapAndBranch)                            \
   V(CmpT)                                       \
   V(ConstantD)                                  \
+  V(ConstantE)                                  \
   V(ConstantI)                                  \
   V(ConstantS)                                  \
   V(ConstantT)                                  \
@@ -1232,6 +1233,17 @@ class LConstantD: public LTemplateInstruction<1, 0, 0> {
 };
 
 
+class LConstantE: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  ExternalReference value() const {
+    return hydrogen()->ExternalReferenceValue();
+  }
+};
+
+
 class LConstantT: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
index 057ca1e..929d04d 100644 (file)
@@ -1822,6 +1822,11 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
 }
 
 
+void LCodeGen::DoConstantE(LConstantE* instr) {
+  __ mov(ToRegister(instr->result()), Operand(instr->value()));
+}
+
+
 void LCodeGen::DoConstantT(LConstantT* instr) {
   Handle<Object> value = instr->value();
   AllowDeferredHandleDereference smi_check;
@@ -3002,6 +3007,13 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
   HObjectAccess access = instr->hydrogen()->access();
   int offset = access.offset();
   Register object = ToRegister(instr->object());
+
+  if (access.IsExternalMemory()) {
+    Register result = ToRegister(instr->result());
+    __ ldr(result, MemOperand(object, offset));
+    return;
+  }
+
   if (instr->hydrogen()->representation().IsDouble()) {
     DwVfpRegister result = ToDoubleRegister(instr->result());
     __ vldr(result, FieldMemOperand(object, offset));
@@ -4181,10 +4193,15 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
 
   Register object = ToRegister(instr->object());
   Register scratch = scratch0();
-
   HObjectAccess access = instr->hydrogen()->access();
   int offset = access.offset();
 
+  if (access.IsExternalMemory()) {
+    Register value = ToRegister(instr->value());
+    __ str(value, MemOperand(object, offset));
+    return;
+  }
+
   Handle<Map> transition = instr->transition();
 
   if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
index 481add5..d70d5aa 100644 (file)
@@ -684,6 +684,8 @@ class ExternalReference BASE_EMBEDDED {
 
   typedef void* ExternalReferenceRedirector(void* original, Type type);
 
+  ExternalReference() : address_(NULL) {}
+
   ExternalReference(Builtins::CFunctionId id, Isolate* isolate);
 
   ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate);
@@ -829,7 +831,7 @@ class ExternalReference BASE_EMBEDDED {
 
   static ExternalReference cpu_features();
 
-  Address address() const {return reinterpret_cast<Address>(address_);}
+  Address address() const { return reinterpret_cast<Address>(address_); }
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Function Debug::Break()
@@ -868,6 +870,14 @@ class ExternalReference BASE_EMBEDDED {
 
   static ExternalReference stress_deopt_count(Isolate* isolate);
 
+  bool operator==(const ExternalReference& other) const {
+    return address_ == other.address_;
+  }
+
+  bool operator!=(const ExternalReference& other) const {
+    return !(*this == other);
+  }
+
  private:
   explicit ExternalReference(void* address)
       : address_(address) {}
index 3eca181..743bb09 100644 (file)
@@ -448,6 +448,7 @@ const char* HType::ToString() {
   // Note: The c1visualizer syntax for locals allows only a sequence of the
   // following characters: A-Za-z0-9_-|:
   switch (type_) {
+    case kNone: return "none";
     case kTagged: return "tagged";
     case kTaggedPrimitive: return "primitive";
     case kTaggedNumber: return "number";
@@ -2644,6 +2645,7 @@ HConstant::HConstant(Handle<Object> handle, Representation r)
     has_smi_value_(false),
     has_int32_value_(false),
     has_double_value_(false),
+    has_external_reference_value_(false),
     is_internalized_string_(false),
     is_not_in_new_space_(true),
     is_cell_(false),
@@ -2679,15 +2681,16 @@ HConstant::HConstant(Handle<Object> handle,
                      bool is_not_in_new_space,
                      bool is_cell,
                      bool boolean_value)
-    : handle_(handle),
-      unique_id_(unique_id),
-      has_smi_value_(false),
-      has_int32_value_(false),
-      has_double_value_(false),
-      is_internalized_string_(is_internalize_string),
-      is_not_in_new_space_(is_not_in_new_space),
-      is_cell_(is_cell),
-      boolean_value_(boolean_value) {
+  : handle_(handle),
+    unique_id_(unique_id),
+    has_smi_value_(false),
+    has_int32_value_(false),
+    has_double_value_(false),
+    has_external_reference_value_(false),
+    is_internalized_string_(is_internalize_string),
+    is_not_in_new_space_(is_not_in_new_space),
+    is_cell_(is_cell),
+    boolean_value_(boolean_value) {
   ASSERT(!handle.is_null());
   ASSERT(!type.IsTaggedNumber());
   set_type(type);
@@ -2699,17 +2702,18 @@ HConstant::HConstant(int32_t integer_value,
                      Representation r,
                      bool is_not_in_new_space,
                      Handle<Object> optional_handle)
-    : handle_(optional_handle),
-      unique_id_(),
-      has_smi_value_(Smi::IsValid(integer_value)),
-      has_int32_value_(true),
-      has_double_value_(true),
-      is_internalized_string_(false),
-      is_not_in_new_space_(is_not_in_new_space),
-      is_cell_(false),
-      boolean_value_(integer_value != 0),
-      int32_value_(integer_value),
-      double_value_(FastI2D(integer_value)) {
+  : handle_(optional_handle),
+    unique_id_(),
+    has_smi_value_(Smi::IsValid(integer_value)),
+    has_int32_value_(true),
+    has_double_value_(true),
+    has_external_reference_value_(false),
+    is_internalized_string_(false),
+    is_not_in_new_space_(is_not_in_new_space),
+    is_cell_(false),
+    boolean_value_(integer_value != 0),
+    int32_value_(integer_value),
+    double_value_(FastI2D(integer_value)) {
   set_type(has_smi_value_ ? HType::Smi() : HType::TaggedNumber());
   Initialize(r);
 }
@@ -2719,22 +2723,38 @@ HConstant::HConstant(double double_value,
                      Representation r,
                      bool is_not_in_new_space,
                      Handle<Object> optional_handle)
-    : handle_(optional_handle),
-      unique_id_(),
-      has_int32_value_(IsInteger32(double_value)),
-      has_double_value_(true),
-      is_internalized_string_(false),
-      is_not_in_new_space_(is_not_in_new_space),
-      is_cell_(false),
-      boolean_value_(double_value != 0 && !std::isnan(double_value)),
-      int32_value_(DoubleToInt32(double_value)),
-      double_value_(double_value) {
+  : handle_(optional_handle),
+    unique_id_(),
+    has_int32_value_(IsInteger32(double_value)),
+    has_double_value_(true),
+    has_external_reference_value_(false),
+    is_internalized_string_(false),
+    is_not_in_new_space_(is_not_in_new_space),
+    is_cell_(false),
+    boolean_value_(double_value != 0 && !std::isnan(double_value)),
+    int32_value_(DoubleToInt32(double_value)),
+    double_value_(double_value) {
   has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_);
   set_type(has_smi_value_ ? HType::Smi() : HType::TaggedNumber());
   Initialize(r);
 }
 
 
+HConstant::HConstant(ExternalReference reference)
+  : has_smi_value_(false),
+    has_int32_value_(false),
+    has_double_value_(false),
+    has_external_reference_value_(true),
+    is_internalized_string_(false),
+    is_not_in_new_space_(true),
+    is_cell_(false),
+    boolean_value_(true),
+    external_reference_value_(reference) {
+  set_type(HType::None());
+  Initialize(Representation::External());
+}
+
+
 void HConstant::Initialize(Representation r) {
   if (r.IsNone()) {
     if (has_smi_value_ && kSmiValueSize == 31) {
@@ -2743,6 +2763,8 @@ void HConstant::Initialize(Representation r) {
       r = Representation::Integer32();
     } else if (has_double_value_) {
       r = Representation::Double();
+    } else if (has_external_reference_value_) {
+      r = Representation::External();
     } else {
       r = Representation::Tagged();
     }
@@ -2767,12 +2789,16 @@ HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
   if (r.IsSmi() && !has_smi_value_) return NULL;
   if (r.IsInteger32() && !has_int32_value_) return NULL;
   if (r.IsDouble() && !has_double_value_) return NULL;
+  if (r.IsExternal() && !has_external_reference_value_) return NULL;
   if (has_int32_value_) {
     return new(zone) HConstant(int32_value_, r, is_not_in_new_space_, handle_);
   }
   if (has_double_value_) {
     return new(zone) HConstant(double_value_, r, is_not_in_new_space_, handle_);
   }
+  if (has_external_reference_value_) {
+    return new(zone) HConstant(external_reference_value_);
+  }
   ASSERT(!handle_.is_null());
   return new(zone) HConstant(handle_,
                              unique_id_,
@@ -2825,6 +2851,9 @@ void HConstant::PrintDataTo(StringStream* stream) {
     stream->Add("%d ", int32_value_);
   } else if (has_double_value_) {
     stream->Add("%f ", FmtElm(double_value_));
+  } else if (has_external_reference_value_) {
+    stream->Add("%p ", reinterpret_cast<void*>(
+            external_reference_value_.address()));
   } else {
     handle()->ShortPrint(stream);
   }
@@ -4505,6 +4534,10 @@ void HObjectAccess::SetGVNFlags(HValue *instr, bool is_store) {
       instr->SetGVNFlag(is_store
           ? kChangesMaps : kDependsOnMaps);
       break;
+    case kExternalMemory:
+      instr->SetGVNFlag(is_store
+          ? kChangesExternalMemory : kDependsOnExternalMemory);
+      break;
   }
 }
 
@@ -4531,6 +4564,9 @@ void HObjectAccess::PrintTo(StringStream* stream) {
       if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString());
       stream->Add("[backing-store]");
       break;
+    case kExternalMemory:
+      stream->Add("[external-memory]");
+      break;
   }
 
   stream->Add("@%d", offset());
index 1015b6e..e71b7cd 100644 (file)
@@ -211,7 +211,7 @@ class LChunkBuilder;
   V(GlobalVars)                                \
   V(InobjectFields)                            \
   V(OsrEntries)                                \
-  V(SpecializedArrayElements)
+  V(ExternalMemory)
 
 
 #define DECLARE_ABSTRACT_INSTRUCTION(type)          \
@@ -350,6 +350,7 @@ class UniqueValueId {
 
 class HType {
  public:
+  static HType None() { return HType(kNone); }
   static HType Tagged() { return HType(kTagged); }
   static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
   static HType TaggedNumber() { return HType(kTaggedNumber); }
@@ -447,6 +448,7 @@ class HType {
 
  private:
   enum Type {
+    kNone = 0x0,             // 0000 0000 0000 0000
     kTagged = 0x1,           // 0000 0000 0000 0001
     kTaggedPrimitive = 0x5,  // 0000 0000 0000 0101
     kTaggedNumber = 0xd,     // 0000 0000 0000 1101
@@ -2693,6 +2695,10 @@ class HLoadExternalArrayPointer: public HUnaryOperation {
     return Representation::Tagged();
   }
 
+  virtual HType CalculateInferredType() {
+    return HType::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
 
  protected:
@@ -3478,6 +3484,7 @@ class HConstant: public HTemplateInstruction<0> {
             bool is_not_in_new_space,
             bool is_cell,
             bool boolean_value);
+  explicit HConstant(ExternalReference reference);
 
   Handle<Object> handle() {
     if (handle_.is_null()) {
@@ -3542,6 +3549,7 @@ class HConstant: public HTemplateInstruction<0> {
     if (HasSmiValue() && kSmiValueSize == 31) return Representation::Smi();
     if (HasInteger32Value()) return Representation::Integer32();
     if (HasNumberValue()) return Representation::Double();
+    if (HasExternalReferenceValue()) return Representation::External();
     return Representation::Tagged();
   }
 
@@ -3593,6 +3601,13 @@ class HConstant: public HTemplateInstruction<0> {
     return HasStringValue() && is_internalized_string_;
   }
 
+  bool HasExternalReferenceValue() const {
+    return has_external_reference_value_;
+  }
+  ExternalReference ExternalReferenceValue() const {
+    return external_reference_value_;
+  }
+
   bool BooleanValue() const { return boolean_value_; }
 
   virtual intptr_t Hashcode() {
@@ -3600,6 +3615,8 @@ class HConstant: public HTemplateInstruction<0> {
       return static_cast<intptr_t>(int32_value_);
     } else if (has_double_value_) {
       return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
+    } else if (has_external_reference_value_) {
+      return reinterpret_cast<intptr_t>(external_reference_value_.address());
     } else {
       ASSERT(!handle_.is_null());
       return unique_id_.Hashcode();
@@ -3607,14 +3624,15 @@ class HConstant: public HTemplateInstruction<0> {
   }
 
   virtual void FinalizeUniqueValueId() {
-    if (!has_double_value_) {
+    if (!has_double_value_ && !has_external_reference_value_) {
       ASSERT(!handle_.is_null());
       unique_id_ = UniqueValueId(handle_);
     }
   }
 
   bool UniqueValueIdsMatch(UniqueValueId other) {
-    return !has_double_value_ && unique_id_ == other;
+    return !has_double_value_ && !has_external_reference_value_ &&
+        unique_id_ == other;
   }
 
 #ifdef DEBUG
@@ -3635,6 +3653,10 @@ class HConstant: public HTemplateInstruction<0> {
       return other_constant->has_double_value_ &&
           BitCast<int64_t>(double_value_) ==
           BitCast<int64_t>(other_constant->double_value_);
+    } else if (has_external_reference_value_) {
+      return other_constant->has_external_reference_value_ &&
+          external_reference_value_ ==
+          other_constant->external_reference_value_;
     } else {
       ASSERT(!handle_.is_null());
       return !other_constant->handle_.is_null() &&
@@ -3662,12 +3684,14 @@ class HConstant: public HTemplateInstruction<0> {
   bool has_smi_value_ : 1;
   bool has_int32_value_ : 1;
   bool has_double_value_ : 1;
+  bool has_external_reference_value_ : 1;
   bool is_internalized_string_ : 1;  // TODO(yangguo): make this part of HType.
   bool is_not_in_new_space_ : 1;
   bool is_cell_ : 1;
   bool boolean_value_ : 1;
   int32_t int32_value_;
   double double_value_;
+  ExternalReference external_reference_value_;
 };
 
 
@@ -5564,7 +5588,11 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
 class HObjectAccess {
  public:
   inline bool IsInobject() const {
-    return portion() != kBackingStore;
+    return portion() != kBackingStore && portion() != kExternalMemory;
+  }
+
+  inline bool IsExternalMemory() const {
+    return portion() == kExternalMemory;
   }
 
   inline int offset() const {
@@ -5640,6 +5668,10 @@ class HObjectAccess {
     return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
   }
 
+  static HObjectAccess ForCounter() {
+    return HObjectAccess(kExternalMemory, 0, Representation::Integer32());
+  }
+
   // Create an access to an offset in a fixed array header.
   static HObjectAccess ForFixedArrayHeader(int offset);
 
@@ -5678,7 +5710,8 @@ class HObjectAccess {
     kElementsPointer,  // elements pointer
     kBackingStore,     // some field in the backing store
     kDouble,           // some double field
-    kInobject          // some other in-object field
+    kInobject,         // some other in-object field
+    kExternalMemory    // some field in external memory
   };
 
   HObjectAccess(Portion portion, int offset,
@@ -5756,7 +5789,9 @@ class HLoadNamedField: public HTemplateInstruction<2> {
     if (representation.IsSmi()) {
       set_type(HType::Smi());
       set_representation(representation);
-    } else if (representation.IsDouble()) {
+    } else if (representation.IsDouble() ||
+               representation.IsExternal() ||
+               representation.IsInteger32()) {
       set_representation(representation);
     } else if (FLAG_track_heap_object_fields &&
                representation.IsHeapObject()) {
@@ -5782,6 +5817,10 @@ class HLoadNamedField: public HTemplateInstruction<2> {
 
   virtual bool HasEscapingOperandAt(int index) { return false; }
   virtual Representation RequiredInputRepresentation(int index) {
+    if (index == 0 && access().IsExternalMemory()) {
+      // object must be external in case of external memory access
+      return Representation::External();
+    }
     return Representation::Tagged();
   }
   virtual void PrintDataTo(StringStream* stream);
@@ -5955,7 +5994,7 @@ class HLoadKeyed
         set_representation(Representation::Integer32());
       }
 
-      SetGVNFlag(kDependsOnSpecializedArrayElements);
+      SetGVNFlag(kDependsOnExternalMemory);
       // Native code could change the specialized array.
       SetGVNFlag(kDependsOnCalls);
     }
@@ -6112,9 +6151,13 @@ class HStoreNamedField: public HTemplateInstruction<2> {
 
   virtual bool HasEscapingOperandAt(int index) { return index == 1; }
   virtual Representation RequiredInputRepresentation(int index) {
-    if (index == 1 && field_representation().IsDouble()) {
-      return field_representation();
-    } else if (index == 1 && field_representation().IsSmi()) {
+    if (index == 0 && access().IsExternalMemory()) {
+      // object must be external in case of external memory access
+      return Representation::External();
+    } else if (index == 1 &&
+        (field_representation().IsDouble() ||
+         field_representation().IsSmi() ||
+         field_representation().IsInteger32())) {
       return field_representation();
     }
     return Representation::Tagged();
@@ -6152,6 +6195,7 @@ class HStoreNamedField: public HTemplateInstruction<2> {
     if (IsSkipWriteBarrier()) return false;
     if (field_representation().IsDouble()) return false;
     if (field_representation().IsSmi()) return false;
+    if (field_representation().IsInteger32()) return false;
     return StoringValueNeedsWriteBarrier(value()) &&
         ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
   }
@@ -6232,7 +6276,7 @@ class HStoreKeyed
       SetGVNFlag(kDependsOnNewSpacePromotion);
     }
     if (is_external()) {
-      SetGVNFlag(kChangesSpecializedArrayElements);
+      SetGVNFlag(kChangesExternalMemory);
       SetFlag(kAllowUndefinedAsNaN);
     } else if (IsFastDoubleElementsKind(elements_kind)) {
       SetGVNFlag(kChangesDoubleArrayElements);
index 4084ea6..d98ce2f 100644 (file)
@@ -986,6 +986,19 @@ HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
 }
 
 
+void HGraphBuilder::AddIncrementCounter(StatsCounter* counter,
+                                        HValue* context) {
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    HValue* reference = Add<HConstant>(ExternalReference(counter));
+    HValue* old_value = AddLoad(reference, HObjectAccess::ForCounter(), NULL);
+    HValue* new_value = AddInstruction(
+        HAdd::New(zone(), context, old_value, graph()->GetConstant1()));
+    new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
+    AddStore(reference, HObjectAccess::ForCounter(), new_value);
+  }
+}
+
+
 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
   HBasicBlock* b = graph()->CreateBasicBlock();
   b->SetInitialEnvironment(env);
index 895b984..498630b 100644 (file)
@@ -1133,6 +1133,9 @@ class HGraphBuilder {
 
   void FinishExitWithHardDeoptimization(HBasicBlock* continuation);
 
+  void AddIncrementCounter(StatsCounter* counter,
+                           HValue* context);
+
   class IfBuilder {
    public:
     explicit IfBuilder(HGraphBuilder* builder,
index 4ce7fd6..3ddad06 100644 (file)
@@ -685,6 +685,13 @@ double LCodeGen::ToDouble(LConstantOperand* op) const {
 }
 
 
+ExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const {
+  HConstant* constant = chunk_->LookupConstant(op);
+  ASSERT(constant->HasExternalReferenceValue());
+  return constant->ExternalReferenceValue();
+}
+
+
 bool LCodeGen::IsInteger32(LConstantOperand* op) const {
   return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
 }
@@ -1853,6 +1860,11 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
 }
 
 
+void LCodeGen::DoConstantE(LConstantE* instr) {
+  __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value()));
+}
+
+
 void LCodeGen::DoConstantT(LConstantT* instr) {
   Register reg = ToRegister(instr->result());
   Handle<Object> handle = instr->value();
@@ -3049,6 +3061,19 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
   HObjectAccess access = instr->hydrogen()->access();
   int offset = access.offset();
+
+  if (access.IsExternalMemory()) {
+    Register result = ToRegister(instr->result());
+    if (instr->object()->IsConstantOperand()) {
+      ExternalReference external_reference = ToExternalReference(
+          LConstantOperand::cast(instr->object()));
+      __ mov(result, MemOperand::StaticVariable(external_reference));
+    } else {
+      __ mov(result, MemOperand(ToRegister(instr->object()), offset));
+    }
+    return;
+  }
+
   Register object = ToRegister(instr->object());
   if (FLAG_track_double_fields &&
       instr->hydrogen()->representation().IsDouble()) {
@@ -4328,10 +4353,25 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   Representation representation = instr->representation();
 
-  Register object = ToRegister(instr->object());
   HObjectAccess access = instr->hydrogen()->access();
   int offset = access.offset();
 
+  if (access.IsExternalMemory()) {
+    MemOperand operand = instr->object()->IsConstantOperand()
+        ? MemOperand::StaticVariable(
+            ToExternalReference(LConstantOperand::cast(instr->object())))
+        : MemOperand(ToRegister(instr->object()), offset);
+    if (instr->value()->IsConstantOperand()) {
+      LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
+      __ mov(operand, Immediate(ToInteger32(operand_value)));
+    } else {
+      Register value = ToRegister(instr->value());
+      __ mov(operand, value);
+    }
+    return;
+  }
+
+  Register object = ToRegister(instr->object());
   Handle<Map> transition = instr->transition();
 
   if (FLAG_track_fields && representation.IsSmi()) {
@@ -4396,8 +4436,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   Register write_register = object;
   if (!access.IsInobject()) {
     write_register = ToRegister(instr->temp());
-    __ mov(write_register,
-           FieldOperand(object, JSObject::kPropertiesOffset));
+    __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
   }
 
   if (instr->value()->IsConstantOperand()) {
index 6574532..27295da 100644 (file)
@@ -297,6 +297,7 @@ class LCodeGen BASE_EMBEDDED {
   X87Register ToX87Register(int index) const;
   int ToRepresentation(LConstantOperand* op, const Representation& r) const;
   int32_t ToInteger32(LConstantOperand* op) const;
+  ExternalReference ToExternalReference(LConstantOperand* op) const;
 
   Operand BuildFastArrayOperand(LOperand* elements_pointer,
                                 LOperand* key,
index 875f608..8c8103f 100644 (file)
@@ -2146,6 +2146,8 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
     bool value_is_zero = BitCast<uint64_t, double>(value) == 0;
     LOperand* temp = value_is_zero ? NULL : TempRegister();
     return DefineAsRegister(new(zone()) LConstantD(temp));
+  } else if (r.IsExternal()) {
+    return DefineAsRegister(new(zone()) LConstantE);
   } else if (r.IsTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
@@ -2222,7 +2224,10 @@ LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
 
 
 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
-  LOperand* obj = UseRegisterAtStart(instr->object());
+  LOperand* obj = (instr->access().IsExternalMemory() &&
+                   instr->access().offset() == 0)
+      ? UseRegisterOrConstantAtStart(instr->object())
+      : UseRegisterAtStart(instr->object());
   return DefineAsRegister(new(zone()) LLoadNamedField(obj));
 }
 
@@ -2436,6 +2441,8 @@ LInstruction* LChunkBuilder::DoTrapAllocationMemento(
 
 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
   bool is_in_object = instr->access().IsInobject();
+  bool is_external_location = instr->access().IsExternalMemory() &&
+      instr->access().offset() == 0;
   bool needs_write_barrier = instr->NeedsWriteBarrier();
   bool needs_write_barrier_for_map = !instr->transition().is_null() &&
       instr->NeedsWriteBarrierForMap();
@@ -2445,6 +2452,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
     obj = is_in_object
         ? UseRegister(instr->object())
         : UseTempRegister(instr->object());
+  } else if (is_external_location) {
+    ASSERT(!is_in_object);
+    ASSERT(!needs_write_barrier);
+    ASSERT(!needs_write_barrier_for_map);
+    obj = UseRegisterOrConstant(instr->object());
   } else {
     obj = needs_write_barrier_for_map
         ? UseRegister(instr->object())
index 5acf29c..6a2aa00 100644 (file)
@@ -80,6 +80,7 @@ class LCodeGen;
   V(CmpMapAndBranch)                            \
   V(CmpT)                                       \
   V(ConstantD)                                  \
+  V(ConstantE)                                  \
   V(ConstantI)                                  \
   V(ConstantS)                                  \
   V(ConstantT)                                  \
@@ -1208,6 +1209,17 @@ class LConstantD: public LTemplateInstruction<1, 0, 1> {
 };
 
 
+class LConstantE: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  ExternalReference value() const {
+    return hydrogen()->ExternalReferenceValue();
+  }
+};
+
+
 class LConstantT: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
index 6bd45fe..8db5f00 100644 (file)
@@ -1658,6 +1658,11 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
 }
 
 
+void LCodeGen::DoConstantE(LConstantE* instr) {
+  __ li(ToRegister(instr->result()), Operand(instr->value()));
+}
+
+
 void LCodeGen::DoConstantT(LConstantT* instr) {
   Handle<Object> value = instr->value();
   AllowDeferredHandleDereference smi_check;
@@ -2878,6 +2883,13 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
   HObjectAccess access = instr->hydrogen()->access();
   int offset = access.offset();
   Register object = ToRegister(instr->object());
+
+  if (access.IsExternalMemory()) {
+    Register result = ToRegister(instr->result());
+    __ lw(result, MemOperand(object, offset));
+    return;
+  }
+
   if (instr->hydrogen()->representation().IsDouble()) {
     DoubleRegister result = ToDoubleRegister(instr->result());
     __ ldc1(result, FieldMemOperand(object, offset));
@@ -4115,6 +4127,12 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   HObjectAccess access = instr->hydrogen()->access();
   int offset = access.offset();
 
+  if (access.IsExternalMemory()) {
+    Register value = ToRegister(instr->value());
+    __ sw(value, MemOperand(object, offset));
+    return;
+  }
+
   Handle<Map> transition = instr->transition();
 
   if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
index fd3fd3a..5cfca00 100644 (file)
@@ -2017,6 +2017,8 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
     return DefineAsRegister(new(zone()) LConstantI);
   } else if (r.IsDouble()) {
     return DefineAsRegister(new(zone()) LConstantD);
+  } else if (r.IsExternal()) {
+    return DefineAsRegister(new(zone()) LConstantE);
   } else if (r.IsTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
index ee1c47d..2618c46 100644 (file)
@@ -79,6 +79,7 @@ class LCodeGen;
   V(CmpMapAndBranch)                            \
   V(CmpT)                                       \
   V(ConstantD)                                  \
+  V(ConstantE)                                  \
   V(ConstantI)                                  \
   V(ConstantS)                                  \
   V(ConstantT)                                  \
@@ -1210,6 +1211,17 @@ class LConstantD: public LTemplateInstruction<1, 0, 0> {
 };
 
 
+class LConstantE: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  ExternalReference value() const {
+    return hydrogen()->ExternalReferenceValue();
+  }
+};
+
+
 class LConstantT: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
index 7f0ed3d..e9210a9 100644 (file)
@@ -429,6 +429,13 @@ double LCodeGen::ToDouble(LConstantOperand* op) const {
 }
 
 
+ExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const {
+  HConstant* constant = chunk_->LookupConstant(op);
+  ASSERT(constant->HasExternalReferenceValue());
+  return constant->ExternalReferenceValue();
+}
+
+
 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
   ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
@@ -1523,6 +1530,11 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
 }
 
 
+void LCodeGen::DoConstantE(LConstantE* instr) {
+  __ LoadAddress(ToRegister(instr->result()), instr->value());
+}
+
+
 void LCodeGen::DoConstantT(LConstantT* instr) {
   Handle<Object> value = instr->value();
   AllowDeferredHandleDereference smi_check;
@@ -2689,6 +2701,19 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
   HObjectAccess access = instr->hydrogen()->access();
   int offset = access.offset();
+
+  if (access.IsExternalMemory()) {
+    Register result = ToRegister(instr->result());
+    if (instr->object()->IsConstantOperand()) {
+      ASSERT(result.is(rax));
+      __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object())));
+    } else {
+      Register object = ToRegister(instr->object());
+      __ movq(result, MemOperand(object, offset));
+    }
+    return;
+  }
+
   Register object = ToRegister(instr->object());
   if (FLAG_track_double_fields &&
       instr->hydrogen()->representation().IsDouble()) {
@@ -3926,11 +3951,23 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   Representation representation = instr->representation();
 
-  Register object = ToRegister(instr->object());
-
   HObjectAccess access = instr->hydrogen()->access();
   int offset = access.offset();
 
+  if (access.IsExternalMemory()) {
+    Register value = ToRegister(instr->value());
+    if (instr->object()->IsConstantOperand()) {
+      ASSERT(value.is(rax));
+      LConstantOperand* object = LConstantOperand::cast(instr->object());
+      __ store_rax(ToExternalReference(object));
+    } else {
+      Register object = ToRegister(instr->object());
+      __ movq(MemOperand(object, offset), value);
+    }
+    return;
+  }
+
+  Register object = ToRegister(instr->object());
   Handle<Map> transition = instr->transition();
 
   if (FLAG_track_fields && representation.IsSmi()) {
index 5ad1c40..4eab56c 100644 (file)
@@ -106,6 +106,7 @@ class LCodeGen BASE_EMBEDDED {
   int32_t ToInteger32(LConstantOperand* op) const;
   Smi* ToSmi(LConstantOperand* op) const;
   double ToDouble(LConstantOperand* op) const;
+  ExternalReference ToExternalReference(LConstantOperand* op) const;
   bool IsTaggedConstant(LConstantOperand* op) const;
   Handle<Object> ToHandle(LConstantOperand* op) const;
   Operand ToOperand(LOperand* op) const;
index 9c6efed..4153417 100644 (file)
@@ -1997,6 +1997,8 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
   } else if (r.IsDouble()) {
     LOperand* temp = TempRegister();
     return DefineAsRegister(new(zone()) LConstantD(temp));
+  } else if (r.IsExternal()) {
+    return DefineAsRegister(new(zone()) LConstantE);
   } else if (r.IsTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
@@ -2074,6 +2076,10 @@ LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
 
 
 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
+  if (instr->access().IsExternalMemory() && instr->access().offset() == 0) {
+    LOperand* obj = UseRegisterOrConstantAtStart(instr->object());
+    return DefineFixed(new(zone()) LLoadNamedField(obj), rax);
+  }
   LOperand* obj = UseRegisterAtStart(instr->object());
   return DefineAsRegister(new(zone()) LLoadNamedField(obj));
 }
@@ -2249,6 +2255,8 @@ LInstruction* LChunkBuilder::DoTrapAllocationMemento(
 
 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
   bool is_in_object = instr->access().IsInobject();
+  bool is_external_location = instr->access().IsExternalMemory() &&
+      instr->access().offset() == 0;
   bool needs_write_barrier = instr->NeedsWriteBarrier();
   bool needs_write_barrier_for_map = !instr->transition().is_null() &&
       instr->NeedsWriteBarrierForMap();
@@ -2258,6 +2266,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
     obj = is_in_object
         ? UseRegister(instr->object())
         : UseTempRegister(instr->object());
+  } else if (is_external_location) {
+    ASSERT(!is_in_object);
+    ASSERT(!needs_write_barrier);
+    ASSERT(!needs_write_barrier_for_map);
+    obj = UseRegisterOrConstant(instr->object());
   } else {
     obj = needs_write_barrier_for_map
         ? UseRegister(instr->object())
@@ -2271,6 +2284,8 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
   LOperand* val;
   if (needs_write_barrier) {
     val = UseTempRegister(instr->value());
+  } else if (is_external_location) {
+    val = UseFixed(instr->value(), rax);
   } else if (can_be_constant) {
     val = UseRegisterOrConstant(instr->value());
   } else if (FLAG_track_fields && instr->field_representation().IsSmi()) {
index ee3bc41..cb3a2b0 100644 (file)
@@ -79,6 +79,7 @@ class LCodeGen;
   V(CmpMapAndBranch)                            \
   V(CmpT)                                       \
   V(ConstantD)                                  \
+  V(ConstantE)                                  \
   V(ConstantI)                                  \
   V(ConstantS)                                  \
   V(ConstantT)                                  \
@@ -1166,6 +1167,17 @@ class LConstantD: public LTemplateInstruction<1, 0, 1> {
 };
 
 
+class LConstantE: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  ExternalReference value() const {
+    return hydrogen()->ExternalReferenceValue();
+  }
+};
+
+
 class LConstantT: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")