[crankshaft] Loads and stores to typed arrays have to reference the backing store holder
The backing store is only held alive indirectly via the array buffer referenced by the holder (typed array), so it's not enough to keep the elements alive (or even just the external pointer loaded from the elements). R=mstarzinger@chromium.org,bmeurer@chromium.org LOG=n BUG=v8:1827 Review URL: https://codereview.chromium.org/1493983004 Cr-Commit-Position: refs/heads/master@{#32644}
This commit is contained in:
parent
da8fd00e4c
commit
086d459847
@ -444,8 +444,8 @@ HValue* CodeStubGraphBuilder<FastCloneRegExpStub>::BuildCodeStub() {
|
||||
HValue* literals_array = Add<HLoadNamedField>(
|
||||
closure, nullptr, HObjectAccess::ForLiteralsPointer());
|
||||
HInstruction* boilerplate = Add<HLoadKeyed>(
|
||||
literals_array, literal_index, nullptr, FAST_ELEMENTS, NEVER_RETURN_HOLE,
|
||||
LiteralsArray::kOffsetToFirstLiteral - kHeapObjectTag);
|
||||
literals_array, literal_index, nullptr, nullptr, FAST_ELEMENTS,
|
||||
NEVER_RETURN_HOLE, LiteralsArray::kOffsetToFirstLiteral - kHeapObjectTag);
|
||||
|
||||
IfBuilder if_notundefined(this);
|
||||
if_notundefined.IfNot<HCompareObjectEqAndBranch>(
|
||||
@ -504,8 +504,8 @@ HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
|
||||
closure, nullptr, HObjectAccess::ForLiteralsPointer());
|
||||
|
||||
HInstruction* allocation_site = Add<HLoadKeyed>(
|
||||
literals_array, literal_index, nullptr, FAST_ELEMENTS, NEVER_RETURN_HOLE,
|
||||
LiteralsArray::kOffsetToFirstLiteral - kHeapObjectTag);
|
||||
literals_array, literal_index, nullptr, nullptr, FAST_ELEMENTS,
|
||||
NEVER_RETURN_HOLE, LiteralsArray::kOffsetToFirstLiteral - kHeapObjectTag);
|
||||
IfBuilder checker(this);
|
||||
checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site,
|
||||
undefined);
|
||||
@ -572,8 +572,8 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
|
||||
closure, nullptr, HObjectAccess::ForLiteralsPointer());
|
||||
|
||||
HInstruction* allocation_site = Add<HLoadKeyed>(
|
||||
literals_array, literal_index, nullptr, FAST_ELEMENTS, NEVER_RETURN_HOLE,
|
||||
LiteralsArray::kOffsetToFirstLiteral - kHeapObjectTag);
|
||||
literals_array, literal_index, nullptr, nullptr, FAST_ELEMENTS,
|
||||
NEVER_RETURN_HOLE, LiteralsArray::kOffsetToFirstLiteral - kHeapObjectTag);
|
||||
|
||||
IfBuilder checker(this);
|
||||
checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site,
|
||||
@ -702,7 +702,7 @@ HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() {
|
||||
|
||||
HInstruction* feedback_vector = GetParameter(0);
|
||||
HInstruction* slot = GetParameter(1);
|
||||
Add<HStoreKeyed>(feedback_vector, slot, object, FAST_ELEMENTS,
|
||||
Add<HStoreKeyed>(feedback_vector, slot, object, nullptr, FAST_ELEMENTS,
|
||||
INITIALIZING_STORE);
|
||||
return feedback_vector;
|
||||
}
|
||||
@ -734,7 +734,7 @@ HValue* CodeStubGraphBuilder<CreateWeakCellStub>::BuildCodeStub() {
|
||||
HInstruction* feedback_vector =
|
||||
GetParameter(CreateWeakCellDescriptor::kVectorIndex);
|
||||
HInstruction* slot = GetParameter(CreateWeakCellDescriptor::kSlotIndex);
|
||||
Add<HStoreKeyed>(feedback_vector, slot, object, FAST_ELEMENTS,
|
||||
Add<HStoreKeyed>(feedback_vector, slot, object, nullptr, FAST_ELEMENTS,
|
||||
INITIALIZING_STORE);
|
||||
return graph()->GetConstant0();
|
||||
}
|
||||
@ -890,8 +890,8 @@ HValue* CodeStubGraphBuilderBase::UnmappedCase(HValue* elements, HValue* key,
|
||||
HValue* value) {
|
||||
HValue* result = NULL;
|
||||
HInstruction* backing_store =
|
||||
Add<HLoadKeyed>(elements, graph()->GetConstant1(), nullptr, FAST_ELEMENTS,
|
||||
ALLOW_RETURN_HOLE);
|
||||
Add<HLoadKeyed>(elements, graph()->GetConstant1(), nullptr, nullptr,
|
||||
FAST_ELEMENTS, ALLOW_RETURN_HOLE);
|
||||
Add<HCheckMaps>(backing_store, isolate()->factory()->fixed_array_map());
|
||||
HValue* backing_store_length = Add<HLoadNamedField>(
|
||||
backing_store, nullptr, HObjectAccess::ForFixedArrayLength());
|
||||
@ -901,10 +901,10 @@ HValue* CodeStubGraphBuilderBase::UnmappedCase(HValue* elements, HValue* key,
|
||||
in_unmapped_range.Then();
|
||||
{
|
||||
if (value == NULL) {
|
||||
result = Add<HLoadKeyed>(backing_store, key, nullptr, FAST_HOLEY_ELEMENTS,
|
||||
NEVER_RETURN_HOLE);
|
||||
result = Add<HLoadKeyed>(backing_store, key, nullptr, nullptr,
|
||||
FAST_HOLEY_ELEMENTS, NEVER_RETURN_HOLE);
|
||||
} else {
|
||||
Add<HStoreKeyed>(backing_store, key, value, FAST_HOLEY_ELEMENTS);
|
||||
Add<HStoreKeyed>(backing_store, key, value, nullptr, FAST_HOLEY_ELEMENTS);
|
||||
}
|
||||
}
|
||||
in_unmapped_range.ElseDeopt(Deoptimizer::kOutsideOfRange);
|
||||
@ -961,8 +961,9 @@ HValue* CodeStubGraphBuilderBase::EmitKeyedSloppyArguments(HValue* receiver,
|
||||
in_range.Then();
|
||||
{
|
||||
HValue* index = AddUncasted<HAdd>(key, constant_two);
|
||||
HInstruction* mapped_index = Add<HLoadKeyed>(
|
||||
elements, index, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
|
||||
HInstruction* mapped_index =
|
||||
Add<HLoadKeyed>(elements, index, nullptr, nullptr, FAST_HOLEY_ELEMENTS,
|
||||
ALLOW_RETURN_HOLE);
|
||||
|
||||
IfBuilder is_valid(this);
|
||||
is_valid.IfNot<HCompareObjectEqAndBranch>(mapped_index,
|
||||
@ -973,15 +974,17 @@ HValue* CodeStubGraphBuilderBase::EmitKeyedSloppyArguments(HValue* receiver,
|
||||
// mapped_index is not the hole that it is indeed, a smi. An unnecessary
|
||||
// smi check is being emitted.
|
||||
HValue* the_context = Add<HLoadKeyed>(elements, graph()->GetConstant0(),
|
||||
nullptr, FAST_ELEMENTS);
|
||||
nullptr, nullptr, FAST_ELEMENTS);
|
||||
STATIC_ASSERT(Context::kHeaderSize == FixedArray::kHeaderSize);
|
||||
if (is_load) {
|
||||
HValue* result = Add<HLoadKeyed>(the_context, mapped_index, nullptr,
|
||||
FAST_ELEMENTS, ALLOW_RETURN_HOLE);
|
||||
HValue* result =
|
||||
Add<HLoadKeyed>(the_context, mapped_index, nullptr, nullptr,
|
||||
FAST_ELEMENTS, ALLOW_RETURN_HOLE);
|
||||
environment()->Push(result);
|
||||
} else {
|
||||
DCHECK(value != NULL);
|
||||
Add<HStoreKeyed>(the_context, mapped_index, value, FAST_ELEMENTS);
|
||||
Add<HStoreKeyed>(the_context, mapped_index, value, nullptr,
|
||||
FAST_ELEMENTS);
|
||||
environment()->Push(value);
|
||||
}
|
||||
}
|
||||
@ -1326,7 +1329,7 @@ HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor(
|
||||
HInstruction* argument = Add<HAccessArgumentsAt>(
|
||||
argument_elements, checked_length, key);
|
||||
|
||||
Add<HStoreKeyed>(elements, key, argument, kind);
|
||||
Add<HStoreKeyed>(elements, key, argument, nullptr, kind);
|
||||
builder.EndBody();
|
||||
return new_object;
|
||||
}
|
||||
@ -1939,8 +1942,8 @@ HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap(
|
||||
HValue* field_offset_value = Add<HConstant>(field_offset);
|
||||
field_slot = AddUncasted<HAdd>(iterator, field_offset_value);
|
||||
}
|
||||
HInstruction* field_entry =
|
||||
Add<HLoadKeyed>(optimized_map, field_slot, nullptr, FAST_ELEMENTS);
|
||||
HInstruction* field_entry = Add<HLoadKeyed>(optimized_map, field_slot,
|
||||
nullptr, nullptr, FAST_ELEMENTS);
|
||||
return field_entry;
|
||||
}
|
||||
|
||||
@ -2359,13 +2362,13 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
|
||||
Add<HConstant>(probe_base + KeyedLookupCache::kKeyIndex));
|
||||
key_index->ClearFlag(HValue::kCanOverflow);
|
||||
HValue* map_to_check =
|
||||
Add<HLoadKeyed>(cache_keys, map_index, nullptr, FAST_ELEMENTS,
|
||||
NEVER_RETURN_HOLE, 0);
|
||||
Add<HLoadKeyed>(cache_keys, map_index, nullptr, nullptr,
|
||||
FAST_ELEMENTS, NEVER_RETURN_HOLE, 0);
|
||||
lookup_if->If<HCompareObjectEqAndBranch>(map_to_check, map);
|
||||
lookup_if->And();
|
||||
HValue* key_to_check =
|
||||
Add<HLoadKeyed>(cache_keys, key_index, nullptr, FAST_ELEMENTS,
|
||||
NEVER_RETURN_HOLE, 0);
|
||||
Add<HLoadKeyed>(cache_keys, key_index, nullptr, nullptr,
|
||||
FAST_ELEMENTS, NEVER_RETURN_HOLE, 0);
|
||||
lookup_if->If<HCompareObjectEqAndBranch>(key_to_check, key);
|
||||
lookup_if->Then();
|
||||
{
|
||||
@ -2376,7 +2379,7 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
|
||||
HValue* index = AddUncasted<HAdd>(hash, Add<HConstant>(probe));
|
||||
index->ClearFlag(HValue::kCanOverflow);
|
||||
HValue* property_index =
|
||||
Add<HLoadKeyed>(cache_field_offsets, index, nullptr,
|
||||
Add<HLoadKeyed>(cache_field_offsets, index, nullptr, cache_keys,
|
||||
INT32_ELEMENTS, NEVER_RETURN_HOLE, 0);
|
||||
Push(property_index);
|
||||
}
|
||||
|
@ -2192,7 +2192,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
DCHECK(instr->representation().IsSmiOrTagged());
|
||||
obj = UseRegisterAtStart(instr->elements());
|
||||
}
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
|
||||
result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key, nullptr));
|
||||
} else {
|
||||
DCHECK(
|
||||
(instr->representation().IsInteger32() &&
|
||||
@ -2200,7 +2200,9 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
(instr->representation().IsDouble() &&
|
||||
IsDoubleOrFloatElementsKind(elements_kind)));
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
result = DefineAsRegister(
|
||||
new (zone()) LLoadKeyed(backing_store, key, backing_store_owner));
|
||||
}
|
||||
|
||||
bool needs_environment;
|
||||
@ -2265,7 +2267,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
}
|
||||
}
|
||||
|
||||
return new(zone()) LStoreKeyed(object, key, val);
|
||||
return new (zone()) LStoreKeyed(object, key, val, nullptr);
|
||||
}
|
||||
|
||||
DCHECK(
|
||||
@ -2277,7 +2279,8 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
LOperand* val = UseRegister(instr->value());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
return new(zone()) LStoreKeyed(backing_store, key, val);
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1602,15 +1602,17 @@ class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 3, 0> {
|
||||
public:
|
||||
LLoadKeyed(LOperand* elements, LOperand* key) {
|
||||
LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) {
|
||||
inputs_[0] = elements;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = backing_store_owner;
|
||||
}
|
||||
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* backing_store_owner() { return inputs_[2]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
@ -2149,12 +2151,14 @@ class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
|
||||
};
|
||||
|
||||
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 4, 0> {
|
||||
public:
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value) {
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value,
|
||||
LOperand* backing_store_owner) {
|
||||
inputs_[0] = object;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = value;
|
||||
inputs_[3] = backing_store_owner;
|
||||
}
|
||||
|
||||
bool is_fixed_typed_array() const {
|
||||
@ -2163,6 +2167,7 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
LOperand* backing_store_owner() { return inputs_[3]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
|
@ -1695,8 +1695,9 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
IsDoubleOrFloatElementsKind(instr->elements_kind())));
|
||||
|
||||
LOperand* temp = instr->key()->IsConstant() ? NULL : TempRegister();
|
||||
LInstruction* result = DefineAsRegister(
|
||||
new(zone()) LLoadKeyedExternal(elements, key, temp));
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
LInstruction* result = DefineAsRegister(new (zone()) LLoadKeyedExternal(
|
||||
elements, key, backing_store_owner, temp));
|
||||
if (elements_kind == UINT32_ELEMENTS &&
|
||||
!instr->CheckFlag(HInstruction::kUint32)) {
|
||||
result = AssignEnvironment(result);
|
||||
@ -2315,7 +2316,9 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
(instr->value()->representation().IsDouble() &&
|
||||
IsDoubleOrFloatElementsKind(instr->elements_kind())));
|
||||
DCHECK(instr->elements()->representation().IsExternal());
|
||||
return new(zone()) LStoreKeyedExternal(elements, key, val, temp);
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
return new (zone())
|
||||
LStoreKeyedExternal(elements, key, val, backing_store_owner, temp);
|
||||
|
||||
} else if (instr->value()->representation().IsDouble()) {
|
||||
DCHECK(instr->elements()->representation().IsTagged());
|
||||
|
@ -1679,16 +1679,18 @@ class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
|
||||
};
|
||||
|
||||
|
||||
template<int T>
|
||||
class LLoadKeyed : public LTemplateInstruction<1, 2, T> {
|
||||
template <int T>
|
||||
class LLoadKeyed : public LTemplateInstruction<1, 3, T> {
|
||||
public:
|
||||
LLoadKeyed(LOperand* elements, LOperand* key) {
|
||||
LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) {
|
||||
this->inputs_[0] = elements;
|
||||
this->inputs_[1] = key;
|
||||
this->inputs_[2] = backing_store_owner;
|
||||
}
|
||||
|
||||
LOperand* elements() { return this->inputs_[0]; }
|
||||
LOperand* key() { return this->inputs_[1]; }
|
||||
LOperand* backing_store_owner() { return this->inputs_[2]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return this->hydrogen()->elements_kind();
|
||||
}
|
||||
@ -1721,8 +1723,9 @@ class LLoadKeyed : public LTemplateInstruction<1, 2, T> {
|
||||
|
||||
class LLoadKeyedExternal: public LLoadKeyed<1> {
|
||||
public:
|
||||
LLoadKeyedExternal(LOperand* elements, LOperand* key, LOperand* temp) :
|
||||
LLoadKeyed<1>(elements, key) {
|
||||
LLoadKeyedExternal(LOperand* elements, LOperand* key,
|
||||
LOperand* backing_store_owner, LOperand* temp)
|
||||
: LLoadKeyed<1>(elements, key, backing_store_owner) {
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
@ -1734,8 +1737,8 @@ class LLoadKeyedExternal: public LLoadKeyed<1> {
|
||||
|
||||
class LLoadKeyedFixed: public LLoadKeyed<1> {
|
||||
public:
|
||||
LLoadKeyedFixed(LOperand* elements, LOperand* key, LOperand* temp) :
|
||||
LLoadKeyed<1>(elements, key) {
|
||||
LLoadKeyedFixed(LOperand* elements, LOperand* key, LOperand* temp)
|
||||
: LLoadKeyed<1>(elements, key, nullptr) {
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
@ -1747,8 +1750,8 @@ class LLoadKeyedFixed: public LLoadKeyed<1> {
|
||||
|
||||
class LLoadKeyedFixedDouble: public LLoadKeyed<1> {
|
||||
public:
|
||||
LLoadKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* temp) :
|
||||
LLoadKeyed<1>(elements, key) {
|
||||
LLoadKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* temp)
|
||||
: LLoadKeyed<1>(elements, key, nullptr) {
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
@ -2369,13 +2372,15 @@ class LStackCheck final : public LTemplateInstruction<0, 1, 0> {
|
||||
};
|
||||
|
||||
|
||||
template<int T>
|
||||
class LStoreKeyed : public LTemplateInstruction<0, 3, T> {
|
||||
template <int T>
|
||||
class LStoreKeyed : public LTemplateInstruction<0, 4, T> {
|
||||
public:
|
||||
LStoreKeyed(LOperand* elements, LOperand* key, LOperand* value) {
|
||||
LStoreKeyed(LOperand* elements, LOperand* key, LOperand* value,
|
||||
LOperand* backing_store_owner) {
|
||||
this->inputs_[0] = elements;
|
||||
this->inputs_[1] = key;
|
||||
this->inputs_[2] = value;
|
||||
this->inputs_[3] = backing_store_owner;
|
||||
}
|
||||
|
||||
bool is_external() const { return this->hydrogen()->is_external(); }
|
||||
@ -2388,6 +2393,7 @@ class LStoreKeyed : public LTemplateInstruction<0, 3, T> {
|
||||
LOperand* elements() { return this->inputs_[0]; }
|
||||
LOperand* key() { return this->inputs_[1]; }
|
||||
LOperand* value() { return this->inputs_[2]; }
|
||||
LOperand* backing_store_owner() { return this->inputs_[3]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return this->hydrogen()->elements_kind();
|
||||
}
|
||||
@ -2427,8 +2433,8 @@ class LStoreKeyed : public LTemplateInstruction<0, 3, T> {
|
||||
class LStoreKeyedExternal final : public LStoreKeyed<1> {
|
||||
public:
|
||||
LStoreKeyedExternal(LOperand* elements, LOperand* key, LOperand* value,
|
||||
LOperand* temp) :
|
||||
LStoreKeyed<1>(elements, key, value) {
|
||||
LOperand* backing_store_owner, LOperand* temp)
|
||||
: LStoreKeyed<1>(elements, key, value, backing_store_owner) {
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
@ -2441,8 +2447,8 @@ class LStoreKeyedExternal final : public LStoreKeyed<1> {
|
||||
class LStoreKeyedFixed final : public LStoreKeyed<1> {
|
||||
public:
|
||||
LStoreKeyedFixed(LOperand* elements, LOperand* key, LOperand* value,
|
||||
LOperand* temp) :
|
||||
LStoreKeyed<1>(elements, key, value) {
|
||||
LOperand* temp)
|
||||
: LStoreKeyed<1>(elements, key, value, nullptr) {
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
@ -2455,8 +2461,8 @@ class LStoreKeyedFixed final : public LStoreKeyed<1> {
|
||||
class LStoreKeyedFixedDouble final : public LStoreKeyed<1> {
|
||||
public:
|
||||
LStoreKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* value,
|
||||
LOperand* temp) :
|
||||
LStoreKeyed<1>(elements, key, value) {
|
||||
LOperand* temp)
|
||||
: LStoreKeyed<1>(elements, key, value, nullptr) {
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
|
@ -3543,7 +3543,7 @@ HValue* HLoadKeyedGeneric::Canonicalize() {
|
||||
HInstruction* index = HLoadKeyed::New(
|
||||
block()->graph()->isolate(), block()->graph()->zone(),
|
||||
block()->graph()->GetInvalidContext(), index_cache, key_load->key(),
|
||||
key_load->key(), key_load->elements_kind());
|
||||
key_load->key(), nullptr, key_load->elements_kind());
|
||||
map_check->InsertBefore(this);
|
||||
index->InsertBefore(this);
|
||||
return Prepend(new(block()->zone()) HLoadFieldByIndex(
|
||||
|
@ -926,6 +926,12 @@ std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
|
||||
return new (zone) I(p1, p2, p3, p4, p5, p6); \
|
||||
}
|
||||
|
||||
#define DECLARE_INSTRUCTION_FACTORY_P7(I, P1, P2, P3, P4, P5, P6, P7) \
|
||||
static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
|
||||
P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { \
|
||||
return new (zone) I(p1, p2, p3, p4, p5, p6, p7); \
|
||||
}
|
||||
|
||||
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
|
||||
static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
|
||||
return new (zone) I(context); \
|
||||
@ -6498,14 +6504,14 @@ enum LoadKeyedHoleMode {
|
||||
};
|
||||
|
||||
|
||||
class HLoadKeyed final : public HTemplateInstruction<3>,
|
||||
class HLoadKeyed final : public HTemplateInstruction<4>,
|
||||
public ArrayInstructionInterface {
|
||||
public:
|
||||
DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
|
||||
DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
|
||||
ElementsKind);
|
||||
DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
|
||||
DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
|
||||
ElementsKind, LoadKeyedHoleMode);
|
||||
DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*,
|
||||
DECLARE_INSTRUCTION_FACTORY_P7(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
|
||||
ElementsKind, LoadKeyedHoleMode, int);
|
||||
|
||||
bool is_fixed_typed_array() const {
|
||||
@ -6518,6 +6524,11 @@ class HLoadKeyed final : public HTemplateInstruction<3>,
|
||||
return OperandAt(2);
|
||||
}
|
||||
bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
|
||||
HValue* backing_store_owner() const {
|
||||
DCHECK(HasBackingStoreOwner());
|
||||
return OperandAt(3);
|
||||
}
|
||||
bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
|
||||
uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
|
||||
bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
|
||||
HValue* GetKey() override { return key(); }
|
||||
@ -6548,7 +6559,12 @@ class HLoadKeyed final : public HTemplateInstruction<3>,
|
||||
return ArrayInstructionInterface::KeyedAccessIndexRequirement(
|
||||
OperandAt(1)->representation());
|
||||
}
|
||||
return Representation::None();
|
||||
if (index == 2) {
|
||||
return Representation::None();
|
||||
}
|
||||
DCHECK_EQ(3, index);
|
||||
return HasBackingStoreOwner() ? Representation::Tagged()
|
||||
: Representation::None();
|
||||
}
|
||||
|
||||
Representation observed_input_representation(int index) override {
|
||||
@ -6576,7 +6592,7 @@ class HLoadKeyed final : public HTemplateInstruction<3>,
|
||||
|
||||
private:
|
||||
HLoadKeyed(HValue* obj, HValue* key, HValue* dependency,
|
||||
ElementsKind elements_kind,
|
||||
HValue* backing_store_owner, ElementsKind elements_kind,
|
||||
LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
|
||||
int offset = kDefaultKeyedHeaderOffsetSentinel)
|
||||
: bit_field_(0) {
|
||||
@ -6589,7 +6605,9 @@ class HLoadKeyed final : public HTemplateInstruction<3>,
|
||||
|
||||
SetOperandAt(0, obj);
|
||||
SetOperandAt(1, key);
|
||||
SetOperandAt(2, dependency != NULL ? dependency : obj);
|
||||
SetOperandAt(2, dependency != nullptr ? dependency : obj);
|
||||
SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
|
||||
DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
|
||||
|
||||
if (!is_fixed_typed_array()) {
|
||||
// I can detect the case between storing double (holey and fast) and
|
||||
@ -6942,15 +6960,16 @@ class HStoreNamedGeneric final : public HTemplateInstruction<3> {
|
||||
};
|
||||
|
||||
|
||||
class HStoreKeyed final : public HTemplateInstruction<3>,
|
||||
class HStoreKeyed final : public HTemplateInstruction<4>,
|
||||
public ArrayInstructionInterface {
|
||||
public:
|
||||
DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
|
||||
ElementsKind);
|
||||
DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
|
||||
ElementsKind, StoreFieldOrKeyedMode);
|
||||
HValue*, ElementsKind);
|
||||
DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
|
||||
ElementsKind, StoreFieldOrKeyedMode, int);
|
||||
HValue*, ElementsKind, StoreFieldOrKeyedMode);
|
||||
DECLARE_INSTRUCTION_FACTORY_P7(HStoreKeyed, HValue*, HValue*, HValue*,
|
||||
HValue*, ElementsKind, StoreFieldOrKeyedMode,
|
||||
int);
|
||||
|
||||
Representation RequiredInputRepresentation(int index) override {
|
||||
// kind_fast: tagged[int32] = tagged
|
||||
@ -6964,10 +6983,13 @@ class HStoreKeyed final : public HTemplateInstruction<3>,
|
||||
} else if (index == 1) {
|
||||
return ArrayInstructionInterface::KeyedAccessIndexRequirement(
|
||||
OperandAt(1)->representation());
|
||||
} else if (index == 2) {
|
||||
return RequiredValueRepresentation(elements_kind(), store_mode());
|
||||
}
|
||||
|
||||
DCHECK_EQ(index, 2);
|
||||
return RequiredValueRepresentation(elements_kind(), store_mode());
|
||||
DCHECK_EQ(3, index);
|
||||
return HasBackingStoreOwner() ? Representation::Tagged()
|
||||
: Representation::None();
|
||||
}
|
||||
|
||||
static Representation RequiredValueRepresentation(
|
||||
@ -6996,7 +7018,7 @@ class HStoreKeyed final : public HTemplateInstruction<3>,
|
||||
}
|
||||
|
||||
Representation observed_input_representation(int index) override {
|
||||
if (index < 2) return RequiredInputRepresentation(index);
|
||||
if (index != 2) return RequiredInputRepresentation(index);
|
||||
if (IsUninitialized()) {
|
||||
return Representation::None();
|
||||
}
|
||||
@ -7010,6 +7032,11 @@ class HStoreKeyed final : public HTemplateInstruction<3>,
|
||||
HValue* elements() const { return OperandAt(0); }
|
||||
HValue* key() const { return OperandAt(1); }
|
||||
HValue* value() const { return OperandAt(2); }
|
||||
HValue* backing_store_owner() const {
|
||||
DCHECK(HasBackingStoreOwner());
|
||||
return OperandAt(3);
|
||||
}
|
||||
bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
|
||||
bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
|
||||
StoreFieldOrKeyedMode store_mode() const {
|
||||
return StoreModeField::decode(bit_field_);
|
||||
@ -7065,7 +7092,8 @@ class HStoreKeyed final : public HTemplateInstruction<3>,
|
||||
DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
|
||||
|
||||
private:
|
||||
HStoreKeyed(HValue* obj, HValue* key, HValue* val, ElementsKind elements_kind,
|
||||
HStoreKeyed(HValue* obj, HValue* key, HValue* val,
|
||||
HValue* backing_store_owner, ElementsKind elements_kind,
|
||||
StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
|
||||
int offset = kDefaultKeyedHeaderOffsetSentinel)
|
||||
: base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
|
||||
@ -7079,6 +7107,8 @@ class HStoreKeyed final : public HTemplateInstruction<3>,
|
||||
SetOperandAt(0, obj);
|
||||
SetOperandAt(1, key);
|
||||
SetOperandAt(2, val);
|
||||
SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
|
||||
DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
|
||||
|
||||
if (IsFastObjectElementsKind(elements_kind)) {
|
||||
SetFlag(kTrackSideEffectDominators);
|
||||
|
@ -1372,7 +1372,8 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(
|
||||
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(), nullptr,
|
||||
kind);
|
||||
}
|
||||
|
||||
length_checker.Else();
|
||||
@ -1676,7 +1677,7 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
|
||||
LanguageMode language_mode) {
|
||||
HValue* capacity =
|
||||
Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
|
||||
nullptr, FAST_ELEMENTS);
|
||||
nullptr, nullptr, FAST_ELEMENTS);
|
||||
|
||||
HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
|
||||
mask->ChangeRepresentation(Representation::Integer32());
|
||||
@ -1707,7 +1708,7 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
|
||||
key_index->ClearFlag(HValue::kCanOverflow);
|
||||
|
||||
HValue* candidate_key =
|
||||
Add<HLoadKeyed>(elements, key_index, nullptr, FAST_ELEMENTS);
|
||||
Add<HLoadKeyed>(elements, key_index, nullptr, nullptr, FAST_ELEMENTS);
|
||||
IfBuilder if_undefined(this);
|
||||
if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
|
||||
graph()->GetConstantUndefined());
|
||||
@ -1750,7 +1751,7 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
|
||||
if_update_with_internalized.Then();
|
||||
// Replace a key that is a non-internalized string by the equivalent
|
||||
// internalized string for faster further lookups.
|
||||
Add<HStoreKeyed>(elements, key_index, key, FAST_ELEMENTS);
|
||||
Add<HStoreKeyed>(elements, key_index, key, nullptr, FAST_ELEMENTS);
|
||||
if_update_with_internalized.Else();
|
||||
|
||||
if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
|
||||
@ -1763,8 +1764,8 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
|
||||
HValue* details_index =
|
||||
AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
|
||||
details_index->ClearFlag(HValue::kCanOverflow);
|
||||
HValue* details =
|
||||
Add<HLoadKeyed>(elements, details_index, nullptr, FAST_ELEMENTS);
|
||||
HValue* details = Add<HLoadKeyed>(elements, details_index, nullptr, nullptr,
|
||||
FAST_ELEMENTS);
|
||||
int details_mask = PropertyDetails::TypeField::kMask;
|
||||
details = AddUncasted<HBitwise>(Token::BIT_AND, details,
|
||||
Add<HConstant>(details_mask));
|
||||
@ -1775,7 +1776,8 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
|
||||
HValue* result_index =
|
||||
AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
|
||||
result_index->ClearFlag(HValue::kCanOverflow);
|
||||
Push(Add<HLoadKeyed>(elements, result_index, nullptr, FAST_ELEMENTS));
|
||||
Push(Add<HLoadKeyed>(elements, result_index, nullptr, nullptr,
|
||||
FAST_ELEMENTS));
|
||||
details_compare.Else();
|
||||
Add<HPushArguments>(receiver, key);
|
||||
Push(Add<HCallRuntime>(
|
||||
@ -1945,7 +1947,7 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
|
||||
// Load the key.
|
||||
HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
|
||||
HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
|
||||
FAST_ELEMENTS, ALLOW_RETURN_HOLE);
|
||||
nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE);
|
||||
|
||||
// Check if object == key.
|
||||
IfBuilder if_objectiskey(this);
|
||||
@ -1980,8 +1982,9 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
|
||||
|
||||
// Load the key.
|
||||
HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
|
||||
HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
|
||||
FAST_ELEMENTS, ALLOW_RETURN_HOLE);
|
||||
HValue* key =
|
||||
Add<HLoadKeyed>(number_string_cache, key_index, nullptr, nullptr,
|
||||
FAST_ELEMENTS, ALLOW_RETURN_HOLE);
|
||||
|
||||
// Check if the key is a heap number and compare it with the object.
|
||||
IfBuilder if_keyisnotsmi(this);
|
||||
@ -2033,7 +2036,7 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
|
||||
// Load the value in case of cache hit.
|
||||
HValue* key_index = Pop();
|
||||
HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
|
||||
Push(Add<HLoadKeyed>(number_string_cache, value_index, nullptr,
|
||||
Push(Add<HLoadKeyed>(number_string_cache, value_index, nullptr, nullptr,
|
||||
FAST_ELEMENTS, ALLOW_RETURN_HOLE));
|
||||
}
|
||||
if_found.Else();
|
||||
@ -2117,7 +2120,7 @@ HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
|
||||
|
||||
// Determine the initial map for the global constructor.
|
||||
HValue* constructor = Add<HLoadKeyed>(native_context, constructor_index,
|
||||
nullptr, FAST_ELEMENTS);
|
||||
nullptr, nullptr, FAST_ELEMENTS);
|
||||
HValue* constructor_initial_map = Add<HLoadNamedField>(
|
||||
constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
|
||||
// Allocate and initialize a JSValue wrapper.
|
||||
@ -2588,7 +2591,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
||||
key, graph()->GetConstant0(), Token::GTE);
|
||||
negative_checker.Then();
|
||||
HInstruction* result = AddElementAccess(
|
||||
backing_store, key, val, bounds_check, elements_kind, access_type);
|
||||
backing_store, key, val, bounds_check, checked_object->ActualValue(),
|
||||
elements_kind, access_type);
|
||||
negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered);
|
||||
negative_checker.End();
|
||||
length_checker.End();
|
||||
@ -2596,9 +2600,9 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
||||
} else {
|
||||
DCHECK(store_mode == STANDARD_STORE);
|
||||
checked_key = Add<HBoundsCheck>(key, length);
|
||||
return AddElementAccess(
|
||||
backing_store, checked_key, val,
|
||||
checked_object, elements_kind, access_type);
|
||||
return AddElementAccess(backing_store, checked_key, val, checked_object,
|
||||
checked_object->ActualValue(), elements_kind,
|
||||
access_type);
|
||||
}
|
||||
}
|
||||
DCHECK(fast_smi_only_elements ||
|
||||
@ -2637,7 +2641,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
||||
}
|
||||
}
|
||||
}
|
||||
return AddElementAccess(elements, checked_key, val, checked_object,
|
||||
return AddElementAccess(elements, checked_key, val, checked_object, nullptr,
|
||||
elements_kind, access_type, load_mode);
|
||||
}
|
||||
|
||||
@ -2800,26 +2804,23 @@ void HGraphBuilder::BuildJSArrayHeader(HValue* array,
|
||||
|
||||
|
||||
HInstruction* HGraphBuilder::AddElementAccess(
|
||||
HValue* elements,
|
||||
HValue* checked_key,
|
||||
HValue* val,
|
||||
HValue* dependency,
|
||||
ElementsKind elements_kind,
|
||||
PropertyAccessType access_type,
|
||||
LoadKeyedHoleMode load_mode) {
|
||||
HValue* elements, HValue* checked_key, HValue* val, HValue* dependency,
|
||||
HValue* backing_store_owner, ElementsKind elements_kind,
|
||||
PropertyAccessType access_type, LoadKeyedHoleMode load_mode) {
|
||||
if (access_type == STORE) {
|
||||
DCHECK(val != NULL);
|
||||
if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
|
||||
val = Add<HClampToUint8>(val);
|
||||
}
|
||||
return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
|
||||
STORE_TO_INITIALIZED_ENTRY);
|
||||
return Add<HStoreKeyed>(elements, checked_key, val, backing_store_owner,
|
||||
elements_kind, STORE_TO_INITIALIZED_ENTRY);
|
||||
}
|
||||
|
||||
DCHECK(access_type == LOAD);
|
||||
DCHECK(val == NULL);
|
||||
HLoadKeyed* load = Add<HLoadKeyed>(
|
||||
elements, checked_key, dependency, elements_kind, load_mode);
|
||||
HLoadKeyed* load =
|
||||
Add<HLoadKeyed>(elements, checked_key, dependency, backing_store_owner,
|
||||
elements_kind, load_mode);
|
||||
if (elements_kind == UINT32_ELEMENTS) {
|
||||
graph()->RecordUint32Instruction(load);
|
||||
}
|
||||
@ -2920,7 +2921,7 @@ void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
|
||||
if (initial_capacity >= 0) {
|
||||
for (int i = 0; i < initial_capacity; i++) {
|
||||
HInstruction* key = Add<HConstant>(i);
|
||||
Add<HStoreKeyed>(elements, key, value, elements_kind);
|
||||
Add<HStoreKeyed>(elements, key, value, nullptr, elements_kind);
|
||||
}
|
||||
} else {
|
||||
// Carefully loop backwards so that the "from" remains live through the loop
|
||||
@ -2934,7 +2935,7 @@ void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
|
||||
HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
|
||||
adjusted_key->ClearFlag(HValue::kCanOverflow);
|
||||
|
||||
Add<HStoreKeyed>(elements, adjusted_key, value, elements_kind);
|
||||
Add<HStoreKeyed>(elements, adjusted_key, value, nullptr, elements_kind);
|
||||
|
||||
builder.EndBody();
|
||||
}
|
||||
@ -2977,9 +2978,10 @@ void HGraphBuilder::BuildCopyProperties(HValue* from_properties,
|
||||
key = AddUncasted<HSub>(key, graph()->GetConstant1());
|
||||
key->ClearFlag(HValue::kCanOverflow);
|
||||
|
||||
HValue* element = Add<HLoadKeyed>(from_properties, key, nullptr, kind);
|
||||
HValue* element =
|
||||
Add<HLoadKeyed>(from_properties, key, nullptr, nullptr, kind);
|
||||
|
||||
Add<HStoreKeyed>(to_properties, key, element, kind);
|
||||
Add<HStoreKeyed>(to_properties, key, element, nullptr, kind);
|
||||
|
||||
builder.EndBody();
|
||||
}
|
||||
@ -3016,9 +3018,10 @@ void HGraphBuilder::BuildCopyElements(HValue* from_elements,
|
||||
// Unroll the loop for small elements kinds.
|
||||
for (int i = 0; i < constant_capacity; i++) {
|
||||
HValue* key_constant = Add<HConstant>(i);
|
||||
HInstruction* value = Add<HLoadKeyed>(from_elements, key_constant,
|
||||
nullptr, from_elements_kind);
|
||||
Add<HStoreKeyed>(to_elements, key_constant, value, to_elements_kind);
|
||||
HInstruction* value = Add<HLoadKeyed>(
|
||||
from_elements, key_constant, nullptr, nullptr, from_elements_kind);
|
||||
Add<HStoreKeyed>(to_elements, key_constant, value, nullptr,
|
||||
to_elements_kind);
|
||||
}
|
||||
} else {
|
||||
if (!pre_fill_with_holes &&
|
||||
@ -3035,7 +3038,7 @@ void HGraphBuilder::BuildCopyElements(HValue* from_elements,
|
||||
key = AddUncasted<HSub>(key, graph()->GetConstant1());
|
||||
key->ClearFlag(HValue::kCanOverflow);
|
||||
|
||||
HValue* element = Add<HLoadKeyed>(from_elements, key, nullptr,
|
||||
HValue* element = Add<HLoadKeyed>(from_elements, key, nullptr, nullptr,
|
||||
from_elements_kind, ALLOW_RETURN_HOLE);
|
||||
|
||||
ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
|
||||
@ -3050,13 +3053,15 @@ void HGraphBuilder::BuildCopyElements(HValue* from_elements,
|
||||
HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
|
||||
? Add<HConstant>(HConstant::kHoleNaN)
|
||||
: graph()->GetConstantHole();
|
||||
Add<HStoreKeyed>(to_elements, key, hole_constant, kind);
|
||||
Add<HStoreKeyed>(to_elements, key, hole_constant, nullptr, kind);
|
||||
if_hole.Else();
|
||||
HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
|
||||
HStoreKeyed* store =
|
||||
Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
|
||||
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, nullptr, kind);
|
||||
store->SetFlag(HValue::kAllowUndefinedAsNaN);
|
||||
}
|
||||
|
||||
@ -3336,7 +3341,8 @@ HInstruction* HGraphBuilder::BuildGetArrayFunction() {
|
||||
HInstruction* native_context = BuildGetNativeContext();
|
||||
HInstruction* index =
|
||||
Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
|
||||
return Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS);
|
||||
return Add<HLoadKeyed>(native_context, index, nullptr, nullptr,
|
||||
FAST_ELEMENTS);
|
||||
}
|
||||
|
||||
|
||||
@ -3424,12 +3430,12 @@ HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
|
||||
HInstruction* index = builder()->Add<HConstant>(
|
||||
static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
|
||||
|
||||
HInstruction* map_array =
|
||||
builder()->Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS);
|
||||
HInstruction* map_array = builder()->Add<HLoadKeyed>(
|
||||
native_context, index, nullptr, nullptr, FAST_ELEMENTS);
|
||||
|
||||
HInstruction* kind_index = builder()->Add<HConstant>(kind_);
|
||||
|
||||
return builder()->Add<HLoadKeyed>(map_array, kind_index, nullptr,
|
||||
return builder()->Add<HLoadKeyed>(map_array, kind_index, nullptr, nullptr,
|
||||
FAST_ELEMENTS);
|
||||
}
|
||||
|
||||
@ -5379,7 +5385,7 @@ void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
|
||||
|
||||
HValue* key =
|
||||
Add<HLoadKeyed>(environment()->ExpressionStackAt(2), // Enum cache.
|
||||
index, index, FAST_ELEMENTS);
|
||||
index, index, nullptr, FAST_ELEMENTS);
|
||||
|
||||
if (fast) {
|
||||
// Check if the expected map still matches that of the enumerable.
|
||||
@ -6087,7 +6093,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
case FAST_DOUBLE_ELEMENTS:
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS: {
|
||||
HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value,
|
||||
HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, nullptr,
|
||||
boilerplate_elements_kind);
|
||||
instr->SetUninitialized(uninitialized);
|
||||
break;
|
||||
@ -8851,16 +8857,16 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
||||
elements_kind, length);
|
||||
}
|
||||
reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
|
||||
result = AddElementAccess(elements, reduced_length, NULL,
|
||||
bounds_check, elements_kind, LOAD);
|
||||
result = AddElementAccess(elements, reduced_length, nullptr,
|
||||
bounds_check, nullptr, elements_kind, LOAD);
|
||||
HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
|
||||
? graph()->GetConstantHole()
|
||||
: Add<HConstant>(HConstant::kHoleNaN);
|
||||
if (IsFastSmiOrObjectElementsKind(elements_kind)) {
|
||||
elements_kind = FAST_HOLEY_ELEMENTS;
|
||||
}
|
||||
AddElementAccess(
|
||||
elements, reduced_length, hole, bounds_check, elements_kind, STORE);
|
||||
AddElementAccess(elements, reduced_length, hole, bounds_check, nullptr,
|
||||
elements_kind, STORE);
|
||||
Add<HStoreNamedField>(
|
||||
checked_object, HObjectAccess::ForArrayLength(elements_kind),
|
||||
reduced_length, STORE_TO_INITIALIZED_ENTRY);
|
||||
@ -8985,8 +8991,8 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
||||
{
|
||||
// Remember the result.
|
||||
if (!ast_context()->IsEffect()) {
|
||||
Push(AddElementAccess(elements, graph()->GetConstant0(), NULL,
|
||||
lengthiszero, kind, LOAD));
|
||||
Push(AddElementAccess(elements, graph()->GetConstant0(), nullptr,
|
||||
lengthiszero, nullptr, kind, LOAD));
|
||||
}
|
||||
|
||||
// Compute the new length.
|
||||
@ -9003,10 +9009,11 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
||||
key->ClearFlag(HValue::kCanOverflow);
|
||||
ElementsKind copy_kind =
|
||||
kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
|
||||
HValue* element = AddUncasted<HLoadKeyed>(
|
||||
elements, key, lengthiszero, copy_kind, ALLOW_RETURN_HOLE);
|
||||
HStoreKeyed* store =
|
||||
Add<HStoreKeyed>(elements, new_key, element, copy_kind);
|
||||
HValue* element =
|
||||
AddUncasted<HLoadKeyed>(elements, key, lengthiszero, nullptr,
|
||||
copy_kind, ALLOW_RETURN_HOLE);
|
||||
HStoreKeyed* store = Add<HStoreKeyed>(elements, new_key, element,
|
||||
nullptr, copy_kind);
|
||||
store->SetFlag(HValue::kAllowUndefinedAsNaN);
|
||||
}
|
||||
loop.EndBody();
|
||||
@ -9016,8 +9023,8 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
|
||||
? graph()->GetConstantHole()
|
||||
: Add<HConstant>(HConstant::kHoleNaN);
|
||||
if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
|
||||
Add<HStoreKeyed>(
|
||||
elements, new_length, hole, kind, INITIALIZING_STORE);
|
||||
Add<HStoreKeyed>(elements, new_length, hole, nullptr, kind,
|
||||
INITIALIZING_STORE);
|
||||
|
||||
// Remember new length.
|
||||
Add<HStoreNamedField>(
|
||||
@ -9479,8 +9486,8 @@ HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
|
||||
LoopBuilder loop(this, context(), direction);
|
||||
{
|
||||
HValue* index = loop.BeginBody(initial, terminating, token);
|
||||
HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr, kind,
|
||||
ALLOW_RETURN_HOLE);
|
||||
HValue* element = AddUncasted<HLoadKeyed>(
|
||||
elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
|
||||
IfBuilder if_issame(this);
|
||||
if_issame.If<HCompareNumericAndBranch>(element, search_element,
|
||||
Token::EQ_STRICT);
|
||||
@ -9501,8 +9508,8 @@ HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
|
||||
LoopBuilder loop(this, context(), direction);
|
||||
{
|
||||
HValue* index = loop.BeginBody(initial, terminating, token);
|
||||
HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
|
||||
kind, ALLOW_RETURN_HOLE);
|
||||
HValue* element = AddUncasted<HLoadKeyed>(
|
||||
elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
|
||||
IfBuilder if_issame(this);
|
||||
if_issame.If<HIsStringAndBranch>(element);
|
||||
if_issame.AndIf<HStringCompareAndBranch>(
|
||||
@ -9531,8 +9538,8 @@ HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
|
||||
LoopBuilder loop(this, context(), direction);
|
||||
{
|
||||
HValue* index = loop.BeginBody(initial, terminating, token);
|
||||
HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
|
||||
kind, ALLOW_RETURN_HOLE);
|
||||
HValue* element = AddUncasted<HLoadKeyed>(
|
||||
elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
|
||||
|
||||
IfBuilder if_element_isnumber(this);
|
||||
if_element_isnumber.If<HIsSmiAndBranch>(element);
|
||||
@ -9563,8 +9570,8 @@ HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
|
||||
LoopBuilder loop(this, context(), direction);
|
||||
{
|
||||
HValue* index = loop.BeginBody(initial, terminating, token);
|
||||
HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
|
||||
kind, ALLOW_RETURN_HOLE);
|
||||
HValue* element = AddUncasted<HLoadKeyed>(
|
||||
elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
|
||||
IfBuilder if_issame(this);
|
||||
if_issame.If<HCompareObjectEqAndBranch>(
|
||||
element, search_element);
|
||||
@ -10218,7 +10225,7 @@ HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
|
||||
HValue* key = builder.BeginBody(
|
||||
Add<HConstant>(static_cast<int32_t>(0)),
|
||||
length, Token::LT);
|
||||
Add<HStoreKeyed>(backing_store, key, filler, fixed_elements_kind);
|
||||
Add<HStoreKeyed>(backing_store, key, filler, elements, fixed_elements_kind);
|
||||
|
||||
builder.EndBody();
|
||||
}
|
||||
@ -11961,10 +11968,11 @@ void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
|
||||
int elements_length = elements->length();
|
||||
for (int i = 0; i < elements_length; i++) {
|
||||
HValue* key_constant = Add<HConstant>(i);
|
||||
HInstruction* value_instruction = Add<HLoadKeyed>(
|
||||
boilerplate_elements, key_constant, nullptr, kind, ALLOW_RETURN_HOLE);
|
||||
HInstruction* value_instruction =
|
||||
Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
|
||||
kind, ALLOW_RETURN_HOLE);
|
||||
HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
|
||||
value_instruction, kind);
|
||||
value_instruction, nullptr, kind);
|
||||
store->SetFlag(HValue::kAllowUndefinedAsNaN);
|
||||
}
|
||||
}
|
||||
@ -11987,15 +11995,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, nullptr, kind);
|
||||
} else {
|
||||
ElementsKind copy_kind =
|
||||
kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
|
||||
HInstruction* value_instruction =
|
||||
Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr,
|
||||
Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
|
||||
copy_kind, ALLOW_RETURN_HOLE);
|
||||
Add<HStoreKeyed>(object_elements, key_constant, value_instruction,
|
||||
copy_kind);
|
||||
nullptr, copy_kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12771,7 +12779,7 @@ void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) {
|
||||
HValue* index = Pop();
|
||||
HValue* object = Pop();
|
||||
HInstruction* result = New<HLoadKeyed>(
|
||||
object, index, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
|
||||
object, index, nullptr, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
|
||||
return ast_context()->ReturnInstruction(result, call->id());
|
||||
}
|
||||
|
||||
@ -12785,7 +12793,7 @@ void HOptimizedGraphBuilder::GenerateFixedArraySet(CallRuntime* call) {
|
||||
HValue* index = Pop();
|
||||
HValue* object = Pop();
|
||||
NoObservableSideEffectsScope no_effects(this);
|
||||
Add<HStoreKeyed>(object, index, value, FAST_HOLEY_ELEMENTS);
|
||||
Add<HStoreKeyed>(object, index, value, nullptr, FAST_HOLEY_ELEMENTS);
|
||||
return ast_context()->ReturnValue(graph()->GetConstantUndefined());
|
||||
}
|
||||
|
||||
|
@ -1403,11 +1403,8 @@ class HGraphBuilder {
|
||||
KeyedAccessStoreMode store_mode);
|
||||
|
||||
HInstruction* AddElementAccess(
|
||||
HValue* elements,
|
||||
HValue* checked_key,
|
||||
HValue* val,
|
||||
HValue* dependency,
|
||||
ElementsKind elements_kind,
|
||||
HValue* elements, HValue* checked_key, HValue* val, HValue* dependency,
|
||||
HValue* backing_store_owner, ElementsKind elements_kind,
|
||||
PropertyAccessType access_type,
|
||||
LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE);
|
||||
|
||||
|
@ -2188,7 +2188,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
|
||||
if (!instr->is_fixed_typed_array()) {
|
||||
LOperand* obj = UseRegisterAtStart(instr->elements());
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
|
||||
result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key, nullptr));
|
||||
} else {
|
||||
DCHECK(
|
||||
(instr->representation().IsInteger32() &&
|
||||
@ -2196,7 +2196,9 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
(instr->representation().IsDouble() &&
|
||||
(IsDoubleOrFloatElementsKind(instr->elements_kind()))));
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
result = DefineAsRegister(
|
||||
new (zone()) LLoadKeyed(backing_store, key, backing_store_owner));
|
||||
}
|
||||
|
||||
bool needs_environment;
|
||||
@ -2261,7 +2263,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
LOperand* val = NULL;
|
||||
val = UseRegisterAtStart(instr->value());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
return new(zone()) LStoreKeyed(object, key, val);
|
||||
return new (zone()) LStoreKeyed(object, key, val, nullptr);
|
||||
} else {
|
||||
DCHECK(instr->value()->representation().IsSmiOrTagged());
|
||||
bool needs_write_barrier = instr->NeedsWriteBarrier();
|
||||
@ -2276,7 +2278,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
val = UseRegisterOrConstantAtStart(instr->value());
|
||||
key = UseRegisterOrConstantAtStart(instr->key());
|
||||
}
|
||||
return new(zone()) LStoreKeyed(obj, key, val);
|
||||
return new (zone()) LStoreKeyed(obj, key, val, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2289,13 +2291,14 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
DCHECK(instr->elements()->representation().IsExternal());
|
||||
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
LOperand* val = GetStoreKeyedValueOperand(instr);
|
||||
bool clobbers_key = ExternalArrayOpRequiresTemp(
|
||||
instr->key()->representation(), elements_kind);
|
||||
LOperand* key = clobbers_key
|
||||
? UseTempRegister(instr->key())
|
||||
: UseRegisterOrConstantAtStart(instr->key());
|
||||
return new(zone()) LStoreKeyed(backing_store, key, val);
|
||||
return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1590,14 +1590,16 @@ class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 3, 0> {
|
||||
public:
|
||||
LLoadKeyed(LOperand* elements, LOperand* key) {
|
||||
LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) {
|
||||
inputs_[0] = elements;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = backing_store_owner;
|
||||
}
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* backing_store_owner() { return inputs_[2]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
@ -2142,12 +2144,14 @@ class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
|
||||
};
|
||||
|
||||
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 4, 0> {
|
||||
public:
|
||||
LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) {
|
||||
LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val,
|
||||
LOperand* backing_store_owner) {
|
||||
inputs_[0] = obj;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = val;
|
||||
inputs_[3] = backing_store_owner;
|
||||
}
|
||||
|
||||
bool is_fixed_typed_array() const {
|
||||
@ -2156,6 +2160,7 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
LOperand* backing_store_owner() { return inputs_[3]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
|
@ -2139,7 +2139,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
DCHECK(instr->representation().IsSmiOrTagged());
|
||||
obj = UseRegisterAtStart(instr->elements());
|
||||
}
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
|
||||
result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key, nullptr));
|
||||
} else {
|
||||
DCHECK(
|
||||
(instr->representation().IsInteger32() &&
|
||||
@ -2147,7 +2147,9 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
(instr->representation().IsDouble() &&
|
||||
IsDoubleOrFloatElementsKind(elements_kind)));
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
result = DefineAsRegister(
|
||||
new (zone()) LLoadKeyed(backing_store, key, backing_store_owner));
|
||||
}
|
||||
|
||||
bool needs_environment;
|
||||
@ -2212,7 +2214,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
}
|
||||
}
|
||||
|
||||
return new(zone()) LStoreKeyed(object, key, val);
|
||||
return new (zone()) LStoreKeyed(object, key, val, nullptr);
|
||||
}
|
||||
|
||||
DCHECK(
|
||||
@ -2224,7 +2226,8 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
LOperand* val = UseRegister(instr->value());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
return new(zone()) LStoreKeyed(backing_store, key, val);
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1565,15 +1565,17 @@ class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 3, 0> {
|
||||
public:
|
||||
LLoadKeyed(LOperand* elements, LOperand* key) {
|
||||
LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) {
|
||||
inputs_[0] = elements;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = backing_store_owner;
|
||||
}
|
||||
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* backing_store_owner() { return inputs_[2]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
@ -2112,12 +2114,14 @@ class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
|
||||
};
|
||||
|
||||
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 4, 0> {
|
||||
public:
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value) {
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value,
|
||||
LOperand* backing_store_owner) {
|
||||
inputs_[0] = object;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = value;
|
||||
inputs_[3] = backing_store_owner;
|
||||
}
|
||||
|
||||
bool is_fixed_typed_array() const {
|
||||
@ -2126,6 +2130,7 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
LOperand* backing_store_owner() { return inputs_[3]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
|
@ -2143,7 +2143,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
instr->representation().IsInteger32());
|
||||
obj = UseRegisterAtStart(instr->elements());
|
||||
}
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
|
||||
result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key, nullptr));
|
||||
} else {
|
||||
DCHECK(
|
||||
(instr->representation().IsInteger32() &&
|
||||
@ -2151,7 +2151,9 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
(instr->representation().IsDouble() &&
|
||||
IsDoubleOrFloatElementsKind(elements_kind)));
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
result = DefineAsRegister(
|
||||
new (zone()) LLoadKeyed(backing_store, key, backing_store_owner));
|
||||
}
|
||||
|
||||
bool needs_environment;
|
||||
@ -2217,7 +2219,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
}
|
||||
}
|
||||
|
||||
return new(zone()) LStoreKeyed(object, key, val);
|
||||
return new (zone()) LStoreKeyed(object, key, val, nullptr);
|
||||
}
|
||||
|
||||
DCHECK(
|
||||
@ -2229,7 +2231,8 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
LOperand* val = UseRegister(instr->value());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
return new(zone()) LStoreKeyed(backing_store, key, val);
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1627,15 +1627,17 @@ class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 3, 0> {
|
||||
public:
|
||||
LLoadKeyed(LOperand* elements, LOperand* key) {
|
||||
LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) {
|
||||
inputs_[0] = elements;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = backing_store_owner;
|
||||
}
|
||||
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* backing_store_owner() { return inputs_[2]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
@ -2158,12 +2160,14 @@ class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
|
||||
};
|
||||
|
||||
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 4, 0> {
|
||||
public:
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value) {
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value,
|
||||
LOperand* backing_store_owner) {
|
||||
inputs_[0] = object;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = value;
|
||||
inputs_[3] = backing_store_owner;
|
||||
}
|
||||
|
||||
bool is_fixed_typed_array() const {
|
||||
@ -2172,6 +2176,7 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
LOperand* backing_store_owner() { return inputs_[3]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
|
@ -2152,14 +2152,16 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
} else {
|
||||
obj = UseRegisterAtStart(instr->elements());
|
||||
}
|
||||
result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key));
|
||||
result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key, nullptr));
|
||||
} else {
|
||||
DCHECK((instr->representation().IsInteger32() &&
|
||||
!IsDoubleOrFloatElementsKind(elements_kind)) ||
|
||||
(instr->representation().IsDouble() &&
|
||||
IsDoubleOrFloatElementsKind(elements_kind)));
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
result = DefineAsRegister(new (zone()) LLoadKeyed(backing_store, key));
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
result = DefineAsRegister(
|
||||
new (zone()) LLoadKeyed(backing_store, key, backing_store_owner));
|
||||
}
|
||||
|
||||
bool needs_environment;
|
||||
@ -2222,7 +2224,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
}
|
||||
}
|
||||
|
||||
return new (zone()) LStoreKeyed(object, key, val);
|
||||
return new (zone()) LStoreKeyed(object, key, val, nullptr);
|
||||
}
|
||||
|
||||
DCHECK((instr->value()->representation().IsInteger32() &&
|
||||
@ -2233,7 +2235,8 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
LOperand* val = UseRegister(instr->value());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
return new (zone()) LStoreKeyed(backing_store, key, val);
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1544,15 +1544,17 @@ class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 3, 0> {
|
||||
public:
|
||||
LLoadKeyed(LOperand* elements, LOperand* key) {
|
||||
LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) {
|
||||
inputs_[0] = elements;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = backing_store_owner;
|
||||
}
|
||||
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* backing_store_owner() { return inputs_[2]; }
|
||||
ElementsKind elements_kind() const { return hydrogen()->elements_kind(); }
|
||||
bool is_fixed_typed_array() const {
|
||||
return hydrogen()->is_fixed_typed_array();
|
||||
@ -2064,12 +2066,14 @@ class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
|
||||
};
|
||||
|
||||
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 4, 0> {
|
||||
public:
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value) {
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value,
|
||||
LOperand* backing_store_owner) {
|
||||
inputs_[0] = object;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = value;
|
||||
inputs_[3] = backing_store_owner;
|
||||
}
|
||||
|
||||
bool is_fixed_typed_array() const {
|
||||
@ -2078,6 +2082,7 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
LOperand* backing_store_owner() { return inputs_[3]; }
|
||||
ElementsKind elements_kind() const { return hydrogen()->elements_kind(); }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
|
||||
|
@ -2190,7 +2190,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
|
||||
if (!instr->is_fixed_typed_array()) {
|
||||
LOperand* obj = UseRegisterAtStart(instr->elements());
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
|
||||
result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key, nullptr));
|
||||
} else {
|
||||
DCHECK(
|
||||
(instr->representation().IsInteger32() &&
|
||||
@ -2198,7 +2198,9 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
(instr->representation().IsDouble() &&
|
||||
(IsDoubleOrFloatElementsKind(elements_kind))));
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
result = DefineAsRegister(
|
||||
new (zone()) LLoadKeyed(backing_store, key, backing_store_owner));
|
||||
}
|
||||
|
||||
bool needs_environment;
|
||||
@ -2270,7 +2272,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
}
|
||||
}
|
||||
|
||||
return new(zone()) LStoreKeyed(object, key, val);
|
||||
return new (zone()) LStoreKeyed(object, key, val, nullptr);
|
||||
}
|
||||
|
||||
DCHECK(
|
||||
@ -2294,7 +2296,8 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
: UseRegisterOrConstantAtStart(instr->key());
|
||||
}
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
return new(zone()) LStoreKeyed(backing_store, key, val);
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1591,11 +1591,12 @@ inline static bool ExternalArrayOpRequiresTemp(
|
||||
}
|
||||
|
||||
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 3, 0> {
|
||||
public:
|
||||
LLoadKeyed(LOperand* elements, LOperand* key) {
|
||||
LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) {
|
||||
inputs_[0] = elements;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = backing_store_owner;
|
||||
}
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
|
||||
@ -1606,6 +1607,7 @@ class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
|
||||
}
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* backing_store_owner() { return inputs_[2]; }
|
||||
void PrintDataTo(StringStream* stream) override;
|
||||
uint32_t base_offset() const { return hydrogen()->base_offset(); }
|
||||
ElementsKind elements_kind() const {
|
||||
@ -2127,12 +2129,14 @@ class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
|
||||
};
|
||||
|
||||
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 4, 0> {
|
||||
public:
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value) {
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value,
|
||||
LOperand* backing_store_owner) {
|
||||
inputs_[0] = object;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = value;
|
||||
inputs_[3] = backing_store_owner;
|
||||
}
|
||||
|
||||
bool is_fixed_typed_array() const {
|
||||
@ -2141,6 +2145,7 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
LOperand* backing_store_owner() { return inputs_[3]; }
|
||||
ElementsKind elements_kind() const { return hydrogen()->elements_kind(); }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
|
||||
|
@ -2186,7 +2186,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
|
||||
if (!instr->is_fixed_typed_array()) {
|
||||
LOperand* obj = UseRegisterAtStart(instr->elements());
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
|
||||
result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key, nullptr));
|
||||
} else {
|
||||
DCHECK(
|
||||
(instr->representation().IsInteger32() &&
|
||||
@ -2194,7 +2194,9 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
(instr->representation().IsDouble() &&
|
||||
(IsDoubleOrFloatElementsKind(instr->elements_kind()))));
|
||||
LOperand* backing_store = UseRegister(instr->elements());
|
||||
result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
result = DefineAsRegister(
|
||||
new (zone()) LLoadKeyed(backing_store, key, backing_store_owner));
|
||||
}
|
||||
|
||||
bool needs_environment;
|
||||
@ -2265,7 +2267,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
? NULL
|
||||
: UseRegisterAtStart(instr->value());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
return new(zone()) LStoreKeyed(object, key, val);
|
||||
return new (zone()) LStoreKeyed(object, key, val, nullptr);
|
||||
} else {
|
||||
DCHECK(instr->value()->representation().IsSmiOrTagged());
|
||||
bool needs_write_barrier = instr->NeedsWriteBarrier();
|
||||
@ -2280,7 +2282,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
val = UseRegisterOrConstantAtStart(instr->value());
|
||||
key = UseRegisterOrConstantAtStart(instr->key());
|
||||
}
|
||||
return new(zone()) LStoreKeyed(obj, key, val);
|
||||
return new (zone()) LStoreKeyed(obj, key, val, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2299,7 +2301,8 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
LOperand* key = clobbers_key
|
||||
? UseTempRegister(instr->key())
|
||||
: UseRegisterOrConstantAtStart(instr->key());
|
||||
return new(zone()) LStoreKeyed(backing_store, key, val);
|
||||
LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
|
||||
return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1598,14 +1598,16 @@ class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
|
||||
class LLoadKeyed final : public LTemplateInstruction<1, 3, 0> {
|
||||
public:
|
||||
LLoadKeyed(LOperand* elements, LOperand* key) {
|
||||
LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) {
|
||||
inputs_[0] = elements;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = backing_store_owner;
|
||||
}
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* backing_store_owner() { return inputs_[2]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
@ -2146,12 +2148,14 @@ class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
|
||||
};
|
||||
|
||||
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
class LStoreKeyed final : public LTemplateInstruction<0, 4, 0> {
|
||||
public:
|
||||
LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) {
|
||||
LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val,
|
||||
LOperand* backing_store_owner) {
|
||||
inputs_[0] = obj;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = val;
|
||||
inputs_[3] = backing_store_owner
|
||||
}
|
||||
|
||||
bool is_fixed_typed_array() const {
|
||||
@ -2160,6 +2164,7 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
LOperand* backing_store_owner() { return inputs_[3]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
|
@ -1050,6 +1050,7 @@
|
||||
'regress/regress-crbug-506956': [SKIP],
|
||||
'regress/regress-crbug-505907': [SKIP],
|
||||
|
||||
'regress/typed-array-lifetime': [SKIP],
|
||||
}], # ignition == True
|
||||
|
||||
['ignition == True and (arch == arm or arch == arm64)', {
|
||||
|
26
test/mjsunit/regress/typed-array-lifetime.js
Normal file
26
test/mjsunit/regress/typed-array-lifetime.js
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// Flags: --allow-natives-syntax --typed-array-max-size-in-heap=1
|
||||
|
||||
var foo = (function () {
|
||||
var y = 0;
|
||||
return function foo(x) {
|
||||
// Needs to be an external array.
|
||||
var a = new Float64Array(32);
|
||||
a[0] = 42;
|
||||
y = x + 0.1; // This has to allocate.
|
||||
return a[0];
|
||||
}
|
||||
})();
|
||||
|
||||
foo(1);
|
||||
foo(1);
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
foo(1);
|
||||
// Try to force a GC during allocation in above marked line.
|
||||
for (var i = 0; i < 20; ++i) {
|
||||
%SetAllocationTimeout(i, i, false);
|
||||
assertEquals(42, foo(2));
|
||||
}
|
Loading…
Reference in New Issue
Block a user