[turbofan] Introduce explicit JSCreateLiteral[Array|Object].
authormstarzinger <mstarzinger@chromium.org>
Mon, 27 Apr 2015 09:57:47 +0000 (02:57 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 27 Apr 2015 09:57:22 +0000 (09:57 +0000)
This uses explicit operators instead of intrinsic runtime calls to
create literals froms boilerplates. It allows for easier access of
static parameters and syncs it with other allocating operators.

R=svenpanne@chromium.org

Review URL: https://codereview.chromium.org/1104453006

Cr-Commit-Position: refs/heads/master@{#28062}

15 files changed:
src/compiler/ast-graph-builder.cc
src/compiler/js-generic-lowering.cc
src/compiler/js-intrinsic-lowering.cc
src/compiler/js-intrinsic-lowering.h
src/compiler/js-operator.cc
src/compiler/js-operator.h
src/compiler/js-typed-lowering.cc
src/compiler/js-typed-lowering.h
src/compiler/linkage.cc
src/compiler/opcodes.h
src/compiler/operator-properties.cc
src/compiler/typer.cc
src/compiler/verifier.cc
test/unittests/compiler/js-intrinsic-lowering-unittest.cc
test/unittests/compiler/js-typed-lowering-unittest.cc

index 03fee58..933f466 100644 (file)
@@ -1660,10 +1660,9 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
   Node* literal_index = jsgraph()->Constant(expr->literal_index());
   Node* constants = jsgraph()->Constant(expr->constant_properties());
-  Node* flags = jsgraph()->Constant(expr->ComputeFlags(true));
   const Operator* op =
-      javascript()->CallRuntime(Runtime::kInlineCreateObjectLiteral, 4);
-  Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
+      javascript()->CreateLiteralObject(expr->ComputeFlags(true));
+  Node* literal = NewNode(op, literals_array, literal_index, constants);
   PrepareFrameState(literal, expr->CreateLiteralId(),
                     OutputFrameStateCombine::Push());
 
@@ -1852,10 +1851,9 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
   Node* literal_index = jsgraph()->Constant(expr->literal_index());
   Node* constants = jsgraph()->Constant(expr->constant_elements());
-  Node* flags = jsgraph()->Constant(expr->ComputeFlags(true));
   const Operator* op =
-      javascript()->CallRuntime(Runtime::kInlineCreateArrayLiteral, 4);
-  Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
+      javascript()->CreateLiteralArray(expr->ComputeFlags(true));
+  Node* literal = NewNode(op, literals_array, literal_index, constants);
   PrepareFrameState(literal, expr->CreateLiteralId(),
                     OutputFrameStateCombine::Push());
 
index 611b5c9..3ebb6bc 100644 (file)
@@ -422,6 +422,20 @@ void JSGenericLowering::LowerJSCreateClosure(Node* node) {
 }
 
 
+void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
+  int literal_flags = OpParameter<int>(node->op());
+  node->InsertInput(zone(), 3, jsgraph()->SmiConstant(literal_flags));
+  ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
+}
+
+
+void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
+  int literal_flags = OpParameter<int>(node->op());
+  node->InsertInput(zone(), 3, jsgraph()->SmiConstant(literal_flags));
+  ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
+}
+
+
 void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
   Unique<String> name = OpParameter<Unique<String>>(node);
   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(name));
index c465720..b299e8b 100644 (file)
@@ -6,10 +6,8 @@
 
 #include <stack>
 
-#include "src/code-factory.h"
 #include "src/compiler/access-builder.h"
 #include "src/compiler/js-graph.h"
-#include "src/compiler/linkage.h"
 #include "src/compiler/node-matchers.h"
 #include "src/compiler/node-properties.h"
 #include "src/compiler/operator-properties.h"
