diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index 5b1ae39c7d..11776d8188 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -446,7 +446,8 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { for (int i = 0; i < object_size; i += kPointerSize) { HObjectAccess access = HObjectAccess::ForJSObjectOffset(i); Add(object, access, - Add(boilerplate, access)); + Add(boilerplate, access), + INITIALIZING_STORE); } ASSERT(FLAG_allocation_site_pretenuring || (size == object_size)); @@ -483,25 +484,29 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { Add(object, HObjectAccess::ForAllocationSiteOffset( AllocationSite::kTransitionInfoOffset), - initial_elements_kind); + initial_elements_kind, + INITIALIZING_STORE); // Unlike literals, constructed arrays don't have nested sites Add(object, HObjectAccess::ForAllocationSiteOffset( AllocationSite::kNestedSiteOffset), - graph()->GetConstant0()); + graph()->GetConstant0(), + INITIALIZING_STORE); // Pretenuring calculation field. Add(object, HObjectAccess::ForAllocationSiteOffset( AllocationSite::kPretenureDataOffset), - graph()->GetConstant0()); + graph()->GetConstant0(), + INITIALIZING_STORE); // Pretenuring memento creation count field. Add(object, HObjectAccess::ForAllocationSiteOffset( AllocationSite::kPretenureCreateCountOffset), - graph()->GetConstant0()); + graph()->GetConstant0(), + INITIALIZING_STORE); // Store an empty fixed array for the code dependency. HConstant* empty_fixed_array = @@ -510,7 +515,8 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { object, HObjectAccess::ForAllocationSiteOffset( AllocationSite::kDependentCodeOffset), - empty_fixed_array); + empty_fixed_array, + INITIALIZING_STORE); // Link the object to the allocation site list HValue* site_list = Add( @@ -519,10 +525,10 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { HObjectAccess::ForAllocationSiteList()); store = Add(object, HObjectAccess::ForAllocationSiteOffset(AllocationSite::kWeakNextOffset), - site); + site, INITIALIZING_STORE); store->SkipWriteBarrier(); Add(site_list, HObjectAccess::ForAllocationSiteList(), - object); + object, INITIALIZING_STORE); // We use a hammer (SkipWriteBarrier()) to indicate that we know the input // cell is really a Cell, and so no write barrier is needed. @@ -530,7 +536,7 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { // a cell. (perhaps with a new instruction, HAssert). HInstruction* cell = GetParameter(0); HObjectAccess access = HObjectAccess::ForCellValue(); - store = Add(cell, access, object); + store = Add(cell, access, object, INITIALIZING_STORE); store->SkipWriteBarrier(); return cell; } @@ -746,7 +752,7 @@ HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor( HInstruction* argument = Add( argument_elements, checked_length, key); - Add(elements, key, argument, kind); + Add(elements, key, argument, kind, INITIALIZING_STORE); builder.EndBody(); return new_object; } @@ -957,7 +963,8 @@ HValue* CodeStubGraphBuilder::BuildCodeInitializedStub() { IfBuilder if_heap_number(this); if_heap_number.IfNot(operand); if_heap_number.Then(); - Add(operand, HObjectAccess::ForHeapNumberValue(), result); + Add(operand, HObjectAccess::ForHeapNumberValue(), result, + INITIALIZING_STORE); Push(operand); if_heap_number.Else(); Push(result); @@ -1080,7 +1087,7 @@ HValue* CodeStubGraphBuilder::BuildCodeInitializedStub() { builder.Then(); builder.Deopt("Unexpected cell contents in global store"); builder.Else(); - Add(cell, access, value); + Add(cell, access, value, INITIALIZING_STORE); builder.End(); } @@ -1144,12 +1151,12 @@ void CodeStubGraphBuilderBase::BuildInstallOptimizedCode( HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); Add(js_function, HObjectAccess::ForNextFunctionLinkPointer(), - optimized_functions_list); + optimized_functions_list, INITIALIZING_STORE); // This store is the only one that should have a write barrier. Add(native_context, HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), - js_function); + js_function, INITIALIZING_STORE); } @@ -1157,7 +1164,8 @@ void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function, HValue* shared_info) { Add(js_function, HObjectAccess::ForNextFunctionLinkPointer(), - graph()->GetConstantUndefined()); + graph()->GetConstantUndefined(), + INITIALIZING_STORE); HValue* code_object = Add(shared_info, HObjectAccess::ForCodeOffset()); Add(js_function, code_object); @@ -1294,22 +1302,23 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { HInstruction* native_context = BuildGetNativeContext(); HInstruction* map_slot_value = Add(native_context, HObjectAccess::ForContextSlot(map_index)); - Add(js_function, HObjectAccess::ForMap(), map_slot_value); + Add(js_function, HObjectAccess::ForMap(), map_slot_value, + INITIALIZING_STORE); // Initialize the rest of the function. Add(js_function, HObjectAccess::ForPropertiesPointer(), - empty_fixed_array); + empty_fixed_array, INITIALIZING_STORE); Add(js_function, HObjectAccess::ForElementsPointer(), - empty_fixed_array); + empty_fixed_array, INITIALIZING_STORE); Add(js_function, HObjectAccess::ForLiteralsPointer(), - empty_fixed_array); + empty_fixed_array, INITIALIZING_STORE); Add(js_function, HObjectAccess::ForPrototypeOrInitialMap(), - graph()->GetConstantHole()); + graph()->GetConstantHole(), INITIALIZING_STORE); Add(js_function, HObjectAccess::ForSharedFunctionInfoPointer(), - shared_info); + shared_info, INITIALIZING_STORE); Add(js_function, HObjectAccess::ForFunctionContextPointer(), - context()); + context(), INITIALIZING_STORE); // Initialize the code pointer in the function to be the one // found in the shared function info object. @@ -1346,18 +1355,18 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { isolate()->factory()->function_context_map()); Add(function_context, HObjectAccess::ForFixedArrayLength(), - Add(length)); + Add(length), INITIALIZING_STORE); // Set up the fixed slots. Add(function_context, HObjectAccess::ForContextSlot(Context::CLOSURE_INDEX), - function); + function, INITIALIZING_STORE); Add(function_context, HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX), - context()); + context(), INITIALIZING_STORE); Add(function_context, HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX), - graph()->GetConstant0()); + graph()->GetConstant0(), INITIALIZING_STORE); // Copy the global object from the previous context. HValue* global_object = Add( @@ -1365,13 +1374,15 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { Add(function_context, HObjectAccess::ForContextSlot( Context::GLOBAL_OBJECT_INDEX), - global_object); + global_object, + INITIALIZING_STORE); // Initialize the rest of the slots to undefined. for (int i = Context::MIN_CONTEXT_SLOTS; i < length; ++i) { Add(function_context, HObjectAccess::ForContextSlot(i), - graph()->GetConstantUndefined()); + graph()->GetConstantUndefined(), + INITIALIZING_STORE); } return function_context; diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 89399db8e4..e0f6921b4d 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -3575,7 +3575,8 @@ void HAllocate::CreateFreeSpaceFiller(int32_t free_space_size) { filler_map->FinalizeUniqueness(); // TODO(titzer): should be init'd a'ready filler_map->InsertAfter(free_space_instr); HInstruction* store_map = HStoreNamedField::New(zone, context(), - free_space_instr, HObjectAccess::ForMap(), filler_map); + free_space_instr, HObjectAccess::ForMap(), filler_map, + INITIALIZING_STORE); store_map->SetFlag(HValue::kHasNoObservableSideEffects); store_map->InsertAfter(filler_map); @@ -3589,7 +3590,7 @@ void HAllocate::CreateFreeSpaceFiller(int32_t free_space_size) { HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset, Representation::Smi()); HStoreNamedField* store_size = HStoreNamedField::New(zone, context(), - free_space_instr, access, filler_size); + free_space_instr, access, filler_size, INITIALIZING_STORE); store_size->SetFlag(HValue::kHasNoObservableSideEffects); store_size->InsertAfter(filler_size); filler_free_space_size_ = store_size; @@ -3602,7 +3603,7 @@ void HAllocate::ClearNextMapWord(int offset) { HObjectAccess access = HObjectAccess::ForJSObjectOffset(offset); HStoreNamedField* clear_next_map = HStoreNamedField::New(zone, context(), this, access, - block()->graph()->GetConstant0()); + block()->graph()->GetConstant0(), INITIALIZING_STORE); clear_next_map->ClearAllSideEffects(); clear_next_map->InsertAfter(this); } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 138c617e17..f0b7be20a3 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -6494,15 +6494,19 @@ class HLoadKeyedGeneric V8_FINAL : public HTemplateInstruction<3> { // Indicates whether the store is a store to an entry that was previously // initialized or not. enum StoreFieldOrKeyedMode { + // This is a store of either an undefined value to a field or a hole/NaN to + // an entry of a newly allocated object. + PREINITIALIZING_STORE, + // The entry could be either previously initialized or not. INITIALIZING_STORE, + // At the time of this store it is guaranteed that the entry is already + // initialized. STORE_TO_INITIALIZED_ENTRY }; class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> { public: - DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*, - HObjectAccess, HValue*); DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*, HObjectAccess, HValue*, StoreFieldOrKeyedMode); @@ -6609,12 +6613,17 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> { HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val, - StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE) + StoreFieldOrKeyedMode store_mode) : access_(access), new_space_dominator_(NULL), write_barrier_mode_(UPDATE_WRITE_BARRIER), has_transition_(false), store_mode_(store_mode) { + // PREINITIALIZING_STORE is only used to mark stores that initialize a + // memory region resulting from HAllocate (possibly through an + // HInnerAllocatedObject). + ASSERT(store_mode != PREINITIALIZING_STORE || + obj->IsAllocate() || obj->IsInnerAllocatedObject()); SetOperandAt(0, obj); SetOperandAt(1, val); SetOperandAt(2, obj); @@ -6625,7 +6634,7 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> { HValue* new_space_dominator_; WriteBarrierMode write_barrier_mode_ : 1; bool has_transition_ : 1; - StoreFieldOrKeyedMode store_mode_ : 1; + StoreFieldOrKeyedMode store_mode_ : 2; }; @@ -6670,8 +6679,6 @@ class HStoreNamedGeneric V8_FINAL : public HTemplateInstruction<3> { class HStoreKeyed V8_FINAL : public HTemplateInstruction<3>, public ArrayInstructionInterface { public: - DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*, - ElementsKind); DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*, ElementsKind, StoreFieldOrKeyedMode); @@ -6791,7 +6798,7 @@ class HStoreKeyed V8_FINAL private: HStoreKeyed(HValue* obj, HValue* key, HValue* val, ElementsKind elements_kind, - StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE) + StoreFieldOrKeyedMode store_mode) : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false), @@ -6802,6 +6809,12 @@ class HStoreKeyed V8_FINAL SetOperandAt(1, key); SetOperandAt(2, val); + // PREINITIALIZING_STORE is only used to mark stores that initialize a + // memory region resulting from HAllocate (possibly through an + // HInnerAllocatedObject). + ASSERT(store_mode != PREINITIALIZING_STORE || + obj->IsAllocate() || obj->IsInnerAllocatedObject()); + ASSERT(store_mode != STORE_TO_INITIALIZED_ENTRY || elements_kind == FAST_SMI_ELEMENTS); @@ -6836,7 +6849,7 @@ class HStoreKeyed V8_FINAL uint32_t index_offset_; bool is_dehoisted_ : 1; bool is_uninitialized_ : 1; - StoreFieldOrKeyedMode store_mode_: 1; + StoreFieldOrKeyedMode store_mode_: 2; HValue* new_space_dominator_; }; diff --git a/src/hydrogen-load-elimination.cc b/src/hydrogen-load-elimination.cc index f2e993b18d..ca322ebc76 100644 --- a/src/hydrogen-load-elimination.cc +++ b/src/hydrogen-load-elimination.cc @@ -176,6 +176,10 @@ class HLoadEliminationTable : public ZoneObject { approx = approx->next_; } } + if (FLAG_trace_load_elimination) { + TRACE((" merge-to B%d\n", succ->block_id())); + Print(); + } return this; } @@ -208,6 +212,11 @@ class HLoadEliminationTable : public ZoneObject { // the stored values are the same), return NULL indicating that this store // instruction is redundant. Otherwise, return {instr}. HValue* store(HStoreNamedField* instr) { + if (instr->store_mode() == PREINITIALIZING_STORE) { + TRACE((" skipping preinitializing store\n")); + return instr; + } + int field = FieldOf(instr->access()); if (field < 0) return KillIfMisaligned(instr); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 142c921710..b2e0d00f96 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -1199,7 +1199,7 @@ void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { HValue* new_value = AddUncasted(old_value, graph()->GetConstant1()); new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow Add(reference, HObjectAccess::ForCounter(), - new_value); + new_value, STORE_TO_INITIALIZED_ENTRY); } } @@ -1337,14 +1337,15 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, new_length->ClearFlag(HValue::kCanOverflow); Add(object, HObjectAccess::ForArrayLength(kind), - new_length); + new_length, INITIALIZING_STORE); } if (is_store && kind == FAST_SMI_ELEMENTS) { HValue* checked_elements = environment()->Top(); // Write zero to ensure that the new element is initialized with some smi. - Add(checked_elements, key, graph()->GetConstant0(), kind); + Add(checked_elements, key, graph()->GetConstant0(), kind, + INITIALIZING_STORE); } length_checker.Else(); @@ -1421,7 +1422,8 @@ void HGraphBuilder::BuildTransitionElementsKind(HValue* object, if_builder.End(); } - Add(object, HObjectAccess::ForMap(), map); + Add(object, HObjectAccess::ForMap(), map, + INITIALIZING_STORE); } @@ -1808,10 +1810,14 @@ HValue* HGraphBuilder::BuildCreateConsString( // Initialize the cons string fields. Add(result, HObjectAccess::ForStringHashField(), - Add(String::kEmptyHashField)); - Add(result, HObjectAccess::ForStringLength(), length); - Add(result, HObjectAccess::ForConsStringFirst(), left); - Add(result, HObjectAccess::ForConsStringSecond(), right); + Add(String::kEmptyHashField), + INITIALIZING_STORE); + Add(result, HObjectAccess::ForStringLength(), length, + INITIALIZING_STORE); + Add(result, HObjectAccess::ForConsStringFirst(), left, + INITIALIZING_STORE); + Add(result, HObjectAccess::ForConsStringSecond(), right, + INITIALIZING_STORE); // Count the native string addition. AddIncrementCounter(isolate()->counters()->string_add_native()); @@ -1960,8 +1966,10 @@ HValue* HGraphBuilder::BuildUncheckedStringAdd( // Initialize the string fields. Add(result, HObjectAccess::ForStringHashField(), - Add(String::kEmptyHashField)); - Add(result, HObjectAccess::ForStringLength(), length); + Add(String::kEmptyHashField), + INITIALIZING_STORE); + Add(result, HObjectAccess::ForStringLength(), length, + INITIALIZING_STORE); // Copy characters to the result string. IfBuilder if_twobyte(this); @@ -2261,7 +2269,7 @@ void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, AddStoreMapConstant(elements, map); Add(elements, HObjectAccess::ForFixedArrayLength(), - capacity); + capacity, INITIALIZING_STORE); } @@ -2284,15 +2292,16 @@ HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, HValue* allocation_site_payload, HValue* length_field) { - Add(array, HObjectAccess::ForMap(), array_map); + Add(array, HObjectAccess::ForMap(), array_map, + INITIALIZING_STORE); HConstant* empty_fixed_array = Add(isolate()->factory()->empty_fixed_array()); HObjectAccess access = HObjectAccess::ForPropertiesPointer(); - Add(array, access, empty_fixed_array); + Add(array, access, empty_fixed_array, INITIALIZING_STORE); Add(array, HObjectAccess::ForArrayLength(elements_kind), - length_field); + length_field, INITIALIZING_STORE); if (mode == TRACK_ALLOCATION_SITE) { BuildCreateAllocationMemento( @@ -2306,7 +2315,8 @@ HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, HInnerAllocatedObject* elements = Add( array, Add(elements_location)); - Add(array, HObjectAccess::ForElementsPointer(), elements); + Add(array, HObjectAccess::ForElementsPointer(), elements, + INITIALIZING_STORE); return elements; } @@ -2397,7 +2407,7 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, length, new_capacity); Add(object, HObjectAccess::ForElementsPointer(), - new_elements); + new_elements, INITIALIZING_STORE); return new_elements; } @@ -2438,14 +2448,15 @@ void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, if (initial_capacity >= 0) { for (int i = 0; i < initial_capacity; i++) { HInstruction* key = Add(i); - Add(elements, key, hole, elements_kind); + Add(elements, key, hole, elements_kind, + PREINITIALIZING_STORE); } } else { LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); HValue* key = builder.BeginBody(from, to, Token::LT); - Add(elements, key, hole, elements_kind); + Add(elements, key, hole, elements_kind, PREINITIALIZING_STORE); builder.EndBody(); } @@ -2491,13 +2502,16 @@ void HGraphBuilder::BuildCopyElements(HValue* from_elements, HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind) ? Add(FixedDoubleArray::hole_nan_as_double()) : graph()->GetConstantHole(); - Add(to_elements, key, hole_constant, kind); + Add(to_elements, key, hole_constant, kind, + PREINITIALIZING_STORE); if_hole.Else(); - HStoreKeyed* store = Add(to_elements, key, element, kind); + HStoreKeyed* store = Add(to_elements, key, element, kind, + INITIALIZING_STORE); store->SetFlag(HValue::kAllowUndefinedAsNaN); if_hole.End(); } else { - HStoreKeyed* store = Add(to_elements, key, element, kind); + HStoreKeyed* store = Add(to_elements, key, element, kind, + INITIALIZING_STORE); store->SetFlag(HValue::kAllowUndefinedAsNaN); } @@ -2535,7 +2549,8 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, if ((i != JSArray::kElementsOffset) || (length == 0)) { HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); Add(object, access, - Add(boilerplate, access)); + Add(boilerplate, access), + INITIALIZING_STORE); } } @@ -2558,13 +2573,14 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, NOT_TENURED, FIXED_ARRAY_TYPE); } Add(object, HObjectAccess::ForElementsPointer(), - object_elements); + object_elements, INITIALIZING_STORE); // Copy the elements array header. for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); Add(object_elements, access, - Add(boilerplate_elements, access)); + Add(boilerplate_elements, access), + INITIALIZING_STORE); } // Copy the elements array contents. @@ -2575,7 +2591,8 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, HValue* key_constant = Add(i); HInstruction* value = Add(boilerplate_elements, key_constant, static_cast(NULL), kind); - Add(object_elements, key_constant, value, kind); + Add(object_elements, key_constant, value, kind, + INITIALIZING_STORE); } } @@ -2645,9 +2662,8 @@ void HGraphBuilder::BuildCreateAllocationMemento( AddStoreMapConstant( allocation_memento, isolate()->factory()->allocation_memento_map()); Add( - allocation_memento, - HObjectAccess::ForAllocationMementoSite(), - allocation_site); + allocation_memento, HObjectAccess::ForAllocationMementoSite(), + allocation_site, INITIALIZING_STORE); if (FLAG_allocation_site_pretenuring) { HValue* memento_create_count = Add( allocation_site, HObjectAccess::ForAllocationSiteOffset( @@ -2659,7 +2675,8 @@ void HGraphBuilder::BuildCreateAllocationMemento( memento_create_count->ClearFlag(HValue::kCanOverflow); HStoreNamedField* store = Add( allocation_site, HObjectAccess::ForAllocationSiteOffset( - AllocationSite::kPretenureCreateCountOffset), memento_create_count); + AllocationSite::kPretenureCreateCountOffset), memento_create_count, + INITIALIZING_STORE); // No write barrier needed to store a smi. store->SkipWriteBarrier(); } @@ -2874,7 +2891,7 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, Handle map) { return Add(object, HObjectAccess::ForMap(), - Add(map)); + Add(map), INITIALIZING_STORE); } @@ -5191,7 +5208,8 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { case FAST_DOUBLE_ELEMENTS: case FAST_HOLEY_DOUBLE_ELEMENTS: { HStoreKeyed* instr = Add(elements, key, value, - boilerplate_elements_kind); + boilerplate_elements_kind, + INITIALIZING_STORE); instr->SetUninitialized(uninitialized); break; } @@ -5272,10 +5290,10 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( HEAP_NUMBER_TYPE); AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); Add(heap_number, HObjectAccess::ForHeapNumberValue(), - value); + value, INITIALIZING_STORE); instr = New(checked_object->ActualValue(), heap_number_access, - heap_number); + heap_number, INITIALIZING_STORE); } else { // Already holds a HeapNumber; load the box and write its value field. HInstruction* heap_number = Add(checked_object, @@ -5283,7 +5301,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( heap_number->set_type(HType::HeapNumber()); instr = New(heap_number, HObjectAccess::ForHeapNumberValue(), - value); + value, STORE_TO_INITIALIZED_ENTRY); } } else { // This is a normal store. @@ -7663,7 +7681,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( } Add( checked_object, HObjectAccess::ForArrayLength(elements_kind), - reduced_length); + reduced_length, STORE_TO_INITIALIZED_ENTRY); if (!ast_context()->IsEffect()) Push(result); Add(expr->id(), REMOVABLE_SIMULATE); if (!ast_context()->IsEffect()) Drop(1); @@ -8084,7 +8102,7 @@ void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { for (int i = 0; i < argument_count; i++) { HValue* value = environment()->ExpressionStackAt(argument_count - i - 1); HValue* constant_i = Add(i); - Add(elements, constant_i, value, kind); + Add(elements, constant_i, value, kind, INITIALIZING_STORE); } } @@ -8200,21 +8218,21 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); Add(receiver, HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), - initial_map_value); + initial_map_value, INITIALIZING_STORE); HValue* empty_fixed_array = Add(factory->empty_fixed_array()); Add(receiver, HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), - empty_fixed_array); + empty_fixed_array, INITIALIZING_STORE); Add(receiver, HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), - empty_fixed_array); + empty_fixed_array, INITIALIZING_STORE); if (initial_map->inobject_properties() != 0) { HConstant* undefined = graph()->GetConstantUndefined(); for (int i = 0; i < initial_map->inobject_properties(); i++) { int property_offset = JSObject::kHeaderSize + i * kPointerSize; Add(receiver, HObjectAccess::ForJSObjectOffset(property_offset), - undefined); + undefined, PREINITIALIZING_STORE); } } } @@ -8299,27 +8317,29 @@ void HGraphBuilder::BuildArrayBufferViewInitialization( offset += kPointerSize) { Add(obj, HObjectAccess::ForJSObjectOffset(offset), - Add(static_cast(0))); + graph()->GetConstant0(), INITIALIZING_STORE); } Add( obj, - HObjectAccess::ForJSArrayBufferViewBuffer(), buffer); + HObjectAccess::ForJSArrayBufferViewBuffer(), buffer, INITIALIZING_STORE); Add( obj, HObjectAccess::ForJSArrayBufferViewByteOffset(), - byte_offset); + byte_offset, INITIALIZING_STORE); Add( obj, HObjectAccess::ForJSArrayBufferViewByteLength(), - byte_length); + byte_length, INITIALIZING_STORE); HObjectAccess weak_first_view_access = HObjectAccess::ForJSArrayBufferWeakFirstView(); Add(obj, HObjectAccess::ForJSArrayBufferViewWeakNext(), - Add(buffer, weak_first_view_access)); - Add(buffer, weak_first_view_access, obj); + Add(buffer, weak_first_view_access), + INITIALIZING_STORE); + Add( + buffer, weak_first_view_access, obj, INITIALIZING_STORE); } @@ -8409,7 +8429,7 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize( Add(obj, HObjectAccess::ForJSTypedArrayLength(), - length); + length, INITIALIZING_STORE); HValue* elements = Add( @@ -8420,9 +8440,7 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize( Handle external_array_map( isolate()->heap()->MapForExternalArrayType(array_type)); - Add(elements, - HObjectAccess::ForMap(), - Add(external_array_map)); + AddStoreMapConstant(elements, external_array_map); HValue* backing_store = Add( buffer, HObjectAccess::ForJSArrayBufferBackingStore()); @@ -8439,14 +8457,14 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize( typed_array_start = external_pointer; } - Add(elements, - HObjectAccess::ForExternalArrayExternalPointer(), - typed_array_start); - Add(elements, - HObjectAccess::ForFixedArrayLength(), - length); Add( - obj, HObjectAccess::ForElementsPointer(), elements); + elements, HObjectAccess::ForExternalArrayExternalPointer(), + typed_array_start, INITIALIZING_STORE); + Add( + elements, HObjectAccess::ForFixedArrayLength(), length, + INITIALIZING_STORE); + Add( + obj, HObjectAccess::ForElementsPointer(), elements, INITIALIZING_STORE); } if (!is_zero_byte_offset) { @@ -9686,7 +9704,7 @@ void HOptimizedGraphBuilder::BuildEmitObjectHeader( ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); HInstruction* properties = Add(properties_field); HObjectAccess access = HObjectAccess::ForPropertiesPointer(); - Add(object, access, properties); + Add(object, access, properties, INITIALIZING_STORE); if (boilerplate_object->IsJSArray()) { Handle boilerplate_array = @@ -9697,7 +9715,7 @@ void HOptimizedGraphBuilder::BuildEmitObjectHeader( ASSERT(boilerplate_array->length()->IsSmi()); Add(object, HObjectAccess::ForArrayLength( - boilerplate_array->GetElementsKind()), length); + boilerplate_array->GetElementsKind()), length, INITIALIZING_STORE); } } @@ -9713,7 +9731,7 @@ void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader( object_elements = Add(elements_field); } Add(object, HObjectAccess::ForElementsPointer(), - object_elements); + object_elements, INITIALIZING_STORE); } @@ -9749,7 +9767,7 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( HInstruction* result = BuildFastLiteral(value_object, site_context); site_context->ExitScope(current_site, value_object); - Add(object, access, result); + Add(object, access, result, INITIALIZING_STORE); } else { Representation representation = details.representation(); HInstruction* value_instruction; @@ -9767,7 +9785,7 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); Add(double_box, HObjectAccess::ForHeapNumberValue(), - Add(value)); + Add(value), INITIALIZING_STORE); value_instruction = double_box; } else if (representation.IsSmi() && value->IsUninitialized()) { value_instruction = graph()->GetConstant0(); @@ -9775,7 +9793,8 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( value_instruction = Add(value); } - Add(object, access, value_instruction); + Add(object, access, value_instruction, + INITIALIZING_STORE); } } @@ -9786,7 +9805,8 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( ASSERT(boilerplate_object->IsJSObject()); int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); - Add(object, access, value_instruction); + Add(object, access, value_instruction, + PREINITIALIZING_STORE); } } @@ -9826,7 +9846,8 @@ void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( static_cast(NULL), kind, ALLOW_RETURN_HOLE); HInstruction* store = Add(object_elements, key_constant, - value_instruction, kind); + value_instruction, kind, + INITIALIZING_STORE); store->SetFlag(HValue::kAllowUndefinedAsNaN); } } @@ -9849,13 +9870,15 @@ void HOptimizedGraphBuilder::BuildEmitFixedArray( HInstruction* result = BuildFastLiteral(value_object, site_context); site_context->ExitScope(current_site, value_object); - Add(object_elements, key_constant, result, kind); + Add(object_elements, key_constant, result, kind, + INITIALIZING_STORE); } else { HInstruction* value_instruction = Add(boilerplate_elements, key_constant, static_cast(NULL), kind, ALLOW_RETURN_HOLE); - Add(object_elements, key_constant, value_instruction, kind); + Add(object_elements, key_constant, value_instruction, kind, + INITIALIZING_STORE); } } } @@ -10239,7 +10262,8 @@ void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { // Create in-object property store to kValueOffset. set_current_block(if_js_value); Add(object, - HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); + HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value, + INITIALIZING_STORE); Goto(if_js_value, join); join->SetJoinId(call->id()); set_current_block(join); diff --git a/src/hydrogen.h b/src/hydrogen.h index d7579c4645..9303b964ef 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -1365,7 +1365,7 @@ class HGraphBuilder { HInstruction* AddLoadStringLength(HValue* string); HStoreNamedField* AddStoreMapNoWriteBarrier(HValue* object, HValue* map) { HStoreNamedField* store_map = Add( - object, HObjectAccess::ForMap(), map); + object, HObjectAccess::ForMap(), map, INITIALIZING_STORE); store_map->SkipWriteBarrier(); return store_map; } diff --git a/test/mjsunit/compiler/load-elimination.js b/test/mjsunit/compiler/load-elimination.js index 9475d4b3f6..e6a8245182 100644 --- a/test/mjsunit/compiler/load-elimination.js +++ b/test/mjsunit/compiler/load-elimination.js @@ -83,6 +83,15 @@ function test_transitioning_store2() { return a.x + a.y; } +var false_v = false; +function test_transitioning_store3() { + var o = new C(); + var v = o; + if (false_v) v = 0; + v.x = 20; + return o.x; +} + function killall() { try { } catch(e) { } } @@ -123,5 +132,6 @@ test(22, test_store_load); test(8, test_nonaliasing_store1); test(5, test_transitioning_store1); test(4, test_transitioning_store2); +test(20, test_transitioning_store3); test(22, test_store_load_kill); test(7, test_store_store);