[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:
jochen 2015-12-07 00:37:27 -08:00 committed by Commit bot
parent da8fd00e4c
commit 086d459847
23 changed files with 332 additions and 202 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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());

View File

@ -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;
}

View File

@ -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(

View File

@ -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);

View File

@ -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());
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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")

View File

@ -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);
}

View File

@ -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")

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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)', {

View 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));
}