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 {
V(CmpMapAndBranch) \
V(CmpT) \
V(ConstantD) \
+ V(ConstantE) \
V(ConstantI) \
V(ConstantS) \
V(ConstantT) \
};
+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")
}
+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;
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));
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()) {
typedef void* ExternalReferenceRedirector(void* original, Type type);
+ ExternalReference() : address_(NULL) {}
+
ExternalReference(Builtins::CFunctionId id, Isolate* isolate);
ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate);
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()
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) {}
// 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";
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),
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);
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);
}
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) {
r = Representation::Integer32();
} else if (has_double_value_) {
r = Representation::Double();
+ } else if (has_external_reference_value_) {
+ r = Representation::External();
} else {
r = Representation::Tagged();
}
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_,
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);
}
instr->SetGVNFlag(is_store
? kChangesMaps : kDependsOnMaps);
break;
+ case kExternalMemory:
+ instr->SetGVNFlag(is_store
+ ? kChangesExternalMemory : kDependsOnExternalMemory);
+ break;
}
}
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());
V(GlobalVars) \
V(InobjectFields) \
V(OsrEntries) \
- V(SpecializedArrayElements)
+ V(ExternalMemory)
#define DECLARE_ABSTRACT_INSTRUCTION(type) \
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); }
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
return Representation::Tagged();
}
+ virtual HType CalculateInferredType() {
+ return HType::None();
+ }
+
DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
protected:
bool is_not_in_new_space,
bool is_cell,
bool boolean_value);
+ explicit HConstant(ExternalReference reference);
Handle<Object> handle() {
if (handle_.is_null()) {
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();
}
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() {
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();
}
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
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() &&
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_;
};
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 {
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);
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,
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()) {
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);
set_representation(Representation::Integer32());
}
- SetGVNFlag(kDependsOnSpecializedArrayElements);
+ SetGVNFlag(kDependsOnExternalMemory);
// Native code could change the specialized array.
SetGVNFlag(kDependsOnCalls);
}
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();
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());
}
SetGVNFlag(kDependsOnNewSpacePromotion);
}
if (is_external()) {
- SetGVNFlag(kChangesSpecializedArrayElements);
+ SetGVNFlag(kChangesExternalMemory);
SetFlag(kAllowUndefinedAsNaN);
} else if (IsFastDoubleElementsKind(elements_kind)) {
SetGVNFlag(kChangesDoubleArrayElements);
}
+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);
void FinishExitWithHardDeoptimization(HBasicBlock* continuation);
+ void AddIncrementCounter(StatsCounter* counter,
+ HValue* context);
+
class IfBuilder {
public:
explicit IfBuilder(HGraphBuilder* builder,
}
+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();
}
}
+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();
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()) {
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()) {
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()) {
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,
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 {
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));
}
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();
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())
V(CmpMapAndBranch) \
V(CmpT) \
V(ConstantD) \
+ V(ConstantE) \
V(ConstantI) \
V(ConstantS) \
V(ConstantT) \
};
+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")
}
+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;
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));
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()) {
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 {
V(CmpMapAndBranch) \
V(CmpT) \
V(ConstantD) \
+ V(ConstantE) \
V(ConstantI) \
V(ConstantS) \
V(ConstantT) \
};
+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")
}
+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());
}
+void LCodeGen::DoConstantE(LConstantE* instr) {
+ __ LoadAddress(ToRegister(instr->result()), instr->value());
+}
+
+
void LCodeGen::DoConstantT(LConstantT* instr) {
Handle<Object> value = instr->value();
AllowDeferredHandleDereference smi_check;
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()) {
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()) {
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;
} 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 {
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));
}
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();
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())
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()) {
V(CmpMapAndBranch) \
V(CmpT) \
V(ConstantD) \
+ V(ConstantE) \
V(ConstantI) \
V(ConstantS) \
V(ConstantT) \
};
+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")