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
This commit is contained in:
titzer@chromium.org 2013-05-24 08:38:21 +00:00
parent 1d39355405
commit 94b4240f5c
10 changed files with 489 additions and 412 deletions

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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_;

View File

@ -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;
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;
int index = ComputeLoadStoreFieldIndex(map, &lookup);
Representation new_representation =
ComputeLoadStoreRepresentation(map, &lookup);
bool is_in_object = index < 0;
int offset = index * kPointerSize;
HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
Representation new_representation =
ComputeLoadStoreRepresentation(map, &lookup);
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);
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(
HLoadNamedField* HGraphBuilder::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(
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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}