Load elimination fix with a test case.
R=titzer@chromium.org, verwaest@chromium.org Review URL: https://codereview.chromium.org/143413019 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18884 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
a09a5a86b7
commit
d330d4801d
@ -446,7 +446,8 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
|
||||
for (int i = 0; i < object_size; i += kPointerSize) {
|
||||
HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
|
||||
Add<HStoreNamedField>(object, access,
|
||||
Add<HLoadNamedField>(boilerplate, access));
|
||||
Add<HLoadNamedField>(boilerplate, access),
|
||||
INITIALIZING_STORE);
|
||||
}
|
||||
|
||||
ASSERT(FLAG_allocation_site_pretenuring || (size == object_size));
|
||||
@ -483,25 +484,29 @@ HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() {
|
||||
Add<HStoreNamedField>(object,
|
||||
HObjectAccess::ForAllocationSiteOffset(
|
||||
AllocationSite::kTransitionInfoOffset),
|
||||
initial_elements_kind);
|
||||
initial_elements_kind,
|
||||
INITIALIZING_STORE);
|
||||
|
||||
// Unlike literals, constructed arrays don't have nested sites
|
||||
Add<HStoreNamedField>(object,
|
||||
HObjectAccess::ForAllocationSiteOffset(
|
||||
AllocationSite::kNestedSiteOffset),
|
||||
graph()->GetConstant0());
|
||||
graph()->GetConstant0(),
|
||||
INITIALIZING_STORE);
|
||||
|
||||
// Pretenuring calculation field.
|
||||
Add<HStoreNamedField>(object,
|
||||
HObjectAccess::ForAllocationSiteOffset(
|
||||
AllocationSite::kPretenureDataOffset),
|
||||
graph()->GetConstant0());
|
||||
graph()->GetConstant0(),
|
||||
INITIALIZING_STORE);
|
||||
|
||||
// Pretenuring memento creation count field.
|
||||
Add<HStoreNamedField>(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<CreateAllocationSiteStub>::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<HConstant>(
|
||||
@ -519,10 +525,10 @@ HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() {
|
||||
HObjectAccess::ForAllocationSiteList());
|
||||
store = Add<HStoreNamedField>(object,
|
||||
HObjectAccess::ForAllocationSiteOffset(AllocationSite::kWeakNextOffset),
|
||||
site);
|
||||
site, INITIALIZING_STORE);
|
||||
store->SkipWriteBarrier();
|
||||
Add<HStoreNamedField>(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<CreateAllocationSiteStub>::BuildCodeStub() {
|
||||
// a cell. (perhaps with a new instruction, HAssert).
|
||||
HInstruction* cell = GetParameter(0);
|
||||
HObjectAccess access = HObjectAccess::ForCellValue();
|
||||
store = Add<HStoreNamedField>(cell, access, object);
|
||||
store = Add<HStoreNamedField>(cell, access, object, INITIALIZING_STORE);
|
||||
store->SkipWriteBarrier();
|
||||
return cell;
|
||||
}
|
||||
@ -746,7 +752,7 @@ HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor(
|
||||
HInstruction* argument = Add<HAccessArgumentsAt>(
|
||||
argument_elements, checked_length, key);
|
||||
|
||||
Add<HStoreKeyed>(elements, key, argument, kind);
|
||||
Add<HStoreKeyed>(elements, key, argument, kind, INITIALIZING_STORE);
|
||||
builder.EndBody();
|
||||
return new_object;
|
||||
}
|
||||
@ -957,7 +963,8 @@ HValue* CodeStubGraphBuilder<BinaryOpICStub>::BuildCodeInitializedStub() {
|
||||
IfBuilder if_heap_number(this);
|
||||
if_heap_number.IfNot<HIsSmiAndBranch>(operand);
|
||||
if_heap_number.Then();
|
||||
Add<HStoreNamedField>(operand, HObjectAccess::ForHeapNumberValue(), result);
|
||||
Add<HStoreNamedField>(operand, HObjectAccess::ForHeapNumberValue(), result,
|
||||
INITIALIZING_STORE);
|
||||
Push(operand);
|
||||
if_heap_number.Else();
|
||||
Push(result);
|
||||
@ -1080,7 +1087,7 @@ HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
|
||||
builder.Then();
|
||||
builder.Deopt("Unexpected cell contents in global store");
|
||||
builder.Else();
|
||||
Add<HStoreNamedField>(cell, access, value);
|
||||
Add<HStoreNamedField>(cell, access, value, INITIALIZING_STORE);
|
||||
builder.End();
|
||||
}
|
||||
|
||||
@ -1144,12 +1151,12 @@ void CodeStubGraphBuilderBase::BuildInstallOptimizedCode(
|
||||
HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
Add<HStoreNamedField>(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<HStoreNamedField>(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<HStoreNamedField>(js_function,
|
||||
HObjectAccess::ForNextFunctionLinkPointer(),
|
||||
graph()->GetConstantUndefined());
|
||||
graph()->GetConstantUndefined(),
|
||||
INITIALIZING_STORE);
|
||||
HValue* code_object = Add<HLoadNamedField>(shared_info,
|
||||
HObjectAccess::ForCodeOffset());
|
||||
Add<HStoreCodeEntry>(js_function, code_object);
|
||||
@ -1294,22 +1302,23 @@ HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() {
|
||||
HInstruction* native_context = BuildGetNativeContext();
|
||||
HInstruction* map_slot_value = Add<HLoadNamedField>(native_context,
|
||||
HObjectAccess::ForContextSlot(map_index));
|
||||
Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value);
|
||||
Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value,
|
||||
INITIALIZING_STORE);
|
||||
|
||||
// Initialize the rest of the function.
|
||||
Add<HStoreNamedField>(js_function, HObjectAccess::ForPropertiesPointer(),
|
||||
empty_fixed_array);
|
||||
empty_fixed_array, INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(),
|
||||
empty_fixed_array);
|
||||
empty_fixed_array, INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(),
|
||||
empty_fixed_array);
|
||||
empty_fixed_array, INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(),
|
||||
graph()->GetConstantHole());
|
||||
graph()->GetConstantHole(), INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(js_function,
|
||||
HObjectAccess::ForSharedFunctionInfoPointer(),
|
||||
shared_info);
|
||||
shared_info, INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(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<FastNewContextStub>::BuildCodeStub() {
|
||||
isolate()->factory()->function_context_map());
|
||||
Add<HStoreNamedField>(function_context,
|
||||
HObjectAccess::ForFixedArrayLength(),
|
||||
Add<HConstant>(length));
|
||||
Add<HConstant>(length), INITIALIZING_STORE);
|
||||
|
||||
// Set up the fixed slots.
|
||||
Add<HStoreNamedField>(function_context,
|
||||
HObjectAccess::ForContextSlot(Context::CLOSURE_INDEX),
|
||||
function);
|
||||
function, INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(function_context,
|
||||
HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX),
|
||||
context());
|
||||
context(), INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(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<HLoadNamedField>(
|
||||
@ -1365,13 +1374,15 @@ HValue* CodeStubGraphBuilder<FastNewContextStub>::BuildCodeStub() {
|
||||
Add<HStoreNamedField>(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<HStoreNamedField>(function_context,
|
||||
HObjectAccess::ForContextSlot(i),
|
||||
graph()->GetConstantUndefined());
|
||||
graph()->GetConstantUndefined(),
|
||||
INITIALIZING_STORE);
|
||||
}
|
||||
|
||||
return function_context;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
160
src/hydrogen.cc
160
src/hydrogen.cc
@ -1199,7 +1199,7 @@ void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
|
||||
HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
|
||||
new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow
|
||||
Add<HStoreNamedField>(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<HStoreNamedField>(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<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind);
|
||||
Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind,
|
||||
INITIALIZING_STORE);
|
||||
}
|
||||
|
||||
length_checker.Else();
|
||||
@ -1421,7 +1422,8 @@ void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
|
||||
if_builder.End();
|
||||
}
|
||||
|
||||
Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
|
||||
Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map,
|
||||
INITIALIZING_STORE);
|
||||
}
|
||||
|
||||
|
||||
@ -1808,10 +1810,14 @@ HValue* HGraphBuilder::BuildCreateConsString(
|
||||
|
||||
// Initialize the cons string fields.
|
||||
Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
|
||||
Add<HConstant>(String::kEmptyHashField));
|
||||
Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
|
||||
Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
|
||||
Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
|
||||
Add<HConstant>(String::kEmptyHashField),
|
||||
INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length,
|
||||
INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left,
|
||||
INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(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<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
|
||||
Add<HConstant>(String::kEmptyHashField));
|
||||
Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
|
||||
Add<HConstant>(String::kEmptyHashField),
|
||||
INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(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<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
|
||||
capacity);
|
||||
capacity, INITIALIZING_STORE);
|
||||
}
|
||||
|
||||
|
||||
@ -2284,15 +2292,16 @@ HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
|
||||
HValue* allocation_site_payload,
|
||||
HValue* length_field) {
|
||||
|
||||
Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
|
||||
Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map,
|
||||
INITIALIZING_STORE);
|
||||
|
||||
HConstant* empty_fixed_array =
|
||||
Add<HConstant>(isolate()->factory()->empty_fixed_array());
|
||||
|
||||
HObjectAccess access = HObjectAccess::ForPropertiesPointer();
|
||||
Add<HStoreNamedField>(array, access, empty_fixed_array);
|
||||
Add<HStoreNamedField>(array, access, empty_fixed_array, INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(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<HInnerAllocatedObject>(
|
||||
array, Add<HConstant>(elements_location));
|
||||
Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements);
|
||||
Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements,
|
||||
INITIALIZING_STORE);
|
||||
return elements;
|
||||
}
|
||||
|
||||
@ -2397,7 +2407,7 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
|
||||
length, new_capacity);
|
||||
|
||||
Add<HStoreNamedField>(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<HConstant>(i);
|
||||
Add<HStoreKeyed>(elements, key, hole, elements_kind);
|
||||
Add<HStoreKeyed>(elements, key, hole, elements_kind,
|
||||
PREINITIALIZING_STORE);
|
||||
}
|
||||
} else {
|
||||
LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
|
||||
|
||||
HValue* key = builder.BeginBody(from, to, Token::LT);
|
||||
|
||||
Add<HStoreKeyed>(elements, key, hole, elements_kind);
|
||||
Add<HStoreKeyed>(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<HConstant>(FixedDoubleArray::hole_nan_as_double())
|
||||
: graph()->GetConstantHole();
|
||||
Add<HStoreKeyed>(to_elements, key, hole_constant, kind);
|
||||
Add<HStoreKeyed>(to_elements, key, hole_constant, kind,
|
||||
PREINITIALIZING_STORE);
|
||||
if_hole.Else();
|
||||
HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
|
||||
HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind,
|
||||
INITIALIZING_STORE);
|
||||
store->SetFlag(HValue::kAllowUndefinedAsNaN);
|
||||
if_hole.End();
|
||||
} else {
|
||||
HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
|
||||
HStoreKeyed* store = Add<HStoreKeyed>(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<HStoreNamedField>(object, access,
|
||||
Add<HLoadNamedField>(boilerplate, access));
|
||||
Add<HLoadNamedField>(boilerplate, access),
|
||||
INITIALIZING_STORE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2558,13 +2573,14 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate,
|
||||
NOT_TENURED, FIXED_ARRAY_TYPE);
|
||||
}
|
||||
Add<HStoreNamedField>(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<HStoreNamedField>(object_elements, access,
|
||||
Add<HLoadNamedField>(boilerplate_elements, access));
|
||||
Add<HLoadNamedField>(boilerplate_elements, access),
|
||||
INITIALIZING_STORE);
|
||||
}
|
||||
|
||||
// Copy the elements array contents.
|
||||
@ -2575,7 +2591,8 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate,
|
||||
HValue* key_constant = Add<HConstant>(i);
|
||||
HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant,
|
||||
static_cast<HValue*>(NULL), kind);
|
||||
Add<HStoreKeyed>(object_elements, key_constant, value, kind);
|
||||
Add<HStoreKeyed>(object_elements, key_constant, value, kind,
|
||||
INITIALIZING_STORE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2645,9 +2662,8 @@ void HGraphBuilder::BuildCreateAllocationMemento(
|
||||
AddStoreMapConstant(
|
||||
allocation_memento, isolate()->factory()->allocation_memento_map());
|
||||
Add<HStoreNamedField>(
|
||||
allocation_memento,
|
||||
HObjectAccess::ForAllocationMementoSite(),
|
||||
allocation_site);
|
||||
allocation_memento, HObjectAccess::ForAllocationMementoSite(),
|
||||
allocation_site, INITIALIZING_STORE);
|
||||
if (FLAG_allocation_site_pretenuring) {
|
||||
HValue* memento_create_count = Add<HLoadNamedField>(
|
||||
allocation_site, HObjectAccess::ForAllocationSiteOffset(
|
||||
@ -2659,7 +2675,8 @@ void HGraphBuilder::BuildCreateAllocationMemento(
|
||||
memento_create_count->ClearFlag(HValue::kCanOverflow);
|
||||
HStoreNamedField* store = Add<HStoreNamedField>(
|
||||
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> map) {
|
||||
return Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
|
||||
Add<HConstant>(map));
|
||||
Add<HConstant>(map), INITIALIZING_STORE);
|
||||
}
|
||||
|
||||
|
||||
@ -5191,7 +5208,8 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
case FAST_DOUBLE_ELEMENTS:
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS: {
|
||||
HStoreKeyed* instr = Add<HStoreKeyed>(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<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
|
||||
value);
|
||||
value, INITIALIZING_STORE);
|
||||
instr = New<HStoreNamedField>(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<HLoadNamedField>(checked_object,
|
||||
@ -5283,7 +5301,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
|
||||
heap_number->set_type(HType::HeapNumber());
|
||||
instr = New<HStoreNamedField>(heap_number,
|
||||
HObjectAccess::ForHeapNumberValue(),
|
||||
value);
|
||||
value, STORE_TO_INITIALIZED_ENTRY);
|
||||
}
|
||||
} else {
|
||||
// This is a normal store.
|
||||
@ -7663,7 +7681,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
||||
}
|
||||
Add<HStoreNamedField>(
|
||||
checked_object, HObjectAccess::ForArrayLength(elements_kind),
|
||||
reduced_length);
|
||||
reduced_length, STORE_TO_INITIALIZED_ENTRY);
|
||||
if (!ast_context()->IsEffect()) Push(result);
|
||||
Add<HSimulate>(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<HConstant>(i);
|
||||
Add<HStoreKeyed>(elements, constant_i, value, kind);
|
||||
Add<HStoreKeyed>(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<HStoreNamedField>(receiver,
|
||||
HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset),
|
||||
initial_map_value);
|
||||
initial_map_value, INITIALIZING_STORE);
|
||||
HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
|
||||
Add<HStoreNamedField>(receiver,
|
||||
HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset),
|
||||
empty_fixed_array);
|
||||
empty_fixed_array, INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(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<HStoreNamedField>(receiver,
|
||||
HObjectAccess::ForJSObjectOffset(property_offset),
|
||||
undefined);
|
||||
undefined, PREINITIALIZING_STORE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8299,27 +8317,29 @@ void HGraphBuilder::BuildArrayBufferViewInitialization(
|
||||
offset += kPointerSize) {
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSObjectOffset(offset),
|
||||
Add<HConstant>(static_cast<int32_t>(0)));
|
||||
graph()->GetConstant0(), INITIALIZING_STORE);
|
||||
}
|
||||
|
||||
Add<HStoreNamedField>(
|
||||
obj,
|
||||
HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
|
||||
HObjectAccess::ForJSArrayBufferViewBuffer(), buffer, INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(
|
||||
obj,
|
||||
HObjectAccess::ForJSArrayBufferViewByteOffset(),
|
||||
byte_offset);
|
||||
byte_offset, INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(
|
||||
obj,
|
||||
HObjectAccess::ForJSArrayBufferViewByteLength(),
|
||||
byte_length);
|
||||
byte_length, INITIALIZING_STORE);
|
||||
|
||||
HObjectAccess weak_first_view_access =
|
||||
HObjectAccess::ForJSArrayBufferWeakFirstView();
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSArrayBufferViewWeakNext(),
|
||||
Add<HLoadNamedField>(buffer, weak_first_view_access));
|
||||
Add<HStoreNamedField>(buffer, weak_first_view_access, obj);
|
||||
Add<HLoadNamedField>(buffer, weak_first_view_access),
|
||||
INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(
|
||||
buffer, weak_first_view_access, obj, INITIALIZING_STORE);
|
||||
}
|
||||
|
||||
|
||||
@ -8409,7 +8429,7 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
|
||||
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSTypedArrayLength(),
|
||||
length);
|
||||
length, INITIALIZING_STORE);
|
||||
|
||||
HValue* elements =
|
||||
Add<HAllocate>(
|
||||
@ -8420,9 +8440,7 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
|
||||
|
||||
Handle<Map> external_array_map(
|
||||
isolate()->heap()->MapForExternalArrayType(array_type));
|
||||
Add<HStoreNamedField>(elements,
|
||||
HObjectAccess::ForMap(),
|
||||
Add<HConstant>(external_array_map));
|
||||
AddStoreMapConstant(elements, external_array_map);
|
||||
|
||||
HValue* backing_store = Add<HLoadNamedField>(
|
||||
buffer, HObjectAccess::ForJSArrayBufferBackingStore());
|
||||
@ -8439,14 +8457,14 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
|
||||
typed_array_start = external_pointer;
|
||||
}
|
||||
|
||||
Add<HStoreNamedField>(elements,
|
||||
HObjectAccess::ForExternalArrayExternalPointer(),
|
||||
typed_array_start);
|
||||
Add<HStoreNamedField>(elements,
|
||||
HObjectAccess::ForFixedArrayLength(),
|
||||
length);
|
||||
Add<HStoreNamedField>(
|
||||
obj, HObjectAccess::ForElementsPointer(), elements);
|
||||
elements, HObjectAccess::ForExternalArrayExternalPointer(),
|
||||
typed_array_start, INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(
|
||||
elements, HObjectAccess::ForFixedArrayLength(), length,
|
||||
INITIALIZING_STORE);
|
||||
Add<HStoreNamedField>(
|
||||
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<HConstant>(properties_field);
|
||||
HObjectAccess access = HObjectAccess::ForPropertiesPointer();
|
||||
Add<HStoreNamedField>(object, access, properties);
|
||||
Add<HStoreNamedField>(object, access, properties, INITIALIZING_STORE);
|
||||
|
||||
if (boilerplate_object->IsJSArray()) {
|
||||
Handle<JSArray> boilerplate_array =
|
||||
@ -9697,7 +9715,7 @@ void HOptimizedGraphBuilder::BuildEmitObjectHeader(
|
||||
|
||||
ASSERT(boilerplate_array->length()->IsSmi());
|
||||
Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
|
||||
boilerplate_array->GetElementsKind()), length);
|
||||
boilerplate_array->GetElementsKind()), length, INITIALIZING_STORE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9713,7 +9731,7 @@ void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader(
|
||||
object_elements = Add<HConstant>(elements_field);
|
||||
}
|
||||
Add<HStoreNamedField>(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<HStoreNamedField>(object, access, result);
|
||||
Add<HStoreNamedField>(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<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(),
|
||||
Add<HConstant>(value));
|
||||
Add<HConstant>(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<HConstant>(value);
|
||||
}
|
||||
|
||||
Add<HStoreNamedField>(object, access, value_instruction);
|
||||
Add<HStoreNamedField>(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<HStoreNamedField>(object, access, value_instruction);
|
||||
Add<HStoreNamedField>(object, access, value_instruction,
|
||||
PREINITIALIZING_STORE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9826,7 +9846,8 @@ void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
|
||||
static_cast<HValue*>(NULL), kind,
|
||||
ALLOW_RETURN_HOLE);
|
||||
HInstruction* store = Add<HStoreKeyed>(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<HStoreKeyed>(object_elements, key_constant, result, kind);
|
||||
Add<HStoreKeyed>(object_elements, key_constant, result, kind,
|
||||
INITIALIZING_STORE);
|
||||
} else {
|
||||
HInstruction* value_instruction =
|
||||
Add<HLoadKeyed>(boilerplate_elements, key_constant,
|
||||
static_cast<HValue*>(NULL), kind,
|
||||
ALLOW_RETURN_HOLE);
|
||||
Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind);
|
||||
Add<HStoreKeyed>(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<HStoreNamedField>(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);
|
||||
|
@ -1365,7 +1365,7 @@ class HGraphBuilder {
|
||||
HInstruction* AddLoadStringLength(HValue* string);
|
||||
HStoreNamedField* AddStoreMapNoWriteBarrier(HValue* object, HValue* map) {
|
||||
HStoreNamedField* store_map = Add<HStoreNamedField>(
|
||||
object, HObjectAccess::ForMap(), map);
|
||||
object, HObjectAccess::ForMap(), map, INITIALIZING_STORE);
|
||||
store_map->SkipWriteBarrier();
|
||||
return store_map;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user