Commit 94b4240f authored by titzer@chromium.org's avatar titzer@chromium.org

Introduce ObjectAccess, which is used by LoadNamedField and StoreNamedField to...

Introduce ObjectAccess, which is used by LoadNamedField and StoreNamedField to denote what parts of an object are referred to by a given load or store. Refactor HGraphBuilder to use ObjectAccess, which removes the need to manually set GVN flags and simplifies the code as well.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14791 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1d393554
......@@ -369,8 +369,7 @@ void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
void LStoreNamedField::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
stream->Add(".");
stream->Add(*String::cast(*name())->ToCString());
hydrogen()->access().PrintTo(stream);
stream->Add(" <- ");
value()->PrintTo(stream);
}
......
......@@ -358,7 +358,6 @@ Handle<Code> FastCloneShallowArrayStub::GenerateCode() {
template <>
HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
Zone* zone = this->zone();
Factory* factory = isolate()->factory();
HValue* undefined = graph()->GetConstantUndefined();
HInstruction* boilerplate =
......@@ -387,20 +386,13 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
flags = static_cast<HAllocate::Flags>(
flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
}
HInstruction* object =
AddInstruction(new(zone) HAllocate(context(),
size_in_bytes,
HType::JSObject(),
flags));
HInstruction* object = AddInstruction(new(zone)
HAllocate(context(), size_in_bytes, HType::JSObject(), flags));
for (int i = 0; i < size; i += kPointerSize) {
HInstruction* value =
AddInstruction(new(zone) HLoadNamedField(
boilerplate, true, Representation::Tagged(), i));
AddInstruction(new(zone) HStoreNamedField(object,
factory->empty_string(),
value, true,
Representation::Tagged(), i));
HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
AddStore(object, access, AddLoad(boilerplate, access));
}
checker.ElseDeopt();
......@@ -430,11 +422,11 @@ Handle<Code> KeyedLoadFastElementStub::GenerateCode() {
template<>
HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
Representation representation = casted_stub()->representation();
HInstruction* load = AddInstruction(DoBuildLoadNamedField(
GetParameter(0), casted_stub()->is_inobject(),
representation, casted_stub()->offset()));
return load;
HObjectAccess access = casted_stub()->is_inobject() ?
HObjectAccess::ForJSObjectOffset(casted_stub()->offset()) :
HObjectAccess::ForBackingStoreOffset(casted_stub()->offset());
return AddInstruction(BuildLoadNamedField(GetParameter(0), access,
casted_stub()->representation()));
}
......@@ -445,11 +437,11 @@ Handle<Code> LoadFieldStub::GenerateCode() {
template<>
HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() {
Representation representation = casted_stub()->representation();
HInstruction* load = AddInstruction(DoBuildLoadNamedField(
GetParameter(0), casted_stub()->is_inobject(),
representation, casted_stub()->offset()));
return load;
HObjectAccess access = casted_stub()->is_inobject() ?
HObjectAccess::ForJSObjectOffset(casted_stub()->offset()) :
HObjectAccess::ForBackingStoreOffset(casted_stub()->offset());
return AddInstruction(BuildLoadNamedField(GetParameter(0), access,
casted_stub()->representation()));
}
......@@ -487,8 +479,8 @@ HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
AddInstruction(new(zone) HTrapAllocationMemento(js_array));
HInstruction* array_length =
AddInstruction(HLoadNamedField::NewArrayLength(
zone, js_array, js_array, HType::Smi()));
AddLoad(js_array, HObjectAccess::ForArrayLength());
array_length->set_type(HType::Smi());
ElementsKind to_kind = casted_stub()->to_kind();
BuildNewSpaceArrayCheck(array_length, to_kind);
......@@ -514,20 +506,12 @@ HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
casted_stub()->from_kind(), new_elements,
to_kind, array_length, elements_length);
Factory* factory = isolate()->factory();
AddInstruction(new(zone) HStoreNamedField(js_array,
factory->elements_field_string(),
new_elements, true,
Representation::Tagged(),
JSArray::kElementsOffset));
AddStore(js_array, HObjectAccess::ForElementsPointer(), new_elements);
if_builder.End();
AddInstruction(new(zone) HStoreNamedField(js_array, factory->length_string(),
map, true,
Representation::Tagged(),
JSArray::kMapOffset));
AddStore(js_array, HObjectAccess::ForMap(), map);
return js_array;
}
......
......@@ -2483,7 +2483,7 @@ void HParameter::PrintDataTo(StringStream* stream) {
void HLoadNamedField::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
access_.PrintTo(stream);
if (HasTypeCheck()) {
stream->Add(" ");
typecheck()->PrintNameTo(stream);
......@@ -2805,11 +2805,9 @@ void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
void HStoreNamedField::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add(".");
stream->Add(*String::cast(*name())->ToCString());
access_.PrintTo(stream);
stream->Add(" = ");
value()->PrintNameTo(stream);
stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
if (NeedsWriteBarrier()) {
stream->Add(" (write-barrier)");
}
......@@ -3669,4 +3667,141 @@ void HCheckFunction::Verify() {
#endif
HObjectAccess HObjectAccess::ForFixedArrayHeader(int offset) {
ASSERT(offset >= 0);
ASSERT(offset < FixedArray::kHeaderSize);
if (offset == FixedArray::kLengthOffset) return ForFixedArrayLength();
return HObjectAccess(kInobject, offset);
}
HObjectAccess HObjectAccess::ForJSObjectOffset(int offset) {
ASSERT(offset >= 0);
Portion portion = kInobject;
if (offset == JSObject::kElementsOffset) {
portion = kElementsPointer;
} else if (offset == JSObject::kMapOffset) {
portion = kMaps;
}
return HObjectAccess(portion, offset, Handle<String>::null());
}
HObjectAccess HObjectAccess::ForJSArrayOffset(int offset) {
ASSERT(offset >= 0);
Portion portion = kInobject;
if (offset == JSObject::kElementsOffset) {
portion = kElementsPointer;
} else if (offset == JSArray::kLengthOffset) {
portion = kArrayLengths;
} else if (offset == JSObject::kMapOffset) {
portion = kMaps;
}
return HObjectAccess(portion, offset, Handle<String>::null());
}
HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset) {
ASSERT(offset >= 0);
return HObjectAccess(kBackingStore, offset, Handle<String>::null());
}
HObjectAccess HObjectAccess::ForField(Handle<Map> map,
LookupResult *lookup, Handle<String> name) {
ASSERT(lookup->IsField() || lookup->IsTransitionToField(*map));
int index;
if (lookup->IsField()) {
index = lookup->GetLocalFieldIndexFromMap(*map);
} else {
Map* transition = lookup->GetTransitionMapFromMap(*map);
int descriptor = transition->LastAdded();
index = transition->instance_descriptors()->GetFieldIndex(descriptor) -
map->inobject_properties();
}
if (index < 0) {
// Negative property indices are in-object properties, indexed
// from the end of the fixed part of the object.
int offset = (index * kPointerSize) + map->instance_size();
return HObjectAccess(kInobject, offset);
} else {
// Non-negative property indices are in the properties array.
int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
return HObjectAccess(kBackingStore, offset, name);
}
}
void HObjectAccess::SetGVNFlags(HValue *instr, bool is_store) {
// set the appropriate GVN flags for a given load or store instruction
if (is_store) {
// track dominating allocations in order to eliminate write barriers
instr->SetGVNFlag(kDependsOnNewSpacePromotion);
instr->SetFlag(HValue::kTrackSideEffectDominators);
instr->SetFlag(HValue::kDeoptimizeOnUndefined);
} else {
// try to GVN loads, but don't hoist above map changes
instr->SetFlag(HValue::kUseGVN);
instr->SetGVNFlag(kDependsOnMaps);
}
switch (portion()) {
case kArrayLengths:
instr->SetGVNFlag(is_store
? kChangesArrayLengths : kDependsOnArrayLengths);
break;
case kInobject:
instr->SetGVNFlag(is_store
? kChangesInobjectFields : kDependsOnInobjectFields);
break;
case kDouble:
instr->SetGVNFlag(is_store
? kChangesDoubleFields : kDependsOnDoubleFields);
break;
case kBackingStore:
instr->SetGVNFlag(is_store
? kChangesBackingStoreFields : kDependsOnBackingStoreFields);
break;
case kElementsPointer:
instr->SetGVNFlag(is_store
? kChangesElementsPointer : kDependsOnElementsPointer);
break;
case kMaps:
instr->SetGVNFlag(is_store
? kChangesMaps : kDependsOnMaps);
break;
}
}
void HObjectAccess::PrintTo(StringStream* stream) {
stream->Add(".");
switch (portion()) {
case kArrayLengths:
stream->Add("%length");
break;
case kElementsPointer:
stream->Add("%elements");
break;
case kMaps:
stream->Add("%map");
break;
case kDouble: // fall through
case kInobject:
if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString());
stream->Add("[in-object]");
break;
case kBackingStore:
if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString());
stream->Add("[backing-store]");
break;
}
stream->Add("@%d", offset());
}
} } // namespace v8::internal
......@@ -5201,14 +5201,114 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
};
// Represents an access to a portion of an object, such as the map pointer,
// array elements pointer, etc, but not accesses to array elements themselves.
class HObjectAccess {
public:
inline bool IsInobject() const {
return portion() != kBackingStore;
}
inline int offset() const {
return OffsetField::decode(value_);
}
inline Handle<String> name() const {
return name_;
}
static HObjectAccess ForHeapNumberValue() {
return HObjectAccess(kDouble, HeapNumber::kValueOffset);
}
static HObjectAccess ForElementsPointer() {
return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
}
static HObjectAccess ForArrayLength() {
return HObjectAccess(kArrayLengths, JSArray::kLengthOffset);
}
static HObjectAccess ForFixedArrayLength() {
return HObjectAccess(kArrayLengths, FixedArray::kLengthOffset);
}
static HObjectAccess ForPropertiesPointer() {
return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
}
static HObjectAccess ForMap() {
return HObjectAccess(kMaps, JSObject::kMapOffset);
}
static HObjectAccess ForAllocationSitePayload() {
return HObjectAccess(kInobject, AllocationSiteInfo::kPayloadOffset);
}
// Create an access to an offset in a fixed array header.
static HObjectAccess ForFixedArrayHeader(int offset);
// Create an access to an in-object property in a JSObject.
static HObjectAccess ForJSObjectOffset(int offset);
// Create an access to an in-object property in a JSArray.
static HObjectAccess ForJSArrayOffset(int offset);
// Create an access to the backing store of an object.
static HObjectAccess ForBackingStoreOffset(int offset);
// Create an access to a resolved field (in-object or backing store).
static HObjectAccess ForField(Handle<Map> map,
LookupResult *lookup, Handle<String> name = Handle<String>::null());
void PrintTo(StringStream* stream);
protected:
void SetGVNFlags(HValue *instr, bool is_store);
private:
// internal use only; different parts of an object or array
enum Portion {
kMaps, // map of an object
kArrayLengths, // the length of an array
kElementsPointer, // elements pointer
kBackingStore, // some field in the backing store
kDouble, // some double field
kInobject // some other in-object field
};
HObjectAccess(Portion portion, int offset,
Handle<String> name = Handle<String>::null())
: value_(PortionField::encode(portion) | OffsetField::encode(offset)),
name_(name) {
ASSERT(this->offset() == offset); // offset should decode correctly
ASSERT(this->portion() == portion); // portion should decode correctly
}
class PortionField : public BitField<Portion, 0, 3> {};
class OffsetField : public BitField<int, 3, 29> {};
uint32_t value_; // encodes both portion and offset
Handle<String> name_;
friend class HLoadNamedField;
friend class HStoreNamedField;
inline Portion portion() const {
return PortionField::decode(value_);
}
};
class HLoadNamedField: public HTemplateInstruction<2> {
public:
HLoadNamedField(HValue* object, bool is_in_object,
Representation field_representation,
int offset, HValue* typecheck = NULL)
: is_in_object_(is_in_object),
field_representation_(field_representation),
offset_(offset) {
HLoadNamedField(HValue* object,
HObjectAccess access,
HValue* typecheck = NULL,
Representation field_representation
= Representation::Tagged())
: access_(access),
field_representation_(field_representation) {
ASSERT(object != NULL);
SetOperandAt(0, object);
SetOperandAt(1, typecheck != NULL ? typecheck : object);
......@@ -5225,31 +5325,7 @@ class HLoadNamedField: public HTemplateInstruction<2> {
} else {
set_representation(Representation::Tagged());
}
SetFlag(kUseGVN);
if (FLAG_track_double_fields && representation().IsDouble()) {
ASSERT(is_in_object);
ASSERT(offset == HeapNumber::kValueOffset);
SetGVNFlag(kDependsOnDoubleFields);
} else if (is_in_object) {
SetGVNFlag(kDependsOnInobjectFields);
SetGVNFlag(kDependsOnMaps);
} else {
SetGVNFlag(kDependsOnBackingStoreFields);
SetGVNFlag(kDependsOnMaps);
}
}
static HLoadNamedField* NewArrayLength(Zone* zone, HValue* object,
HValue* typecheck,
HType type = HType::Tagged()) {
Representation representation =
type.IsSmi() ? Representation::Smi() : Representation::Tagged();
HLoadNamedField* result = new(zone) HLoadNamedField(
object, true, representation, JSArray::kLengthOffset, typecheck);
result->set_type(type);
result->SetGVNFlag(kDependsOnArrayLengths);
result->ClearGVNFlag(kDependsOnInobjectFields);
return result;
access.SetGVNFlags(this, false);
}
HValue* object() { return OperandAt(0); }
......@@ -5259,9 +5335,10 @@ class HLoadNamedField: public HTemplateInstruction<2> {
}
bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
bool is_in_object() const { return is_in_object_; }
HObjectAccess access() const { return access_; }
bool is_in_object() const { return access_.IsInobject(); }
Representation field_representation() const { return representation_; }
int offset() const { return offset_; }
int offset() const { return access_.offset(); }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::Tagged();
......@@ -5273,15 +5350,14 @@ class HLoadNamedField: public HTemplateInstruction<2> {
protected:
virtual bool DataEquals(HValue* other) {
HLoadNamedField* b = HLoadNamedField::cast(other);
return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
return is_in_object() == b->is_in_object() && offset() == b->offset();
}
private:
virtual bool IsDeletable() const { return true; }
bool is_in_object_;
HObjectAccess access_;
Representation field_representation_;
int offset_;
};
......@@ -5578,30 +5654,17 @@ class HLoadKeyedGeneric: public HTemplateInstruction<3> {
class HStoreNamedField: public HTemplateInstruction<2> {
public:
HStoreNamedField(HValue* obj,
Handle<Name> name,
HObjectAccess access,
HValue* val,
bool in_object,
Representation field_representation,
int offset)
: name_(name),
is_in_object_(in_object),
Representation field_representation
= Representation::Tagged())
: access_(access),
field_representation_(field_representation),
offset_(offset),
transition_unique_id_(),
new_space_dominator_(NULL) {
SetOperandAt(0, obj);
SetOperandAt(1, val);
SetFlag(kTrackSideEffectDominators);
if (FLAG_track_double_fields && field_representation.IsDouble()) {
SetGVNFlag(kChangesDoubleFields);
} else if (is_in_object_) {
SetGVNFlag(kChangesInobjectFields);
SetGVNFlag(kDependsOnNewSpacePromotion);
} else {
SetGVNFlag(kChangesBackingStoreFields);
SetGVNFlag(kDependsOnNewSpacePromotion);
}
SetFlag(kDeoptimizeOnUndefined);
access.SetGVNFlags(this, true);
}
DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
......@@ -5625,9 +5688,10 @@ class HStoreNamedField: public HTemplateInstruction<2> {
HValue* object() { return OperandAt(0); }
HValue* value() { return OperandAt(1); }
Handle<Name> name() const { return name_; }
bool is_in_object() const { return is_in_object_; }
int offset() const { return offset_; }
HObjectAccess access() const { return access_; }
Handle<String> name() const { return access_.name(); }
bool is_in_object() const { return access_.IsInobject(); }
int offset() const { return access_.offset(); }
Handle<Map> transition() const { return transition_; }
UniqueValueId transition_unique_id() const { return transition_unique_id_; }
void set_transition(Handle<Map> map) { transition_ = map; }
......@@ -5656,10 +5720,8 @@ class HStoreNamedField: public HTemplateInstruction<2> {
}
private:
Handle<Name> name_;
bool is_in_object_;
HObjectAccess access_;
Representation field_representation_;
int offset_;
Handle<Map> transition_;
UniqueValueId transition_unique_id_;
HValue* new_space_dominator_;
......
......@@ -1195,16 +1195,10 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
new_length->AssumeRepresentation(Representation::Integer32());
new_length->ClearFlag(HValue::kCanOverflow);
Factory* factory = isolate()->factory();
Representation representation = IsFastElementsKind(kind)
? Representation::Smi() : Representation::Tagged();
HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField(
object,
factory->length_field_string(),
new_length, true,
representation,
JSArray::kLengthOffset));
length_store->SetGVNFlag(kChangesArrayLengths);
AddStore(object, HObjectAccess::ForArrayLength(), new_length,
representation);
}
length_checker.Else();
......@@ -1286,8 +1280,9 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
}
HInstruction* length = NULL;
if (is_js_array) {
length = AddInstruction(
HLoadNamedField::NewArrayLength(zone, object, mapcheck, HType::Smi()));
length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck,
Representation::Smi());
length->set_type(HType::Smi());
} else {
length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
}
......@@ -1413,21 +1408,16 @@ HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
void HGraphBuilder::BuildInitializeElements(HValue* elements,
ElementsKind kind,
HValue* capacity) {
Zone* zone = this->zone();
Factory* factory = isolate()->factory();
Handle<Map> map = IsFastDoubleElementsKind(kind)
? factory->fixed_double_array_map()
: factory->fixed_array_map();
BuildStoreMap(elements, map);
Handle<String> fixed_array_length_field_name = factory->length_field_string();
AddStoreMapConstant(elements, map);
Representation representation = IsFastElementsKind(kind)
? Representation::Smi() : Representation::Tagged();
HInstruction* store_length =
new(zone) HStoreNamedField(elements, fixed_array_length_field_name,
capacity, true, representation,
FixedArray::kLengthOffset);
AddInstruction(store_length);
AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity,
representation);
}
......@@ -1446,7 +1436,7 @@ HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
HValue* allocation_site_payload,
HValue* length_field) {
BuildStoreMap(array, array_map);
AddStore(array, HObjectAccess::ForMap(), array_map);
HConstant* empty_fixed_array =
new(zone()) HConstant(
......@@ -1454,21 +1444,9 @@ HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
Representation::Tagged());
AddInstruction(empty_fixed_array);
AddInstruction(new(zone()) HStoreNamedField(array,
isolate()->factory()->properties_field_symbol(),
empty_fixed_array,
true,
Representation::Tagged(),
JSArray::kPropertiesOffset));
HInstruction* length_store = AddInstruction(
new(zone()) HStoreNamedField(array,
isolate()->factory()->length_field_string(),
length_field,
true,
Representation::Tagged(),
JSArray::kLengthOffset));
length_store->SetGVNFlag(kChangesArrayLengths);
HObjectAccess access = HObjectAccess::ForPropertiesPointer();
AddStore(array, access, empty_fixed_array);
AddStore(array, HObjectAccess::ForArrayLength(), length_field);
if (mode == TRACK_ALLOCATION_SITE) {
BuildCreateAllocationSiteInfo(array,
......@@ -1482,58 +1460,17 @@ HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
}
HInnerAllocatedObject* elements = new(zone()) HInnerAllocatedObject(
array,
elements_location);
array, elements_location);
AddInstruction(elements);
HInstruction* elements_store = AddInstruction(
new(zone()) HStoreNamedField(
array,
isolate()->factory()->elements_field_string(),
elements,
true,
Representation::Tagged(),
JSArray::kElementsOffset));
elements_store->SetGVNFlag(kChangesElementsPointer);
AddStore(array, HObjectAccess::ForElementsPointer(), elements);
return elements;
}
HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
HValue* map) {
Zone* zone = this->zone();
Factory* factory = isolate()->factory();
Handle<String> map_field_name = factory->map_field_string();
HInstruction* store_map =
new(zone) HStoreNamedField(object, map_field_name, map,
true, Representation::Tagged(),
JSObject::kMapOffset);
store_map->ClearGVNFlag(kChangesInobjectFields);
store_map->SetGVNFlag(kChangesMaps);
AddInstruction(store_map);
return store_map;
}
HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
Handle<Map> map) {
Zone* zone = this->zone();
HValue* map_constant =
AddInstruction(new(zone) HConstant(map, Representation::Tagged()));
return BuildStoreMap(object, map_constant);
}
HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
HValue* typecheck) {
HLoadNamedField* instr = new(zone()) HLoadNamedField(object, true,
Representation::Tagged(), JSObject::kElementsOffset, typecheck);
AddInstruction(instr);
instr->SetGVNFlag(kDependsOnElementsPointer);
instr->ClearGVNFlag(kDependsOnMaps);
instr->ClearGVNFlag(kDependsOnInobjectFields);
return instr;
HValue* typecheck) {
return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck);
}
......@@ -1586,7 +1523,6 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
ElementsKind kind,
HValue* length,
HValue* new_capacity) {
Zone* zone = this->zone();
HValue* context = environment()->LookupContext();
BuildNewSpaceArrayCheck(new_capacity, kind);
......@@ -1598,13 +1534,7 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
new_elements, kind,
length, new_capacity);
Factory* factory = isolate()->factory();
HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
object,
factory->elements_field_string(),
new_elements, true, Representation::Tagged(),
JSArray::kElementsOffset));
elements_store->SetGVNFlag(kChangesElementsPointer);
AddStore(object, HObjectAccess::ForElementsPointer(), new_elements);
return new_elements;
}
......@@ -1709,7 +1639,6 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context,
ElementsKind kind,
int length) {
Zone* zone = this->zone();
Factory* factory = isolate()->factory();
NoObservableSideEffectsScope no_effects(this);
......@@ -1739,16 +1668,8 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context,
// Copy the JS array part.
for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
if ((i != JSArray::kElementsOffset) || (length == 0)) {
HInstruction* value = AddInstruction(new(zone) HLoadNamedField(
boilerplate, true, Representation::Tagged(), i));
if (i != JSArray::kMapOffset) {
AddInstruction(new(zone) HStoreNamedField(object,
factory->empty_string(),
value, true,
Representation::Tagged(), i));
} else {
BuildStoreMap(object, value);
}
HObjectAccess access = HObjectAccess::ForJSArrayOffset(i);
AddStore(object, access, AddLoad(boilerplate, access));
}
}
......@@ -1763,21 +1684,12 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context,
HValue* boilerplate_elements = AddLoadElements(boilerplate);
HValue* object_elements =
AddInstruction(new(zone) HInnerAllocatedObject(object, elems_offset));
AddInstruction(new(zone) HStoreNamedField(object,
factory->elements_field_string(),
object_elements, true,
Representation::Tagged(),
JSObject::kElementsOffset));
AddStore(object, HObjectAccess::ForElementsPointer(), object_elements);
// Copy the elements array header.
for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
HInstruction* value =
AddInstruction(new(zone) HLoadNamedField(
boilerplate_elements, true, Representation::Tagged(), i));
AddInstruction(new(zone) HStoreNamedField(object_elements,
factory->empty_string(),
value, true,
Representation::Tagged(), i));
HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
AddStore(object_elements, access, AddLoad(boilerplate_elements, access));
}
// Copy the elements array contents.
......@@ -1857,34 +1769,30 @@ HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object,
HInnerAllocatedObject(previous_object, previous_object_size);
AddInstruction(alloc_site);
Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map());
BuildStoreMap(alloc_site, alloc_site_map);
AddInstruction(new(zone()) HStoreNamedField(alloc_site,
isolate()->factory()->payload_string(),
payload,
true,
Representation::Tagged(),
AllocationSiteInfo::kPayloadOffset));
AddStoreMapConstant(alloc_site, alloc_site_map);
HObjectAccess access = HObjectAccess::ForAllocationSitePayload();
AddStore(alloc_site, access, payload);
return alloc_site;
}
HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) {
// Get the global context, then the native context
HInstruction* global_object = AddInstruction(new(zone())
HGlobalObject(context));
HInstruction* native_context = AddInstruction(new(zone())
HLoadNamedField(global_object, true, Representation::Tagged(),
GlobalObject::kNativeContextOffset));
return native_context;
HGlobalObject(context));
HObjectAccess access = HObjectAccess::ForJSObjectOffset(
GlobalObject::kNativeContextOffset);
return AddLoad(global_object, access);
}
HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) {
HInstruction* native_context = BuildGetNativeContext(context);
int offset = Context::kHeaderSize +
kPointerSize * Context::ARRAY_FUNCTION_INDEX;
HInstruction* array_function = AddInstruction(new(zone())
HLoadNamedField(native_context, true, Representation::Tagged(), offset));
return array_function;
HInstruction* index = AddInstruction(new(zone())
HConstant(Context::ARRAY_FUNCTION_INDEX, Representation::Integer32()));
return AddInstruction(new (zone())
HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS));
}
......@@ -1905,13 +1813,18 @@ HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) {
HInstruction* native_context = builder()->BuildGetNativeContext(context);
int offset = Context::kHeaderSize +
kPointerSize * Context::JS_ARRAY_MAPS_INDEX;
HInstruction* map_array = AddInstruction(new(zone())
HLoadNamedField(native_context, true, Representation::Tagged(), offset));
offset = kind_ * kPointerSize + FixedArrayBase::kHeaderSize;
return AddInstruction(new(zone()) HLoadNamedField(
map_array, true, Representation::Tagged(), offset));
HInstruction* index = builder()->AddInstruction(new(zone())
HConstant(Context::JS_ARRAY_MAPS_INDEX, Representation::Integer32()));
HInstruction* map_array = builder()->AddInstruction(new(zone())
HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS));
HInstruction* kind_index = builder()->AddInstruction(new(zone())
HConstant(kind_, Representation::Integer32()));
return builder()->AddInstruction(new(zone())
HLoadKeyed(map_array, kind_index, NULL, FAST_ELEMENTS));
}
......@@ -2020,6 +1933,39 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
}
HStoreNamedField* HGraphBuilder::AddStore(HValue *object,
HObjectAccess access,
HValue *val,
Representation representation) {
HStoreNamedField *instr = new(zone())
HStoreNamedField(object, access, val, representation);
AddInstruction(instr);
return instr;
}
HLoadNamedField* HGraphBuilder::AddLoad(HValue *object,
HObjectAccess access,
HValue *typecheck,
Representation representation) {
HLoadNamedField *instr =
new(zone()) HLoadNamedField(object, access, typecheck, representation);
AddInstruction(instr);
return instr;
}
HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
Handle<Map> map) {
HValue* constant =
AddInstruction(new(zone()) HConstant(map, Representation::Tagged()));
HStoreNamedField *instr =
new(zone()) HStoreNamedField(object, HObjectAccess::ForMap(), constant);
AddInstruction(instr);
return instr;
}
HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info,
TypeFeedbackOracle* oracle)
: HGraphBuilder(info),
......@@ -6390,7 +6336,7 @@ static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
Code* unoptimized_code, FunctionLiteral* expr) {
int start_position = expr->start_position();
RelocIterator it(unoptimized_code);
for (;!it.done(); it.next()) {
for (; !it.done(); it.next()) {
RelocInfo* rinfo = it.rinfo();
if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
Object* obj = rinfo->target_object();
......@@ -7072,20 +7018,6 @@ static bool ComputeLoadStoreField(Handle<Map> type,
}
static int ComputeLoadStoreFieldIndex(Handle<Map> type,
LookupResult* lookup) {
ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type));
if (lookup->IsField()) {
return lookup->GetLocalFieldIndexFromMap(*type);
} else {
Map* transition = lookup->GetTransitionMapFromMap(*type);
int descriptor = transition->LastAdded();
int index = transition->instance_descriptors()->GetFieldIndex(descriptor);
return index - type->inobject_properties();
}
}
static Representation ComputeLoadStoreRepresentation(Handle<Map> type,
LookupResult* lookup) {
if (lookup->IsField()) {
......@@ -7150,43 +7082,37 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
zone()));
}
int index = ComputeLoadStoreFieldIndex(map, lookup);
bool is_in_object = index < 0;
HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
Representation representation = ComputeLoadStoreRepresentation(map, lookup);
int offset = index * kPointerSize;
if (index < 0) {
// Negative property indices are in-object properties, indexed
// from the end of the fixed part of the object.
offset += map->instance_size();
} else {
offset += FixedArray::kHeaderSize;
}
bool transition_to_field = lookup->IsTransitionToField(*map);
HStoreNamedField *instr;
if (FLAG_track_double_fields && representation.IsDouble()) {
if (transition_to_field) {
// The store requires a mutable HeapNumber to be allocated.
NoObservableSideEffectsScope no_side_effects(this);
HInstruction* heap_number_size = AddInstruction(new(zone()) HConstant(
HeapNumber::kSize, Representation::Integer32()));
HInstruction* double_box = AddInstruction(new(zone()) HAllocate(
environment()->LookupContext(), heap_number_size,
HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE));
BuildStoreMap(double_box, isolate()->factory()->heap_number_map());
AddInstruction(new(zone()) HStoreNamedField(
double_box, name, value, true,
Representation::Double(), HeapNumber::kValueOffset));
value = double_box;
representation = Representation::Tagged();
AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map());
AddStore(double_box, HObjectAccess::ForHeapNumberValue(),
value, Representation::Double());
instr = new(zone()) HStoreNamedField(object, field_access, double_box);
} else {
HInstruction* double_box = AddInstruction(new(zone()) HLoadNamedField(
object, is_in_object, Representation::Tagged(), offset));
// Already holds a HeapNumber; load the box and write its value field.
HInstruction* double_box = AddLoad(object, field_access);
double_box->set_type(HType::HeapNumber());
return new(zone()) HStoreNamedField(
double_box, name, value, true,
Representation::Double(), HeapNumber::kValueOffset);
instr = new(zone()) HStoreNamedField(double_box,
HObjectAccess::ForHeapNumberValue(), value, Representation::Double());
}
} else {
// This is a non-double store.
instr = new(zone()) HStoreNamedField(
object, field_access, value, representation);
}
HStoreNamedField* instr = new(zone()) HStoreNamedField(
object, name, value, is_in_object, representation, offset);
if (transition_to_field) {
Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
instr->set_transition(transition);
......@@ -7256,9 +7182,10 @@ bool HOptimizedGraphBuilder::HandlePolymorphicArrayLengthLoad(
BuildCheckNonSmi(object);
HInstruction* typecheck =
AddInstruction(HCheckMaps::New(object, types, zone()));
HInstruction* instr =
HLoadNamedField::NewArrayLength(zone(), object, typecheck);
AddInstruction(HCheckMaps::New(object, types, zone()));
HInstruction* instr = new(zone())
HLoadNamedField(object, HObjectAccess::ForArrayLength(), typecheck);
instr->set_position(expr->position());
ast_context()->ReturnInstruction(instr, expr->id());
return true;
......@@ -7278,53 +7205,42 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
// Use monomorphic load if property lookup results in the same field index
// for all maps. Requires special map check on the set of all handled maps.
HInstruction* instr = NULL;
if (types->length() > 0 && types->length() <= kMaxLoadPolymorphism) {
LookupResult lookup(isolate());
int previous_field_offset = 0;
bool previous_field_is_in_object = false;
Representation representation = Representation::None();
int count;
for (count = 0; count < types->length(); ++count) {
Handle<Map> map = types->at(count);
if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
int index = ComputeLoadStoreFieldIndex(map, &lookup);
Representation new_representation =
ComputeLoadStoreRepresentation(map, &lookup);
bool is_in_object = index < 0;
int offset = index * kPointerSize;
if (index < 0) {
// Negative property indices are in-object properties, indexed
// from the end of the fixed part of the object.
offset += map->instance_size();
} else {
offset += FixedArray::kHeaderSize;
}
if (count == 0) {
previous_field_offset = offset;
previous_field_is_in_object = is_in_object;
representation = new_representation;
} else if (offset != previous_field_offset ||
is_in_object != previous_field_is_in_object ||
(FLAG_track_fields &&
!representation.IsCompatibleForLoad(new_representation))) {
break;
}
representation = representation.generalize(new_representation);
}
if (count == types->length()) {
AddInstruction(HCheckMaps::New(object, types, zone()));
instr = DoBuildLoadNamedField(
object, previous_field_is_in_object,
representation, previous_field_offset);
LookupResult lookup(isolate());
int count;
Representation representation = Representation::None();
HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
for (count = 0;
count < types->length() && count < kMaxLoadPolymorphism;
++count) {
Handle<Map> map = types->at(count);
if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
Representation new_representation =
ComputeLoadStoreRepresentation(map, &lookup);
if (count == 0) {
// First time through the loop; set access and representation.
access = new_access;
representation = new_representation;
} else if (!representation.IsCompatibleForLoad(new_representation)) {
// Representations did not match.
break;
} else if (access.offset() != new_access.offset()) {
// Offsets did not match.
break;
} else if (access.IsInobject() != new_access.IsInobject()) {
// In-objectness did not match.
break;
}
}
if (instr == NULL) {
if (count == types->length()) {
// Everything matched; can use monomorphic load.
AddInstruction(HCheckMaps::New(object, types, zone()));
instr = BuildLoadNamedField(object, access, representation);
} else {
// Something did not match; must use a polymorphic load.
HValue* context = environment()->LookupContext();
instr = new(zone()) HLoadNamedFieldPolymorphic(
context, object, types, name, zone());
......@@ -7881,40 +7797,22 @@ void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
}
HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField(
HValue* object,
Handle<Map> map,
LookupResult* lookup) {
int index = lookup->GetLocalFieldIndexFromMap(*map);
// Negative property indices are in-object properties, indexed from the end of
// the fixed part of the object. Non-negative property indices are in the
// properties array.
int inobject = index < 0;
Representation representation = lookup->representation();
int offset = inobject
? index * kPointerSize + map->instance_size()
: index * kPointerSize + FixedArray::kHeaderSize;
return DoBuildLoadNamedField(object, inobject, representation, offset);
}
HLoadNamedField* HGraphBuilder::DoBuildLoadNamedField(
HLoadNamedField* HGraphBuilder::BuildLoadNamedField(
HValue* object,
bool inobject,
Representation representation,
int offset) {
HObjectAccess access,
Representation representation) {
bool load_double = false;
if (representation.IsDouble()) {
representation = Representation::Tagged();
load_double = FLAG_track_double_fields;
}
HLoadNamedField* field =
new(zone()) HLoadNamedField(object, inobject, representation, offset);
new(zone()) HLoadNamedField(object, access, NULL, representation);
if (load_double) {
AddInstruction(field);
field->set_type(HType::HeapNumber());
return new(zone()) HLoadNamedField(
field, true, Representation::Double(), HeapNumber::kValueOffset);
return new(zone()) HLoadNamedField(field,
HObjectAccess::ForHeapNumberValue(), NULL, Representation::Double());
}
return field;
}
......@@ -7955,7 +7853,8 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
if (name->Equals(isolate()->heap()->length_string())) {
if (map->instance_type() == JS_ARRAY_TYPE) {
AddCheckMapsWithTransitions(object, map);
return HLoadNamedField::NewArrayLength(zone(), object, object);
return new(zone()) HLoadNamedField(object,
HObjectAccess::ForArrayLength());
}
}
......@@ -7963,7 +7862,9 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
map->LookupDescriptor(NULL, *name, &lookup);
if (lookup.IsField()) {
AddCheckMap(object, map);
return BuildLoadNamedField(object, map, &lookup);
return BuildLoadNamedField(object,
HObjectAccess::ForField(map, &lookup, name),
ComputeLoadStoreRepresentation(map, &lookup));
}
// Handle a load of a constant known function.
......@@ -7982,9 +7883,11 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
AddCheckMap(object, map);
AddInstruction(
new(zone()) HCheckPrototypeMaps(prototype, holder, zone()));
HValue* holder_value = AddInstruction(
new(zone()) HConstant(holder, Representation::Tagged()));
return BuildLoadNamedField(holder_value, holder_map, &lookup);
HValue* holder_value = AddInstruction(new(zone())
HConstant(holder, Representation::Tagged()));
return BuildLoadNamedField(holder_value,
HObjectAccess::ForField(holder_map, &lookup, name),
ComputeLoadStoreRepresentation(map, &lookup));
}
// Handle a load of a constant function somewhere in the prototype chain.
......@@ -8260,10 +8163,10 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
current_block()->Finish(typecheck);
set_current_block(if_jsarray);
HInstruction* length;
length = AddInstruction(
HLoadNamedField::NewArrayLength(zone(), object, typecheck,
HType::Smi()));
HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(),
typecheck, Representation::Smi());
length->set_type(HType::Smi());
checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
access = AddInstruction(BuildFastElementAccess(
elements, checked_key, val, elements_kind_branch,
......@@ -10903,7 +10806,6 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
int* offset,
AllocationSiteMode mode) {
Zone* zone = this->zone();
Factory* factory = isolate()->factory();
HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant(
original_boilerplate_object, Representation::Tagged()));
......@@ -10954,6 +10856,12 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
Handle<Object> value =
Handle<Object>(boilerplate_object->InObjectPropertyAt(index),
isolate());
// The access for the store depends on the type of the boilerplate.
HObjectAccess access = boilerplate_object->IsJSArray() ?
HObjectAccess::ForJSArrayOffset(property_offset) :
HObjectAccess::ForJSObjectOffset(property_offset);
if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
Handle<JSObject> original_value_object = Handle<JSObject>::cast(
......@@ -10961,39 +10869,39 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
isolate()));
HInstruction* value_instruction =
AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
AddInstruction(new(zone) HStoreNamedField(
object_properties, name, value_instruction, true,
Representation::Tagged(), property_offset));
AddStore(object_properties, access, value_instruction);
BuildEmitDeepCopy(value_object, original_value_object, target,
offset, DONT_TRACK_ALLOCATION_SITE);
offset, DONT_TRACK_ALLOCATION_SITE);
} else {
Representation representation = details.representation();
HInstruction* value_instruction = AddInstruction(new(zone) HConstant(
value, Representation::Tagged()));
if (representation.IsDouble()) {
// Allocate a HeapNumber box and store the value into it.
HInstruction* double_box =
AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
BuildStoreMap(double_box, factory->heap_number_map());
AddInstruction(new(zone) HStoreNamedField(
double_box, name, value_instruction, true,
Representation::Double(), HeapNumber::kValueOffset));
AddStoreMapConstant(double_box,
isolate()->factory()->heap_number_map());
AddStore(double_box, HObjectAccess::ForHeapNumberValue(),
value_instruction, Representation::Double());
value_instruction = double_box;
*offset += HeapNumber::kSize;
}
AddInstruction(new(zone) HStoreNamedField(
object_properties, name, value_instruction, true,
Representation::Tagged(), property_offset));
AddStore(object_properties, access, value_instruction);
}
}
int inobject_properties = boilerplate_object->map()->inobject_properties();
HInstruction* value_instruction = AddInstruction(new(zone) HConstant(
factory->one_pointer_filler_map(), Representation::Tagged()));
HInstruction* value_instruction = AddInstruction(new(zone)
HConstant(isolate()->factory()->one_pointer_filler_map(),
Representation::Tagged()));
for (int i = copied_fields; i < inobject_properties; i++) {
AddInstruction(new(zone) HStoreNamedField(
object_properties, factory->unknown_field_string(), value_instruction,
true, Representation::Tagged(),
boilerplate_object->GetInObjectPropertyOffset(i)));
HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
AddStore(object_properties, access, value_instruction);
}
// Build Allocation Site Info if desired
......@@ -11067,13 +10975,12 @@ HValue* HOptimizedGraphBuilder::BuildCopyObjectHeader(
int elements_size) {
ASSERT(boilerplate_object->properties()->length() == 0);
Zone* zone = this->zone();
Factory* factory = isolate()->factory();
HValue* result = NULL;
HValue* object_header =
AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
Handle<Map> boilerplate_object_map(boilerplate_object->map());
BuildStoreMap(object_header, boilerplate_object_map);
AddStoreMapConstant(object_header, boilerplate_object_map);
HInstruction* elements;
if (elements_size == 0) {
......@@ -11086,23 +10993,15 @@ HValue* HOptimizedGraphBuilder::BuildCopyObjectHeader(
target, elements_offset));
result = elements;
}
HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
object_header,
factory->elements_field_string(),
elements,
true, Representation::Tagged(), JSObject::kElementsOffset));
elements_store->SetGVNFlag(kChangesElementsPointer);
AddStore(object_header, HObjectAccess::ForElementsPointer(), elements);
Handle<Object> properties_field =
Handle<Object>(boilerplate_object->properties(), isolate());
ASSERT(*properties_field == isolate()->heap()->empty_fixed_array());
HInstruction* properties = AddInstruction(new(zone) HConstant(
properties_field, Representation::None()));
AddInstruction(new(zone) HStoreNamedField(object_header,
factory->empty_string(),
properties, true,
Representation::Tagged(),
JSObject::kPropertiesOffset));
HObjectAccess access = HObjectAccess::ForPropertiesPointer();
AddStore(object_header, access, properties);
if (boilerplate_object->IsJSArray()) {
Handle<JSArray> boilerplate_array =
......@@ -11111,16 +11010,13 @@ HValue* HOptimizedGraphBuilder::BuildCopyObjectHeader(
Handle<Object>(boilerplate_array->length(), isolate());
HInstruction* length = AddInstruction(new(zone) HConstant(
length_field, Representation::None()));
ASSERT(boilerplate_array->length()->IsSmi());
Representation representation =
IsFastElementsKind(boilerplate_array->GetElementsKind())
? Representation::Smi() : Representation::Tagged();
HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField(
object_header,
factory->length_field_string(),
length,
true, representation, JSArray::kLengthOffset));
length_store->SetGVNFlag(kChangesArrayLengths);
AddStore(object_header, HObjectAccess::ForArrayLength(),
length, representation);
}
return result;
......@@ -11504,13 +11400,8 @@ void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
// Create in-object property store to kValueOffset.
set_current_block(if_js_value);
Handle<String> name = isolate()->factory()->undefined_string();
AddInstruction(new(zone()) HStoreNamedField(object,
name,
value,
true, // in-object store.
Representation::Tagged(),
JSValue::kValueOffset));
AddStore(object,
HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value);
if_js_value->Goto(join);
join->SetJoinId(call->id());
set_current_block(join);
......
......@@ -992,11 +992,6 @@ class HGraphBuilder {
HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
// Building common constructs
HLoadNamedField* DoBuildLoadNamedField(HValue* object,
bool inobject,
Representation representation,
int offset);
HInstruction* BuildExternalArrayElementAccess(
HValue* external_elements,
HValue* checked_key,
......@@ -1039,8 +1034,24 @@ class HGraphBuilder {
KeyedAccessStoreMode store_mode,
Representation checked_index_representation = Representation::None());
HInstruction* BuildStoreMap(HValue* object, HValue* map);
HInstruction* BuildStoreMap(HValue* object, Handle<Map> map);
HLoadNamedField* AddLoad(
HValue *object,
HObjectAccess access,
HValue *typecheck = NULL,
Representation representation = Representation::Tagged());
HLoadNamedField* BuildLoadNamedField(
HValue* object,
HObjectAccess access,
Representation representation);
HStoreNamedField* AddStore(
HValue *object,
HObjectAccess access,
HValue *val,
Representation representation = Representation::Tagged());
HStoreNamedField* AddStoreMapConstant(HValue *object, Handle<Map>);
HLoadNamedField* AddLoadElements(HValue *object, HValue *typecheck = NULL);
......@@ -1692,9 +1703,6 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
bool is_store,
bool* has_side_effects);
HLoadNamedField* BuildLoadNamedField(HValue* object,
Handle<Map> map,
LookupResult* result);
HInstruction* BuildLoadNamedGeneric(HValue* object,
Handle<String> name,
Property* expr);
......
......@@ -416,8 +416,7 @@ LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
void LStoreNamedField::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
stream->Add(".");
stream->Add(*String::cast(*name())->ToCString());
hydrogen()->access().PrintTo(stream);
stream->Add(" <- ");
value()->PrintTo(stream);
}
......
......@@ -373,8 +373,7 @@ void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
void LStoreNamedField::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
stream->Add(".");
stream->Add(*String::cast(*name())->ToCString());
hydrogen()->access().PrintTo(stream);
stream->Add(" <- ");
value()->PrintTo(stream);
}
......
......@@ -341,6 +341,7 @@ Handle<Code> StubCache::ComputeKeyedLoadField(Handle<Name> name,
PropertyIndex field,
Representation representation) {
if (receiver.is_identical_to(holder)) {
// TODO(titzer): this should use an HObjectAccess
KeyedLoadFieldStub stub(field.is_inobject(holder),
field.translate(holder),
representation);
......
......@@ -391,8 +391,7 @@ LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
void LStoreNamedField::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
stream->Add(".");
stream->Add(*String::cast(*name())->ToCString());
hydrogen()->access().PrintTo(stream);
stream->Add(" <- ");
value()->PrintTo(stream);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment