| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index de3254a2721cfc12c599f6a83639fed48928d2bf..d6a648891a7e4971acd69ad6a29eee704c1b9f5b 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -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),
|
| @@ -6386,7 +6332,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();
|
| @@ -7062,20 +7008,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()) {
|
| @@ -7140,43 +7072,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);
|
| @@ -7246,9 +7172,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;
|
| @@ -7268,53 +7195,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());
|
| @@ -7871,40 +7787,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;
|
| }
|
| @@ -7945,7 +7843,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());
|
| }
|
| }
|
|
|
| @@ -7953,7 +7852,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.
|
| @@ -7972,9 +7873,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.
|
| @@ -8250,10 +8153,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,
|
| @@ -10896,7 +10799,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()));
|
| @@ -10945,6 +10847,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(
|
| @@ -10952,28 +10860,29 @@ 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);
|
| }
|
| }
|
|
|
| @@ -11045,13 +10954,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) {
|
| @@ -11064,23 +10972,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 =
|
| @@ -11089,16 +10989,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;
|
| @@ -11485,13 +11382,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);
|
|
|