@@ -30,10 +28,6 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
   switch (f->function_id) {
     case Runtime::kInlineConstructDouble:
       return ReduceConstructDouble(node);
-    case Runtime::kInlineCreateArrayLiteral:
-      return ReduceCreateArrayLiteral(node);
-    case Runtime::kInlineCreateObjectLiteral:
-      return ReduceCreateObjectLiteral(node);
     case Runtime::kInlineDeoptimizeNow:
       return ReduceDeoptimizeNow(node);
     case Runtime::kInlineDoubleHi:
@@ -100,64 +94,6 @@ Reduction JSIntrinsicLowering::ReduceConstructDouble(Node* node) {
 }
 
 
-Reduction JSIntrinsicLowering::ReduceCreateArrayLiteral(Node* node) {
-  HeapObjectMatcher<FixedArray> mconst(NodeProperties::GetValueInput(node, 2));
-  NumberMatcher mflags(NodeProperties::GetValueInput(node, 3));
-  int length = mconst.Value().handle()->length();
-  int flags = FastD2I(mflags.Value());
-
-  // Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
-  // initial length limit for arrays with "fast" elements kind.
-  if ((flags & ArrayLiteral::kShallowElements) != 0 &&
-      length < JSObject::kInitialMaxFastElementArray) {
-    Isolate* isolate = jsgraph()->isolate();
-    Callable callable = CodeFactory::FastCloneShallowArray(isolate);
-    CallDescriptor* desc = Linkage::GetStubCallDescriptor(
-        isolate, graph()->zone(), callable.descriptor(), 0,
-        (OperatorProperties::GetFrameStateInputCount(node->op()) != 0)
-            ? CallDescriptor::kNeedsFrameState
-            : CallDescriptor::kNoFlags);
-    const Operator* new_op = common()->Call(desc);
-    Node* stub_code = jsgraph()->HeapConstant(callable.code());
-    node->RemoveInput(3);  // Remove flags input from node.
-    node->InsertInput(graph()->zone(), 0, stub_code);
-    node->set_op(new_op);
-    return Changed(node);
-  }
-
-  return NoChange();
-}
-
-
-Reduction JSIntrinsicLowering::ReduceCreateObjectLiteral(Node* node) {
-  HeapObjectMatcher<FixedArray> mconst(NodeProperties::GetValueInput(node, 2));
-  NumberMatcher mflags(NodeProperties::GetValueInput(node, 3));
-  // Constants are pairs, see ObjectLiteral::properties_count().
-  int length = mconst.Value().handle()->length() / 2;
-  int flags = FastD2I(mflags.Value());
-
-  // Use the FastCloneShallowObjectStub only for shallow boilerplates without
-  // elements up to the number of properties that the stubs can handle.
-  if ((flags & ObjectLiteral::kShallowProperties) != 0 &&
-      length <= FastCloneShallowObjectStub::kMaximumClonedProperties) {
-    Isolate* isolate = jsgraph()->isolate();
-    Callable callable = CodeFactory::FastCloneShallowObject(isolate, length);
-    CallDescriptor* desc = Linkage::GetStubCallDescriptor(
-        isolate, graph()->zone(), callable.descriptor(), 0,
-        (OperatorProperties::GetFrameStateInputCount(node->op()) != 0)
-            ? CallDescriptor::kNeedsFrameState
-            : CallDescriptor::kNoFlags);
-    const Operator* new_op = common()->Call(desc);
-    Node* stub_code = jsgraph()->HeapConstant(callable.code());
-    node->InsertInput(graph()->zone(), 0, stub_code);
-    node->set_op(new_op);
-    return Changed(node);
-  }
-
-  return NoChange();
-}
-
-
 Reduction JSIntrinsicLowering::ReduceDeoptimizeNow(Node* node) {
   // TODO(jarin): This should not depend on the global flag.
   if (!FLAG_turbo_deoptimization) return NoChange();
index 113e410..a0e773d 100644 (file)
@@ -29,8 +29,6 @@ class JSIntrinsicLowering final : public Reducer {
 
  private:
   Reduction ReduceConstructDouble(Node* node);
-  Reduction ReduceCreateArrayLiteral(Node* node);
-  Reduction ReduceCreateObjectLiteral(Node* node);
   Reduction ReduceDeoptimizeNow(Node* node);
   Reduction ReduceDoubleHi(Node* node);
   Reduction ReduceDoubleLo(Node* node);
index 91aa271..63a0d56 100644 (file)
@@ -465,6 +465,24 @@ const Operator* JSOperatorBuilder::CreateClosure(
 }
 
 
+const Operator* JSOperatorBuilder::CreateLiteralArray(int literal_flags) {
+  return new (zone()) Operator1<int>(                            // --
+      IrOpcode::kJSCreateLiteralArray, Operator::kNoProperties,  // opcode
+      "JSCreateLiteralArray",                                    // name
+      3, 1, 1, 1, 1, 2,                                          // counts
+      literal_flags);                                            // parameter
+}
+
+
+const Operator* JSOperatorBuilder::CreateLiteralObject(int literal_flags) {
+  return new (zone()) Operator1<int>(                             // --
+      IrOpcode::kJSCreateLiteralObject, Operator::kNoProperties,  // opcode
+      "JSCreateLiteralObject",                                    // name
+      3, 1, 1, 1, 1, 2,                                           // counts
+      literal_flags);                                             // parameter
+}
+
+
 const Operator* JSOperatorBuilder::CreateCatchContext(
     const Unique<String>& name) {
   return new (zone()) Operator1<Unique<String>>(                 // --
index bdb0c9c..739de6a 100644 (file)
@@ -270,6 +270,8 @@ class JSOperatorBuilder final : public ZoneObject {
   const Operator* Create();
   const Operator* CreateClosure(Handle<SharedFunctionInfo> shared_info,
                                 PretenureFlag pretenure);
+  const Operator* CreateLiteralArray(int literal_flags);
+  const Operator* CreateLiteralObject(int literal_flags);
 
   const Operator* CallFunction(size_t arity, CallFunctionFlags flags);
   const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
index 554ef75..8e93d52 100644 (file)
@@ -951,6 +951,64 @@ Reduction JSTypedLowering::ReduceJSCreateClosure(Node* node) {
 }
 
 
+Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSCreateLiteralArray, node->opcode());
+  HeapObjectMatcher<FixedArray> mconst(NodeProperties::GetValueInput(node, 2));
+  int length = mconst.Value().handle()->length();
+  int flags = OpParameter<int>(node->op());
+
+  // Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
+  // initial length limit for arrays with "fast" elements kind.
+  if ((flags & ArrayLiteral::kShallowElements) != 0 &&
+      length < JSObject::kInitialMaxFastElementArray) {
+    Isolate* isolate = jsgraph()->isolate();
+    Callable callable = CodeFactory::FastCloneShallowArray(isolate);
+    CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+        isolate, graph()->zone(), callable.descriptor(), 0,
+        (OperatorProperties::GetFrameStateInputCount(node->op()) != 0)
+            ? CallDescriptor::kNeedsFrameState
+            : CallDescriptor::kNoFlags);
+    const Operator* new_op = common()->Call(desc);
+    Node* stub_code = jsgraph()->HeapConstant(callable.code());
+    node->InsertInput(graph()->zone(), 0, stub_code);
+    node->set_op(new_op);
+    return Changed(node);
+  }
+
+  return NoChange();
+}
+
+
+Reduction JSTypedLowering::ReduceJSCreateLiteralObject(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSCreateLiteralObject, node->opcode());
+  HeapObjectMatcher<FixedArray> mconst(NodeProperties::GetValueInput(node, 2));
+  // Constants are pairs, see ObjectLiteral::properties_count().
+  int length = mconst.Value().handle()->length() / 2;
+  int flags = OpParameter<int>(node->op());
+
+  // Use the FastCloneShallowObjectStub only for shallow boilerplates without
+  // elements up to the number of properties that the stubs can handle.
+  if ((flags & ObjectLiteral::kShallowProperties) != 0 &&
+      length <= FastCloneShallowObjectStub::kMaximumClonedProperties) {
+    Isolate* isolate = jsgraph()->isolate();
+    Callable callable = CodeFactory::FastCloneShallowObject(isolate, length);
+    CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+        isolate, graph()->zone(), callable.descriptor(), 0,
+        (OperatorProperties::GetFrameStateInputCount(node->op()) != 0)
+            ? CallDescriptor::kNeedsFrameState
+            : CallDescriptor::kNoFlags);
+    const Operator* new_op = common()->Call(desc);
+    Node* stub_code = jsgraph()->HeapConstant(callable.code());
+    node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(flags));
+    node->InsertInput(graph()->zone(), 0, stub_code);
+    node->set_op(new_op);
+    return Changed(node);
+  }
+
+  return NoChange();
+}
+
+
 Reduction JSTypedLowering::Reduce(Node* node) {
   // Check if the output type is a singleton.  In that case we already know the
   // result value and can simply replace the node if it's eliminable.
@@ -1039,6 +1097,10 @@ Reduction JSTypedLowering::Reduce(Node* node) {
       return ReduceJSStoreContext(node);
     case IrOpcode::kJSCreateClosure:
       return ReduceJSCreateClosure(node);
+    case IrOpcode::kJSCreateLiteralArray:
+      return ReduceJSCreateLiteralArray(node);
+    case IrOpcode::kJSCreateLiteralObject:
+      return ReduceJSCreateLiteralObject(node);
     default:
       break;
   }
index 7f4b49e..855de8a 100644 (file)
@@ -55,6 +55,8 @@ class JSTypedLowering final : public Reducer {
   Reduction ReduceJSToStringInput(Node* input);
   Reduction ReduceJSToString(Node* node);
   Reduction ReduceJSCreateClosure(Node* node);
+  Reduction ReduceJSCreateLiteralArray(Node* node);
+  Reduction ReduceJSCreateLiteralObject(Node* node);
   Reduction ReduceNumberBinop(Node* node, const Operator* numberOp);
   Reduction ReduceInt32Binop(Node* node, const Operator* intOp);
   Reduction ReduceUI32Shift(Node* node, Signedness left_signedness,
index b4b8e2d..29d4388 100644 (file)
@@ -123,8 +123,6 @@ bool Linkage::NeedsFrameState(Runtime::FunctionId function) {
       return false;
     case Runtime::kInlineArguments:
     case Runtime::kInlineCallFunction:
-    case Runtime::kInlineCreateArrayLiteral:
-    case Runtime::kInlineCreateObjectLiteral:
     case Runtime::kInlineDateField:
     case Runtime::kInlineDeoptimizeNow:
     case Runtime::kInlineGetPrototype:
index 39f7cdb..e5b978a 100644 (file)
 #define JS_OBJECT_OP_LIST(V) \
   V(JSCreate)                \
   V(JSCreateClosure)         \
+  V(JSCreateLiteralArray)    \
+  V(JSCreateLiteralObject)   \
   V(JSLoadProperty)          \
   V(JSLoadNamed)             \
   V(JSStoreProperty)         \
index a87a172..a36caf5 100644 (file)
@@ -48,6 +48,10 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
     case IrOpcode::kJSLessThanOrEqual:
     case IrOpcode::kJSNotEqual:
 
+    // Object operations
+    case IrOpcode::kJSCreateLiteralArray:
+    case IrOpcode::kJSCreateLiteralObject:
+
     // Context operations
     case IrOpcode::kJSCreateScriptContext:
     case IrOpcode::kJSCreateWithContext:
index 0e7d31c..6fd609f 100644 (file)
@@ -1316,6 +1316,16 @@ Bounds Typer::Visitor::TypeJSCreateClosure(Node* node) {
 }
 
 
+Bounds Typer::Visitor::TypeJSCreateLiteralArray(Node* node) {
+  return Bounds(Type::None(), Type::OtherObject());
+}
+
+
+Bounds Typer::Visitor::TypeJSCreateLiteralObject(Node* node) {
+  return Bounds(Type::None(), Type::OtherObject());
+}
+
+
 Type* Typer::Visitor::JSLoadPropertyTyper(Type* object, Type* name, Typer* t) {
   // TODO(rossberg): Use range types and sized array types to filter undefined.
   if (object->IsArray() && name->Is(Type::Integral32())) {
index 733f8d7..238de2f 100644 (file)
@@ -496,6 +496,11 @@ void Verifier::Visitor::Check(Node* node) {
       // Type is Function.
       CheckUpperIs(node, Type::OtherObject());
       break;
+    case IrOpcode::kJSCreateLiteralArray:
+    case IrOpcode::kJSCreateLiteralObject:
+      // Type is OtherObject.
+      CheckUpperIs(node, Type::OtherObject());
+      break;
     case IrOpcode::kJSLoadProperty:
     case IrOpcode::kJSLoadNamed:
       // Type can be anything.
index a9a59d5..bc34306 100644 (file)
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "src/code-factory.h"
 #include "src/compiler/access-builder.h"
 #include "src/compiler/diamond.h"
 #include "src/compiler/js-graph.h"
@@ -73,57 +72,6 @@ TEST_F(JSIntrinsicLoweringTest, InlineOptimizedConstructDouble) {
 
 
 // -----------------------------------------------------------------------------
-// %_CreateArrayLiteral
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineCreateArrayLiteral) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const input2 = HeapConstant(factory()->NewFixedArray(12));
-  Node* const input3 = NumberConstant(ArrayLiteral::kShallowElements);
-  Node* const context = Parameter(2);
-  Node* const frame_state = EmptyFrameState();
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(graph()->NewNode(
-      javascript()->CallRuntime(Runtime::kInlineCreateArrayLiteral, 4), input0,
-      input1, input2, input3, context, frame_state, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(
-      r.replacement(),
-      IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
-                    CodeFactory::FastCloneShallowArray(isolate()).code())),
-             input0, input1, input2, context, frame_state, effect, control));
-}
-
-
-// -----------------------------------------------------------------------------
-// %_CreateObjectLiteral
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineCreateObjectLiteral) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const input2 = HeapConstant(factory()->NewFixedArray(2 * 6));
-  Node* const input3 = NumberConstant(ObjectLiteral::kShallowProperties);
-  Node* const context = Parameter(2);
-  Node* const frame_state = EmptyFrameState();
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(graph()->NewNode(
-      javascript()->CallRuntime(Runtime::kInlineCreateObjectLiteral, 4), input0,
-      input1, input2, input3, context, frame_state, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(
-      r.replacement(),
-      IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
-                    CodeFactory::FastCloneShallowObject(isolate(), 6).code())),
-             input0, input1, input2, input3, context, frame_state, effect,
-             control));
-}
-
-
-// -----------------------------------------------------------------------------
 // %_DoubleLo
 
 
index e269db0..aa4d81c 100644 (file)
@@ -906,6 +906,54 @@ TEST_F(JSTypedLoweringTest, JSCreateClosure) {
              effect, control));
 }
 
