From b019910a38f725f445fa64d876bfddea99607e8b Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Mon, 29 Jul 2013 13:56:51 +0000 Subject: [PATCH] This adds generic support for ExternalReferences in Hydrogen (and Lithium), as required for AddIncrementCounter. 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 --- src/arm/lithium-arm.cc | 2 + src/arm/lithium-arm.h | 12 +++++ src/arm/lithium-codegen-arm.cc | 19 +++++++- src/assembler.h | 12 ++++- src/hydrogen-instructions.cc | 96 +++++++++++++++++++++++++++------------- src/hydrogen-instructions.h | 66 ++++++++++++++++++++++----- src/hydrogen.cc | 13 ++++++ src/hydrogen.h | 3 ++ src/ia32/lithium-codegen-ia32.cc | 45 +++++++++++++++++-- src/ia32/lithium-codegen-ia32.h | 1 + src/ia32/lithium-ia32.cc | 14 +++++- src/ia32/lithium-ia32.h | 12 +++++ src/mips/lithium-codegen-mips.cc | 18 ++++++++ src/mips/lithium-mips.cc | 2 + src/mips/lithium-mips.h | 12 +++++ src/x64/lithium-codegen-x64.cc | 41 ++++++++++++++++- src/x64/lithium-codegen-x64.h | 1 + src/x64/lithium-x64.cc | 15 +++++++ src/x64/lithium-x64.h | 12 +++++ 19 files changed, 347 insertions(+), 49 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index f54e84b..b55679e 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -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 { diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index 241bba9..eecacec 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -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") diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 057ca1e..929d04d 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -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 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 transition = instr->transition(); if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { diff --git a/src/assembler.h b/src/assembler.h index 481add5..d70d5aa 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -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() const { return reinterpret_cast
(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) {} diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 3eca181..743bb09 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -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 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 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 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 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( + 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()); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 1015b6e..e71b7cd 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -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 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(int32_value_); } else if (has_double_value_) { return static_cast(BitCast(double_value_)); + } else if (has_external_reference_value_) { + return reinterpret_cast(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(double_value_) == BitCast(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); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 4084ea6..d98ce2f 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -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(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); diff --git a/src/hydrogen.h b/src/hydrogen.h index 895b984..498630b 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -1133,6 +1133,9 @@ class HGraphBuilder { void FinishExitWithHardDeoptimization(HBasicBlock* continuation); + void AddIncrementCounter(StatsCounter* counter, + HValue* context); + class IfBuilder { public: explicit IfBuilder(HGraphBuilder* builder, diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 4ce7fd6..3ddad06 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -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 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 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()) { diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h index 6574532..27295da 100644 --- a/src/ia32/lithium-codegen-ia32.h +++ b/src/ia32/lithium-codegen-ia32.h @@ -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, diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 875f608..8c8103f 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -2146,6 +2146,8 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { bool value_is_zero = BitCast(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()) diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index 5acf29c..6a2aa00 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -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") diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 6bd45fe..8db5f00 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -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 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 transition = instr->transition(); if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index fd3fd3a..5cfca00 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -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 { diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h index ee1c47d..2618c46 100644 --- a/src/mips/lithium-mips.h +++ b/src/mips/lithium-mips.h @@ -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") diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 7f0ed3d..e9210a9 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -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 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 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 transition = instr->transition(); if (FLAG_track_fields && representation.IsSmi()) { diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h index 5ad1c40..4eab56c 100644 --- a/src/x64/lithium-codegen-x64.h +++ b/src/x64/lithium-codegen-x64.h @@ -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 ToHandle(LConstantOperand* op) const; Operand ToOperand(LOperand* op) const; diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 9c6efed..4153417 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -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()) { diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index ee3bc41..cb3a2b0 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -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") -- 2.7.4