From deaf463bf1ec61d9fa7abb7a308f3c058f721958 Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Wed, 24 Sep 2014 09:28:56 +0000 Subject: [PATCH] [turbofan] Add length operand to LoadElement and StoreElement. This is preliminary work, required to properly support bounds checking for typed array loads/stores. TEST=compiler-unittests,cctest R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/602563002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24172 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler/generic-node-inl.h | 10 +++ src/compiler/generic-node.h | 3 +- src/compiler/js-generic-lowering.cc | 9 +- src/compiler/js-typed-lowering.cc | 12 ++- src/compiler/simplified-lowering.cc | 10 ++- src/compiler/simplified-operator-unittest.cc | 105 +++++++++++++++++++++++ src/compiler/simplified-operator.cc | 44 ++++++++-- src/compiler/simplified-operator.h | 15 +++- test/cctest/compiler/simplified-graph-builder.h | 10 ++- test/cctest/compiler/test-node.cc | 21 +++++ test/cctest/compiler/test-simplified-lowering.cc | 65 ++++++++------ 11 files changed, 250 insertions(+), 54 deletions(-) diff --git a/src/compiler/generic-node-inl.h b/src/compiler/generic-node-inl.h index 82fd907..c2dc24e 100644 --- a/src/compiler/generic-node-inl.h +++ b/src/compiler/generic-node-inl.h @@ -178,6 +178,16 @@ void GenericNode::InsertInput(Zone* zone, int index, } template +void GenericNode::RemoveInput(int index) { + DCHECK(index >= 0 && index < InputCount()); + // TODO(turbofan): Optimize this implementation! + for (; index < InputCount() - 1; ++index) { + ReplaceInput(index, InputAt(index + 1)); + } + TrimInputCount(InputCount() - 1); +} + +template void GenericNode::AppendUse(Use* use) { use->next = NULL; use->prev = last_use_; diff --git a/src/compiler/generic-node.h b/src/compiler/generic-node.h index d909943..3dc324d 100644 --- a/src/compiler/generic-node.h +++ b/src/compiler/generic-node.h @@ -41,6 +41,7 @@ class GenericNode : public B { inline void ReplaceInput(int index, GenericNode* new_input); inline void AppendInput(Zone* zone, GenericNode* new_input); inline void InsertInput(Zone* zone, int index, GenericNode* new_input); + inline void RemoveInput(int index); int UseCount() { return use_count_; } S* UseAt(int index) { @@ -56,7 +57,7 @@ class GenericNode : public B { inline void ReplaceUsesIf(UnaryPredicate pred, GenericNode* replace_to); inline void RemoveAllInputs(); - void TrimInputCount(int input_count); + inline void TrimInputCount(int input_count); class Inputs { public: diff --git a/src/compiler/js-generic-lowering.cc b/src/compiler/js-generic-lowering.cc index 586b6b5..300604e 100644 --- a/src/compiler/js-generic-lowering.cc +++ b/src/compiler/js-generic-lowering.cc @@ -176,14 +176,7 @@ void JSGenericLowering::ReplaceWithCompareIC(Node* node, Token::Value token, if (has_frame_state) { // Remove the frame state from inputs. - // TODO(jarin) This should use Node::RemoveInput (which does not exist yet). - int dest = NodeProperties::FirstFrameStateIndex(node); - for (int i = NodeProperties::PastFrameStateIndex(node); - i < node->InputCount(); i++) { - node->ReplaceInput(dest, node->InputAt(i)); - dest++; - } - node->TrimInputCount(dest); + node->RemoveInput(NodeProperties::FirstFrameStateIndex(node)); } ReplaceWithRuntimeCall(node, Runtime::kBooleanize); diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index 130c5cb..be12534 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -540,6 +540,8 @@ Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { JSTypedArray* array = JSTypedArray::cast(*base_type->AsConstant()->Value()); ElementsKind elements_kind = array->map()->elements_kind(); ExternalArrayType type = array->type(); + uint32_t length; + CHECK(array->length()->ToUint32(&length)); ElementAccess element_access; Node* elements = graph()->NewNode( simplified()->LoadField(AccessBuilder::ForJSObjectElements()), base, @@ -555,7 +557,8 @@ Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { } Node* value = graph()->NewNode(simplified()->LoadElement(element_access), elements, - key, NodeProperties::GetEffectInput(node)); + key, jsgraph()->Uint32Constant(length), + NodeProperties::GetEffectInput(node)); return ReplaceEagerly(node, value); } return NoChange(); @@ -599,9 +602,10 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) { NodeProperties::GetControlInput(node)); Node* if_true = graph()->NewNode(common()->IfTrue(), branch); - Node* store = graph()->NewNode( - simplified()->StoreElement(element_access), elements, key, value, - NodeProperties::GetEffectInput(node), if_true); + Node* store = + graph()->NewNode(simplified()->StoreElement(element_access), elements, + key, jsgraph()->Uint32Constant(length), value, + NodeProperties::GetEffectInput(node), if_true); Node* if_false = graph()->NewNode(common()->IfFalse(), branch); diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index e3ddf5c..8ac2a85 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -596,7 +596,8 @@ class RepresentationSelector { ElementAccess access = ElementAccessOf(node->op()); ProcessInput(node, 0, changer_->TypeForBasePointer(access)); ProcessInput(node, 1, kMachInt32); // element index - ProcessRemainingInputs(node, 2); + ProcessInput(node, 2, kMachInt32); // length + ProcessRemainingInputs(node, 3); SetOutput(node, AssumeImplicitFloat32Change(access.machine_type)); if (lower()) lowering->DoLoadElement(node); break; @@ -605,8 +606,9 @@ class RepresentationSelector { ElementAccess access = ElementAccessOf(node->op()); ProcessInput(node, 0, changer_->TypeForBasePointer(access)); ProcessInput(node, 1, kMachInt32); // element index - ProcessInput(node, 2, AssumeImplicitFloat32Change(access.machine_type)); - ProcessRemainingInputs(node, 3); + ProcessInput(node, 2, kMachInt32); // length + ProcessInput(node, 3, AssumeImplicitFloat32Change(access.machine_type)); + ProcessRemainingInputs(node, 4); SetOutput(node, 0); if (lower()) lowering->DoStoreElement(node); break; @@ -867,6 +869,7 @@ void SimplifiedLowering::DoLoadElement(Node* node) { const ElementAccess& access = ElementAccessOf(node->op()); node->set_op(machine()->Load(access.machine_type)); node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); + node->RemoveInput(2); } @@ -877,6 +880,7 @@ void SimplifiedLowering::DoStoreElement(Node* node) { node->set_op( machine()->Store(StoreRepresentation(access.machine_type, kind))); node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); + node->RemoveInput(2); } diff --git a/src/compiler/simplified-operator-unittest.cc b/src/compiler/simplified-operator-unittest.cc index ef13dac..4014f24 100644 --- a/src/compiler/simplified-operator-unittest.cc +++ b/src/compiler/simplified-operator-unittest.cc @@ -11,6 +11,14 @@ namespace v8 { namespace internal { namespace compiler { +// TODO(bmeurer): Drop once we use std::ostream instead of our OStream. +inline std::ostream& operator<<(std::ostream& os, const ElementAccess& access) { + OStringStream ost; + ost << access; + return os << ost.c_str(); +} + + // ----------------------------------------------------------------------------- // Pure operators. @@ -112,6 +120,103 @@ TEST_P(SimplifiedPureOperatorTest, Properties) { INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, SimplifiedPureOperatorTest, ::testing::ValuesIn(kPureOperators)); + +// ----------------------------------------------------------------------------- +// Element access operators. + +namespace { + +const ElementAccess kElementAccesses[] = { + {kTaggedBase, FixedArray::kHeaderSize, Type::Any(), kMachAnyTagged}, + {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(), + kMachInt8}, + {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(), + kMachInt16}, + {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(), + kMachInt32}, + {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(), + kMachUint8}, + {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(), + kMachUint16}, + {kUntaggedBase, kNonHeapObjectHeaderSize - kHeapObjectTag, Type::Any(), + kMachUint32}, + {kUntaggedBase, 0, Type::Signed32(), kMachInt8}, + {kUntaggedBase, 0, Type::Unsigned32(), kMachUint8}, + {kUntaggedBase, 0, Type::Signed32(), kMachInt16}, + {kUntaggedBase, 0, Type::Unsigned32(), kMachUint16}, + {kUntaggedBase, 0, Type::Signed32(), kMachInt32}, + {kUntaggedBase, 0, Type::Unsigned32(), kMachUint32}, + {kUntaggedBase, 0, Type::Number(), kRepFloat32}, + {kUntaggedBase, 0, Type::Number(), kRepFloat64}, + {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(), + kMachInt8}, + {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(), + kMachUint8}, + {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(), + kMachInt16}, + {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(), + kMachUint16}, + {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(), + kMachInt32}, + {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(), + kMachUint32}, + {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(), + kRepFloat32}, + {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(), + kRepFloat64}}; + +} // namespace + + +class SimplifiedElementAccessOperatorTest + : public TestWithZone, + public ::testing::WithParamInterface {}; + + +TEST_P(SimplifiedElementAccessOperatorTest, LoadElement) { + SimplifiedOperatorBuilder simplified(zone()); + const ElementAccess& access = GetParam(); + const Operator* op = simplified.LoadElement(access); + + EXPECT_EQ(IrOpcode::kLoadElement, op->opcode()); + EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties()); + EXPECT_EQ(access, ElementAccessOf(op)); + + EXPECT_EQ(3, OperatorProperties::GetValueInputCount(op)); + EXPECT_EQ(1, OperatorProperties::GetEffectInputCount(op)); + EXPECT_EQ(0, OperatorProperties::GetControlInputCount(op)); + EXPECT_EQ(4, OperatorProperties::GetTotalInputCount(op)); + + EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op)); + EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op)); + EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); +} + + +TEST_P(SimplifiedElementAccessOperatorTest, StoreElement) { + SimplifiedOperatorBuilder simplified(zone()); + const ElementAccess& access = GetParam(); + const Operator* op = simplified.StoreElement(access); + + EXPECT_EQ(IrOpcode::kStoreElement, op->opcode()); + EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties()); + EXPECT_EQ(access, ElementAccessOf(op)); + + EXPECT_EQ(4, OperatorProperties::GetValueInputCount(op)); + EXPECT_EQ(1, OperatorProperties::GetEffectInputCount(op)); + EXPECT_EQ(1, OperatorProperties::GetControlInputCount(op)); + EXPECT_EQ(6, OperatorProperties::GetTotalInputCount(op)); + + EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op)); + EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op)); + EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); +} + + +INSTANTIATE_TEST_CASE_P(SimplifiedOperatorTest, + SimplifiedElementAccessOperatorTest, + ::testing::ValuesIn(kElementAccesses)); + } // namespace compiler } // namespace internal } // namespace v8 diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc index 75b6e22..642ffc7 100644 --- a/src/compiler/simplified-operator.cc +++ b/src/compiler/simplified-operator.cc @@ -13,6 +13,38 @@ namespace v8 { namespace internal { namespace compiler { +OStream& operator<<(OStream& os, BaseTaggedness base_taggedness) { + switch (base_taggedness) { + case kUntaggedBase: + return os << "untagged base"; + case kTaggedBase: + return os << "tagged base"; + } + UNREACHABLE(); + return os; +} + + +bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) { + return lhs.base_is_tagged == rhs.base_is_tagged && + lhs.header_size == rhs.header_size && lhs.type == rhs.type && + lhs.machine_type == rhs.machine_type; +} + + +bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) { + return !(lhs == rhs); +} + + +OStream& operator<<(OStream& os, ElementAccess const& access) { + os << "[" << access.base_is_tagged << ", " << access.header_size << ", "; + access.type->PrintTo(os); + os << ", " << access.machine_type << "]"; + return os; +} + + const FieldAccess& FieldAccessOf(const Operator* op) { DCHECK_NOT_NULL(op); DCHECK(op->opcode() == IrOpcode::kLoadField || @@ -49,11 +81,11 @@ struct StaticParameterTraits { // Specialization for static parameters of type {ElementAccess}. template <> struct StaticParameterTraits { - static OStream& PrintTo(OStream& os, const ElementAccess& val) { - return os << val.header_size; + static OStream& PrintTo(OStream& os, const ElementAccess& access) { + return os << access; } - static int HashCode(const ElementAccess& val) { - return (val.header_size < 16) | (val.machine_type & 0xffff); + static int HashCode(const ElementAccess& access) { + return (access.header_size < 16) | (access.machine_type & 0xffff); } static bool Equals(const ElementAccess& lhs, const ElementAccess& rhs) { return lhs.base_is_tagged == rhs.base_is_tagged && @@ -93,8 +125,8 @@ struct StaticParameterTraits { #define ACCESS_OP_LIST(V) \ V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1) \ V(StoreField, FieldAccess, Operator::kNoRead, 2, 0) \ - V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1) \ - V(StoreElement, ElementAccess, Operator::kNoRead, 3, 0) + V(LoadElement, ElementAccess, Operator::kNoWrite, 3, 1) \ + V(StoreElement, ElementAccess, Operator::kNoRead, 4, 0) struct SimplifiedOperatorBuilderImpl FINAL { diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h index 907507c..32f0e8b 100644 --- a/src/compiler/simplified-operator.h +++ b/src/compiler/simplified-operator.h @@ -28,6 +28,8 @@ struct SimplifiedOperatorBuilderImpl; enum BaseTaggedness { kUntaggedBase, kTaggedBase }; +OStream& operator<<(OStream&, BaseTaggedness); + // An access descriptor for loads/stores of fixed structures like field // accesses of heap objects. Accesses from either tagged or untagged base // pointers are supported; untagging is done automatically during lowering. @@ -55,6 +57,11 @@ struct ElementAccess { int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; } }; +bool operator==(ElementAccess const& lhs, ElementAccess const& rhs); +bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs); + +OStream& operator<<(OStream&, ElementAccess const&); + // If the accessed object is not a heap object, add this to the header_size. static const int kNonHeapObjectHeaderSize = kHeapObjectTag; @@ -122,8 +129,12 @@ class SimplifiedOperatorBuilder FINAL { const Operator* LoadField(const FieldAccess&); const Operator* StoreField(const FieldAccess&); - const Operator* LoadElement(const ElementAccess&); - const Operator* StoreElement(const ElementAccess&); + + // load-element [base + index], length + const Operator* LoadElement(ElementAccess const&); + + // store-element [base + index], length, value + const Operator* StoreElement(ElementAccess const&); private: Zone* zone() const { return zone_; } diff --git a/test/cctest/compiler/simplified-graph-builder.h b/test/cctest/compiler/simplified-graph-builder.h index 586b39f..1b637b7 100644 --- a/test/cctest/compiler/simplified-graph-builder.h +++ b/test/cctest/compiler/simplified-graph-builder.h @@ -127,12 +127,14 @@ class SimplifiedGraphBuilder : public GraphBuilder { Node* StoreField(const FieldAccess& access, Node* object, Node* value) { return NewNode(simplified()->StoreField(access), object, value); } - Node* LoadElement(const ElementAccess& access, Node* object, Node* index) { - return NewNode(simplified()->LoadElement(access), object, index); + Node* LoadElement(const ElementAccess& access, Node* object, Node* index, + Node* length) { + return NewNode(simplified()->LoadElement(access), object, index, length); } Node* StoreElement(const ElementAccess& access, Node* object, Node* index, - Node* value) { - return NewNode(simplified()->StoreElement(access), object, index, value); + Node* length, Node* value) { + return NewNode(simplified()->StoreElement(access), object, index, length, + value); } protected: diff --git a/test/cctest/compiler/test-node.cc b/test/cctest/compiler/test-node.cc index da10d25..28d807e 100644 --- a/test/cctest/compiler/test-node.cc +++ b/test/cctest/compiler/test-node.cc @@ -338,6 +338,27 @@ TEST(Inputs) { } +TEST(RemoveInput) { + GraphTester graph; + + Node* n0 = graph.NewNode(&dummy_operator); + Node* n1 = graph.NewNode(&dummy_operator, n0); + Node* n2 = graph.NewNode(&dummy_operator, n0, n1); + + n1->RemoveInput(0); + CHECK_EQ(0, n1->InputCount()); + CHECK_EQ(1, n0->UseCount()); + + n2->RemoveInput(0); + CHECK_EQ(1, n2->InputCount()); + CHECK_EQ(0, n0->UseCount()); + CHECK_EQ(1, n1->UseCount()); + + n2->RemoveInput(0); + CHECK_EQ(0, n2->InputCount()); +} + + TEST(AppendInputsAndIterator) { GraphTester graph; diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc index 2c97379..a8ff7da 100644 --- a/test/cctest/compiler/test-simplified-lowering.cc +++ b/test/cctest/compiler/test-simplified-lowering.cc @@ -207,8 +207,10 @@ TEST(RunLoadStoreMap) { TEST(RunLoadStoreFixedArrayIndex) { SimplifiedLoweringTester t(kMachAnyTagged); ElementAccess access = AccessBuilder::ForFixedArrayElement(); - Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0)); - t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load); + Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0), + t.Int32Constant(2)); + t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), t.Int32Constant(2), + load); t.Return(load); t.LowerAllNodes(); @@ -231,14 +233,16 @@ TEST(RunLoadStoreFixedArrayIndex) { TEST(RunLoadStoreArrayBuffer) { SimplifiedLoweringTester t(kMachAnyTagged); const int index = 12; + const int array_length = 2 * index; ElementAccess buffer_access = AccessBuilder::ForBackingStoreElement(kMachInt8); Node* backing_store = t.LoadField( AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0)); Node* load = - t.LoadElement(buffer_access, backing_store, t.Int32Constant(index)); + t.LoadElement(buffer_access, backing_store, t.Int32Constant(index), + t.Int32Constant(array_length)); t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1), - load); + t.Int32Constant(array_length), load); t.Return(t.jsgraph.TrueConstant()); t.LowerAllNodes(); @@ -246,7 +250,6 @@ TEST(RunLoadStoreArrayBuffer) { if (Pipeline::SupportedTarget()) { Handle array = t.factory()->NewJSArrayBuffer(); - const int array_length = 2 * index; Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length); uint8_t* data = reinterpret_cast(array->backing_store()); for (int i = 0; i < array_length; i++) { @@ -326,8 +329,9 @@ TEST(RunLoadElementFromUntaggedBase) { kMachAnyTagged}; SimplifiedLoweringTester t; - Node* load = t.LoadElement(access, t.PointerConstant(smis), - t.Int32Constant(static_cast(j))); + Node* load = t.LoadElement( + access, t.PointerConstant(smis), t.Int32Constant(static_cast(j)), + t.Int32Constant(static_cast(arraysize(smis)))); t.Return(load); t.LowerAllNodes(); @@ -356,7 +360,8 @@ TEST(RunStoreElementFromUntaggedBase) { SimplifiedLoweringTester t(kMachAnyTagged); Node* p0 = t.Parameter(0); t.StoreElement(access, t.PointerConstant(smis), - t.Int32Constant(static_cast(j)), p0); + t.Int32Constant(static_cast(j)), + t.Int32Constant(static_cast(arraysize(smis))), p0); t.Return(p0); t.LowerAllNodes(); @@ -422,8 +427,10 @@ class AccessTester : public HandleAndZoneScope { SimplifiedLoweringTester t; Node* ptr = GetBaseNode(&t); - Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index)); - t.StoreElement(access, ptr, t.Int32Constant(to_index), load); + Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index), + t.Int32Constant(num_elements)); + t.StoreElement(access, ptr, t.Int32Constant(to_index), + t.Int32Constant(num_elements), load); t.Return(t.jsgraph.TrueConstant()); t.LowerAllNodes(); t.GenerateCode(); @@ -633,11 +640,13 @@ class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders { JSGraph jsgraph; Node* p0; Node* p1; + Node* p2; Node* start; Node* end; Node* ret; - explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None()) + explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None(), + Type* p2_type = Type::None()) : GraphAndBuilders(main_zone()), typer(main_zone()), javascript(main_zone()), @@ -650,8 +659,10 @@ class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders { graph()->SetEnd(end); p0 = graph()->NewNode(common()->Parameter(0), start); p1 = graph()->NewNode(common()->Parameter(1), start); + p2 = graph()->NewNode(common()->Parameter(2), start); NodeProperties::SetBounds(p0, Bounds(p0_type)); NodeProperties::SetBounds(p1, Bounds(p1_type)); + NodeProperties::SetBounds(p2, Bounds(p2_type)); } void CheckLoweringBinop(IrOpcode::Value expected, const Operator* op) { @@ -1341,8 +1352,9 @@ TEST(LowerLoadElement_to_load) { ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), machine_reps[i]}; - Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, - t.p1, t.start); + Node* load = + t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, t.p1, + t.jsgraph.Int32Constant(1024), t.start); Node* use = t.Use(load, machine_reps[i]); t.Return(use); t.Lower(); @@ -1365,7 +1377,8 @@ TEST(LowerStoreElement_to_store) { Node* val = t.ExampleWithOutput(machine_reps[i]); Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, - t.p1, val, t.start, t.start); + t.p1, t.jsgraph.Int32Constant(1024), val, + t.start, t.start); t.Effect(store); t.Lower(); CHECK_EQ(IrOpcode::kStore, store->opcode()); @@ -1382,14 +1395,14 @@ TEST(LowerStoreElement_to_store) { TEST(InsertChangeForLoadElementIndex) { - // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged) => + // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) - TestingGraph t(Type::Any(), Type::Signed32()); + TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), kMachAnyTagged}; Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, - t.p1, t.start); + t.p1, t.p2, t.start); t.Return(load); t.Lower(); CHECK_EQ(IrOpcode::kLoad, load->opcode()); @@ -1401,14 +1414,14 @@ TEST(InsertChangeForLoadElementIndex) { TEST(InsertChangeForStoreElementIndex) { - // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, val) => + // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) => // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val) - TestingGraph t(Type::Any(), Type::Signed32()); + TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), kMachAnyTagged}; Node* store = - t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, + t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1, t.p2, t.jsgraph.TrueConstant(), t.start, t.start); t.Effect(store); t.Lower(); @@ -1422,12 +1435,12 @@ TEST(InsertChangeForStoreElementIndex) { TEST(InsertChangeForLoadElement) { // TODO(titzer): test all load/store representation change insertions. - TestingGraph t(Type::Any(), Type::Signed32()); + TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), kMachFloat64}; Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, - t.p1, t.start); + t.p1, t.p1, t.start); t.Return(load); t.Lower(); CHECK_EQ(IrOpcode::kLoad, load->opcode()); @@ -1454,13 +1467,13 @@ TEST(InsertChangeForLoadField) { TEST(InsertChangeForStoreElement) { // TODO(titzer): test all load/store representation change insertions. - TestingGraph t(Type::Any(), Type::Signed32()); + TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), kMachFloat64}; - Node* store = - t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, - t.jsgraph.Int32Constant(0), t.p1, t.start, t.start); + Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, + t.jsgraph.Int32Constant(0), t.p2, t.p1, + t.start, t.start); t.Effect(store); t.Lower(); -- 2.7.4