return OffsetField::decode(value_);
}
+ inline Representation representation() const {
+ return Representation::FromKind(RepresentationField::decode(value_));
+ }
+
inline Handle<String> name() const {
return name_;
}
+ inline HObjectAccess WithRepresentation(Representation representation) {
+ return HObjectAccess(portion(), offset(), representation, name());
+ }
+
static HObjectAccess ForHeapNumberValue() {
- return HObjectAccess(kDouble, HeapNumber::kValueOffset);
+ return HObjectAccess(
+ kDouble, HeapNumber::kValueOffset, Representation::Double());
}
static HObjectAccess ForElementsPointer() {
return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
}
- static HObjectAccess ForArrayLength() {
- return HObjectAccess(kArrayLengths, JSArray::kLengthOffset);
+ static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
+ return HObjectAccess(
+ kArrayLengths, JSArray::kLengthOffset,
+ IsFastElementsKind(elements_kind) && FLAG_track_fields ?
+ Representation::Smi() : Representation::Tagged());
}
static HObjectAccess ForAllocationSiteTransitionInfo() {
}
static HObjectAccess ForFixedArrayLength() {
- return HObjectAccess(kArrayLengths, FixedArray::kLengthOffset);
+ return HObjectAccess(
+ kArrayLengths, FixedArray::kLengthOffset,
+ FLAG_track_fields ?
+ Representation::Smi() : Representation::Tagged());
}
static HObjectAccess ForPropertiesPointer() {
static HObjectAccess ForFixedArrayHeader(int offset);
// Create an access to an in-object property in a JSObject.
- static HObjectAccess ForJSObjectOffset(int offset);
+ static HObjectAccess ForJSObjectOffset(int offset,
+ Representation representation = Representation::Tagged());
// 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);
+ static HObjectAccess ForBackingStoreOffset(int offset,
+ Representation representation = Representation::Tagged());
// Create an access to a resolved field (in-object or backing store).
static HObjectAccess ForField(Handle<Map> map,
};
HObjectAccess(Portion portion, int offset,
- Handle<String> name = Handle<String>::null())
- : value_(PortionField::encode(portion) | OffsetField::encode(offset)),
+ Representation representation = Representation::Tagged(),
+ Handle<String> name = Handle<String>::null())
+ : value_(PortionField::encode(portion) |
+ RepresentationField::encode(representation.kind()) |
+ OffsetField::encode(offset)),
name_(name) {
- ASSERT(this->offset() == offset); // offset should decode correctly
- ASSERT(this->portion() == portion); // portion should decode correctly
+ // assert that the fields decode correctly
+ ASSERT(this->offset() == offset);
+ ASSERT(this->portion() == portion);
+ ASSERT(RepresentationField::decode(value_) == representation.kind());
}
class PortionField : public BitField<Portion, 0, 3> {};
- class OffsetField : public BitField<int, 3, 29> {};
+ class RepresentationField : public BitField<Representation::Kind, 3, 3> {};
+ class OffsetField : public BitField<int, 6, 26> {};
- uint32_t value_; // encodes both portion and offset
+ uint32_t value_; // encodes portion, representation, and offset
Handle<String> name_;
friend class HLoadNamedField;
public:
HLoadNamedField(HValue* object,
HObjectAccess access,
- HValue* typecheck = NULL,
- Representation field_representation
- = Representation::Tagged())
- : access_(access),
- field_representation_(field_representation) {
+ HValue* typecheck = NULL)
+ : access_(access) {
ASSERT(object != NULL);
SetOperandAt(0, object);
SetOperandAt(1, typecheck != NULL ? typecheck : object);
- if (FLAG_track_fields && field_representation.IsSmi()) {
+ Representation representation = access.representation();
+ if (representation.IsSmi()) {
set_type(HType::Smi());
- set_representation(field_representation);
- } else if (FLAG_track_double_fields && field_representation.IsDouble()) {
- set_representation(field_representation);
+ set_representation(representation);
+ } else if (representation.IsDouble()) {
+ set_representation(representation);
} else if (FLAG_track_heap_object_fields &&
- field_representation.IsHeapObject()) {
+ representation.IsHeapObject()) {
set_type(HType::NonPrimitive());
set_representation(Representation::Tagged());
} else {
bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
HObjectAccess access() const { return access_; }
- Representation field_representation() const { return representation_; }
+ Representation field_representation() const {
+ return access_.representation();
+ }
virtual bool HasEscapingOperandAt(int index) { return false; }
virtual Representation RequiredInputRepresentation(int index) {
virtual bool IsDeletable() const { return true; }
HObjectAccess access_;
- Representation field_representation_;
};
public:
HStoreNamedField(HValue* obj,
HObjectAccess access,
- HValue* val,
- Representation field_representation
- = Representation::Tagged())
+ HValue* val)
: access_(access),
- field_representation_(field_representation),
transition_(),
transition_unique_id_(),
new_space_dominator_(NULL),
virtual bool HasEscapingOperandAt(int index) { return index == 1; }
virtual Representation RequiredInputRepresentation(int index) {
- if (FLAG_track_double_fields &&
- index == 1 && field_representation_.IsDouble()) {
- return field_representation_;
- } else if (FLAG_track_fields &&
- index == 1 && field_representation_.IsSmi()) {
- return field_representation_;
+ if (index == 1 && field_representation().IsDouble()) {
+ return field_representation();
+ } else if (index == 1 && field_representation().IsSmi()) {
+ return field_representation();
}
return Representation::Tagged();
}
HValue* new_space_dominator() const { return new_space_dominator_; }
bool NeedsWriteBarrier() {
- ASSERT(!(FLAG_track_double_fields && field_representation_.IsDouble()) ||
+ ASSERT(!(FLAG_track_double_fields && field_representation().IsDouble()) ||
transition_.is_null());
if (IsSkipWriteBarrier()) return false;
- return (!FLAG_track_fields || !field_representation_.IsSmi()) &&
- // If there is a transition, a new storage object needs to be allocated.
- !(FLAG_track_double_fields && field_representation_.IsDouble()) &&
- StoringValueNeedsWriteBarrier(value()) &&
+ if (field_representation().IsDouble()) return false;
+ if (field_representation().IsSmi()) return false;
+ return StoringValueNeedsWriteBarrier(value()) &&
ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
}
}
Representation field_representation() const {
- return field_representation_;
+ return access_.representation();
}
private:
HObjectAccess access_;
- Representation field_representation_;
Handle<Map> transition_;
UniqueValueId transition_unique_id_;
HValue* new_space_dominator_;
HAdd::New(zone, context, key, graph_->GetConstant1()));
new_length->ClearFlag(HValue::kCanOverflow);
- Representation representation = IsFastElementsKind(kind)
- ? Representation::Smi() : Representation::Tagged();
- AddStore(object, HObjectAccess::ForArrayLength(), new_length,
- representation);
+ AddStore(object, HObjectAccess::ForArrayLength(kind), new_length);
}
length_checker.Else();
HInstruction* elements_length = AddLoadFixedArrayLength(elements);
HInstruction* array_length = is_jsarray
- ? AddLoad(object, HObjectAccess::ForArrayLength(),
- NULL, Representation::Smi())
+ ? AddLoad(object, HObjectAccess::ForArrayLength(from_kind), NULL)
: elements_length;
- array_length->set_type(HType::Smi());
BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
array_length, elements_length);
}
HInstruction* length = NULL;
if (is_js_array) {
- length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck,
- Representation::Smi());
+ length = AddLoad(object, HObjectAccess::ForArrayLength(elements_kind),
+ mapcheck);
} else {
length = AddLoadFixedArrayLength(elements);
}
: factory->fixed_array_map();
AddStoreMapConstant(elements, map);
- Representation representation = IsFastElementsKind(kind)
- ? Representation::Smi() : Representation::Tagged();
- AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity,
- representation);
+ AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity);
}
HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
HValue* array_map,
AllocationSiteMode mode,
+ ElementsKind elements_kind,
HValue* allocation_site_payload,
HValue* length_field) {
HObjectAccess access = HObjectAccess::ForPropertiesPointer();
AddStore(array, access, empty_fixed_array);
- AddStore(array, HObjectAccess::ForArrayLength(), length_field);
+ AddStore(array, HObjectAccess::ForArrayLength(elements_kind), length_field);
if (mode == TRACK_ALLOCATION_SITE) {
BuildCreateAllocationMemento(array,
HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) {
- HLoadNamedField* instr = AddLoad(object, HObjectAccess::ForFixedArrayLength(),
- NULL, Representation::Smi());
- instr->set_type(HType::Smi());
- return instr;
+ return AddLoad(object, HObjectAccess::ForFixedArrayLength());
}
// No need for a context lookup if the kind_ matches the initial
// map, because we can just load the map in that case.
HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
- HInstruction* load =
- builder()->BuildLoadNamedField(constructor_function_,
- access,
- Representation::Tagged());
- return builder()->AddInstruction(load);
+ return builder()->AddInstruction(
+ builder()->BuildLoadNamedField(constructor_function_, access));
}
HInstruction* native_context = builder()->BuildGetNativeContext(context);
// Find the map near the constructor function
HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
return builder()->AddInstruction(
- builder()->BuildLoadNamedField(constructor_function_,
- access,
- Representation::Tagged()));
+ builder()->BuildLoadNamedField(constructor_function_, access));
}
elements_location_ = builder()->BuildJSArrayHeader(new_object,
map,
mode_,
+ kind_,
allocation_site_payload_,
length_field);
HStoreNamedField* HGraphBuilder::AddStore(HValue *object,
HObjectAccess access,
- HValue *val,
- Representation representation) {
- return Add<HStoreNamedField>(object, access, val, representation);
+ HValue *val) {
+ return Add<HStoreNamedField>(object, access, val);
}
HLoadNamedField* HGraphBuilder::AddLoad(HValue *object,
HObjectAccess access,
- HValue *typecheck,
- Representation representation) {
- return Add<HLoadNamedField>(object, access, typecheck, representation);
+ HValue *typecheck) {
+ return Add<HLoadNamedField>(object, access, typecheck);
}
}
-static Representation ComputeLoadStoreRepresentation(Handle<Map> type,
- LookupResult* lookup) {
- if (lookup->IsField()) {
- return lookup->representation();
- } else {
- Map* transition = lookup->GetTransitionMapFromMap(*type);
- int descriptor = transition->LastAdded();
- PropertyDetails details =
- transition->instance_descriptors()->GetDetails(descriptor);
- return details.representation();
- }
-}
-
-
void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) {
BuildCheckHeapObject(object);
AddInstruction(HCheckMaps::New(object, map, zone(), top_info()));
}
HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
- Representation representation = ComputeLoadStoreRepresentation(map, lookup);
bool transition_to_field = lookup->IsTransitionToField(*map);
HStoreNamedField *instr;
- if (FLAG_track_double_fields && representation.IsDouble()) {
+ if (FLAG_track_double_fields && field_access.representation().IsDouble()) {
+ HObjectAccess heap_number_access =
+ field_access.WithRepresentation(Representation::Tagged());
if (transition_to_field) {
// The store requires a mutable HeapNumber to be allocated.
NoObservableSideEffectsScope no_side_effects(this);
HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
- HInstruction* double_box = Add<HAllocate>(
+ HInstruction* heap_number = Add<HAllocate>(
environment()->LookupContext(), heap_number_size,
HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE);
- 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);
+ AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map());
+ AddStore(heap_number, HObjectAccess::ForHeapNumberValue(), value);
+ instr = new(zone()) HStoreNamedField(
+ object, heap_number_access, heap_number);
} else {
// 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());
- instr = new(zone()) HStoreNamedField(double_box,
- HObjectAccess::ForHeapNumberValue(), value, Representation::Double());
+ HInstruction* heap_number = AddLoad(object, heap_number_access);
+ heap_number->set_type(HType::HeapNumber());
+ instr = new(zone()) HStoreNamedField(heap_number,
+ HObjectAccess::ForHeapNumberValue(), value);
}
} else {
- // This is a non-double store.
- instr = new(zone()) HStoreNamedField(
- object, field_access, value, representation);
+ // This is a normal store.
+ instr = new(zone()) HStoreNamedField(object, field_access, value);
}
if (transition_to_field) {
LookupResult lookup(isolate());
int count;
- Representation representation = Representation::None();
HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
for (count = 0; count < types->length(); ++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;
- } else if (!representation.IsCompatibleForLoad(new_representation)) {
+ } else if (!access.representation().IsCompatibleForLoad(
+ new_access.representation())) {
// Representations did not match.
break;
} else if (access.offset() != new_access.offset()) {
// In-objectness did not match.
break;
}
- representation = representation.generalize(new_representation);
+ access = access.WithRepresentation(
+ access.representation().generalize(new_access.representation()));
}
if (count == types->length()) {
// Everything matched; can use monomorphic load.
BuildCheckHeapObject(object);
AddInstruction(HCheckMaps::New(object, types, zone()));
- return BuildLoadNamedField(object, access, representation);
+ return BuildLoadNamedField(object, access);
}
if (count != 0) return NULL;
BuildCheckHeapObject(object);
AddInstruction(HCheckMaps::New(object, types, zone()));
+
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
AddInstruction(new(zone()) HCheckPrototypeMaps(
Handle<JSObject>::cast(prototype), holder, zone(), top_info()));
HValue* holder_value = AddInstruction(new(zone()) HConstant(holder));
return BuildLoadNamedField(holder_value,
- HObjectAccess::ForField(holder_map, &lookup, name),
- ComputeLoadStoreRepresentation(map, &lookup));
+ HObjectAccess::ForField(holder_map, &lookup, name));
}
ASSERT(!map->is_observed());
HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
- Representation new_representation =
- ComputeLoadStoreRepresentation(map, &lookup);
+ Representation new_representation = new_access.representation();
if (count == 0) {
// First time through the loop; set access and representation.
}
-HLoadNamedField* HGraphBuilder::BuildLoadNamedField(
- HValue* object,
- 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, access, NULL, representation);
- if (load_double) {
- AddInstruction(field);
- field->set_type(HType::HeapNumber());
- return new(zone()) HLoadNamedField(field,
- HObjectAccess::ForHeapNumberValue(), NULL, Representation::Double());
+HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
+ HObjectAccess access) {
+ if (FLAG_track_double_fields && access.representation().IsDouble()) {
+ // load the heap number
+ HLoadNamedField* heap_number =
+ AddLoad(object, access.WithRepresentation(Representation::Tagged()));
+ heap_number->set_type(HType::HeapNumber());
+ // load the double value from it
+ return new(zone()) HLoadNamedField(heap_number,
+ HObjectAccess::ForHeapNumberValue(), NULL);
}
- return field;
+ return new(zone()) HLoadNamedField(object, access, NULL);
}
if (map->instance_type() == JS_ARRAY_TYPE) {
AddCheckMapsWithTransitions(object, map);
return new(zone()) HLoadNamedField(object,
- HObjectAccess::ForArrayLength());
+ HObjectAccess::ForArrayLength(map->elements_kind()));
}
}
if (lookup.IsField()) {
AddCheckMap(object, map);
return BuildLoadNamedField(object,
- HObjectAccess::ForField(map, &lookup, name),
- ComputeLoadStoreRepresentation(map, &lookup));
+ HObjectAccess::ForField(map, &lookup, name));
}
// Handle a load of a constant known function.
Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info());
HValue* holder_value = Add<HConstant>(holder);
return BuildLoadNamedField(holder_value,
- HObjectAccess::ForField(holder_map, &lookup, name),
- ComputeLoadStoreRepresentation(map, &lookup));
+ HObjectAccess::ForField(holder_map, &lookup, name));
}
// Handle a load of a constant function somewhere in the prototype chain.
zone(), top_info(), mapcompare));
}
if (map->IsJSArray()) {
- HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(),
- mapcompare, Representation::Smi());
- length->set_type(HType::Smi());
+ HInstruction* length = AddLoad(
+ object, HObjectAccess::ForArrayLength(elements_kind), mapcompare);
checked_key = Add<HBoundsCheck>(key, length);
} else {
HInstruction* length = AddLoadFixedArrayLength(elements);
HInstruction* length = Add<HConstant>(length_field);
ASSERT(boilerplate_array->length()->IsSmi());
- Representation representation =
- IsFastElementsKind(boilerplate_array->GetElementsKind())
- ? Representation::Smi() : Representation::Tagged();
- AddStore(object_header, HObjectAccess::ForArrayLength(),
- length, representation);
+ AddStore(object_header, HObjectAccess::ForArrayLength(
+ boilerplate_array->GetElementsKind()), length);
}
return result;
AddStoreMapConstant(double_box,
isolate()->factory()->heap_number_map());
AddStore(double_box, HObjectAccess::ForHeapNumberValue(),
- value_instruction, Representation::Double());
+ value_instruction);
value_instruction = double_box;
}