+
+// -----------------------------------------------------------------------------
+// JSCreateLiteralArray
+
+
+TEST_F(JSTypedLoweringTest, JSCreateLiteralArray) {
+  Node* const input0 = Parameter(0);
+  Node* const input1 = Parameter(1);
+  Node* const input2 = HeapConstant(factory()->NewFixedArray(12));
+  Node* const context = UndefinedConstant();
+  Node* const frame_state = EmptyFrameState();
+  Node* const effect = graph()->start();
+  Node* const control = graph()->start();
+  Reduction const r = Reduce(graph()->NewNode(
+      javascript()->CreateLiteralArray(ArrayLiteral::kShallowElements), input0,
+      input1, input2, context, frame_state, effect, control));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(
+      r.replacement(),
+      IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
+                    CodeFactory::FastCloneShallowArray(isolate()).code())),
+             input0, input1, input2, context, frame_state, effect, control));
+}
+
+
+// -----------------------------------------------------------------------------
+// JSCreateLiteralObject
+
+
+TEST_F(JSTypedLoweringTest, JSCreateLiteralObject) {
+  Node* const input0 = Parameter(0);
+  Node* const input1 = Parameter(1);
+  Node* const input2 = HeapConstant(factory()->NewFixedArray(2 * 6));
+  Node* const context = UndefinedConstant();
+  Node* const frame_state = EmptyFrameState();
+  Node* const effect = graph()->start();
+  Node* const control = graph()->start();
+  Reduction const r = Reduce(graph()->NewNode(
+      javascript()->CreateLiteralObject(ObjectLiteral::kShallowProperties),
+      input0, input1, input2, context, frame_state, effect, control));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(
+      r.replacement(),
+      IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
+                    CodeFactory::FastCloneShallowObject(isolate(), 6).code())),
+             input0, input1, input2, _, context, frame_state, effect, control));
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8