Revision: 24172
Author:   [email protected]
Date:     Wed Sep 24 09:28:56 2014 UTC
Log:      [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
[email protected]

Review URL: https://codereview.chromium.org/602563002
https://code.google.com/p/v8/source/detail?r=24172

Modified:
 /branches/bleeding_edge/src/compiler/generic-node-inl.h
 /branches/bleeding_edge/src/compiler/generic-node.h
 /branches/bleeding_edge/src/compiler/js-generic-lowering.cc
 /branches/bleeding_edge/src/compiler/js-typed-lowering.cc
 /branches/bleeding_edge/src/compiler/simplified-lowering.cc
 /branches/bleeding_edge/src/compiler/simplified-operator-unittest.cc
 /branches/bleeding_edge/src/compiler/simplified-operator.cc
 /branches/bleeding_edge/src/compiler/simplified-operator.h
 /branches/bleeding_edge/test/cctest/compiler/simplified-graph-builder.h
 /branches/bleeding_edge/test/cctest/compiler/test-node.cc
 /branches/bleeding_edge/test/cctest/compiler/test-simplified-lowering.cc

=======================================
--- /branches/bleeding_edge/src/compiler/generic-node-inl.h Fri Aug 29 12:14:52 2014 UTC +++ /branches/bleeding_edge/src/compiler/generic-node-inl.h Wed Sep 24 09:28:56 2014 UTC
@@ -176,6 +176,16 @@
   }
   ReplaceInput(index, to_insert);
 }
+
+template <class B, class S>
+void GenericNode<B, S>::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 <class B, class S>
 void GenericNode<B, S>::AppendUse(Use* use) {
=======================================
--- /branches/bleeding_edge/src/compiler/generic-node.h Tue Aug 26 13:09:08 2014 UTC +++ /branches/bleeding_edge/src/compiler/generic-node.h Wed Sep 24 09:28:56 2014 UTC
@@ -41,6 +41,7 @@
   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 @@
   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:
=======================================
--- /branches/bleeding_edge/src/compiler/js-generic-lowering.cc Fri Sep 12 14:49:07 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-generic-lowering.cc Wed Sep 24 09:28:56 2014 UTC
@@ -176,14 +176,7 @@

   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);
=======================================
--- /branches/bleeding_edge/src/compiler/js-typed-lowering.cc Mon Sep 22 07:17:13 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-typed-lowering.cc Wed Sep 24 09:28:56 2014 UTC
@@ -540,6 +540,8 @@
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 @@
     }
     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 @@
                                     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);

=======================================
--- /branches/bleeding_edge/src/compiler/simplified-lowering.cc Fri Sep 19 09:56:12 2014 UTC +++ /branches/bleeding_edge/src/compiler/simplified-lowering.cc Wed Sep 24 09:28:56 2014 UTC
@@ -596,7 +596,8 @@
         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 @@
         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 @@
   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 @@
   node->set_op(
       machine()->Store(StoreRepresentation(access.machine_type, kind)));
   node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1)));
+  node->RemoveInput(2);
 }


=======================================
--- /branches/bleeding_edge/src/compiler/simplified-operator-unittest.cc Mon Sep 15 09:09:45 2014 UTC +++ /branches/bleeding_edge/src/compiler/simplified-operator-unittest.cc Wed Sep 24 09:28:56 2014 UTC
@@ -11,6 +11,14 @@
 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 @@
 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<ElementAccess> {};
+
+
+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
=======================================
--- /branches/bleeding_edge/src/compiler/simplified-operator.cc Wed Sep 17 14:47:25 2014 UTC +++ /branches/bleeding_edge/src/compiler/simplified-operator.cc Wed Sep 24 09:28:56 2014 UTC
@@ -13,6 +13,38 @@
 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 @@
 // Specialization for static parameters of type {ElementAccess}.
 template <>
 struct StaticParameterTraits<ElementAccess> {
-  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 @@
 #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 {
=======================================
--- /branches/bleeding_edge/src/compiler/simplified-operator.h Wed Sep 17 14:47:25 2014 UTC +++ /branches/bleeding_edge/src/compiler/simplified-operator.h Wed Sep 24 09:28:56 2014 UTC
@@ -28,6 +28,8 @@

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

   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_; }
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/simplified-graph-builder.h Wed Sep 10 12:23:45 2014 UTC +++ /branches/bleeding_edge/test/cctest/compiler/simplified-graph-builder.h Wed Sep 24 09:28:56 2014 UTC
@@ -127,12 +127,14 @@
   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:
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-node.cc Fri Aug 29 12:14:52 2014 UTC +++ /branches/bleeding_edge/test/cctest/compiler/test-node.cc Wed Sep 24 09:28:56 2014 UTC
@@ -336,6 +336,27 @@
   ++current;
   CHECK(current == uses.end());
 }
+
+
+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) {
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-simplified-lowering.cc Fri Sep 19 09:56:12 2014 UTC +++ /branches/bleeding_edge/test/cctest/compiler/test-simplified-lowering.cc Wed Sep 24 09:28:56 2014 UTC
@@ -207,8 +207,10 @@
 TEST(RunLoadStoreFixedArrayIndex) {
   SimplifiedLoweringTester<Object*> 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(RunLoadStoreArrayBuffer) {
   SimplifiedLoweringTester<Object*> 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 @@

   if (Pipeline::SupportedTarget()) {
     Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer();
-    const int array_length = 2 * index;
Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length);
     uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store());
     for (int i = 0; i < array_length; i++) {
@@ -326,8 +329,9 @@
                               kMachAnyTagged};

       SimplifiedLoweringTester<Object*> t;
-      Node* load = t.LoadElement(access, t.PointerConstant(smis),
-                                 t.Int32Constant(static_cast<int>(j)));
+      Node* load = t.LoadElement(
+ access, t.PointerConstant(smis), t.Int32Constant(static_cast<int>(j)),
+          t.Int32Constant(static_cast<int>(arraysize(smis))));
       t.Return(load);
       t.LowerAllNodes();

@@ -356,7 +360,8 @@
       SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
       Node* p0 = t.Parameter(0);
       t.StoreElement(access, t.PointerConstant(smis),
-                     t.Int32Constant(static_cast<int>(j)), p0);
+                     t.Int32Constant(static_cast<int>(j)),
+ t.Int32Constant(static_cast<int>(arraysize(smis))), p0);
       t.Return(p0);
       t.LowerAllNodes();

@@ -422,8 +427,10 @@

     SimplifiedLoweringTester<Object*> 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 @@
   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 @@
     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 @@
     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 @@

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

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to