[turbofan] Add language mode to JSCallFunction operator.
authorBenedikt Meurer <bmeurer@chromium.org>
Mon, 27 Apr 2015 10:44:47 +0000 (12:44 +0200)
committerBenedikt Meurer <bmeurer@chromium.org>
Mon, 27 Apr 2015 10:44:30 +0000 (10:44 +0000)
Also do some drive-by-cleanup to the unittests.

R=svenpanne@chromium.org

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

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

src/compiler/ast-graph-builder.cc
src/compiler/js-operator.cc
src/compiler/js-operator.h
test/unittests/compiler/js-builtin-reducer-unittest.cc

index 933f466f163368b3b03ca09ac31b513ba00fa8b8..742797c9fe7085e7a5ad5d1a02fb933494df40b5 100644 (file)
@@ -1293,8 +1293,9 @@ void AstGraphBuilder::VisitForInBody(ForInStatement* stmt) {
         JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY));
     // result is either the string key or Smi(0) indicating the property
     // is gone.
-    Node* res = NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
-                        function, obj, value);
+    Node* res = NewNode(
+        javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS, language_mode()),
+        function, obj, value);
     PrepareFrameState(res, stmt->FilterId(), OutputFrameStateCombine::Push());
     Node* property_missing =
         NewNode(javascript()->StrictEqual(), res, jsgraph()->ZeroConstant());
@@ -2196,7 +2197,8 @@ void AstGraphBuilder::VisitCall(Call* expr) {
   }
 
   // Create node to perform the function call.
-  const Operator* call = javascript()->CallFunction(args->length() + 2, flags);
+  const Operator* call =
+      javascript()->CallFunction(args->length() + 2, flags, language_mode());
   Node* value = ProcessArguments(call, args->length() + 2);
   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
@@ -2240,7 +2242,8 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
   VisitForValues(args);
 
   // Create node to perform the JS runtime call.
-  const Operator* call = javascript()->CallFunction(args->length() + 2, flags);
+  const Operator* call =
+      javascript()->CallFunction(args->length() + 2, flags, language_mode());
   Node* value = ProcessArguments(call, args->length() + 2);
   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
index 63a0d563978dea3a73f7af421f2a158b763337b8..f737b40865fecae6f7a1caaedee681d264fa57ad 100644 (file)
@@ -14,25 +14,8 @@ namespace v8 {
 namespace internal {
 namespace compiler {
 
-bool operator==(CallFunctionParameters const& lhs,
-                CallFunctionParameters const& rhs) {
-  return lhs.arity() == rhs.arity() && lhs.flags() == rhs.flags();
-}
-
-
-bool operator!=(CallFunctionParameters const& lhs,
-                CallFunctionParameters const& rhs) {
-  return !(lhs == rhs);
-}
-
-
-size_t hash_value(CallFunctionParameters const& p) {
-  return base::hash_combine(p.arity(), p.flags());
-}
-
-
 std::ostream& operator<<(std::ostream& os, CallFunctionParameters const& p) {
-  return os << p.arity() << ", " << p.flags();
+  return os << p.arity() << ", " << p.flags() << ", " << p.language_mode();
 }
 
 
@@ -354,8 +337,9 @@ CACHED_OP_LIST_WITH_LANGUAGE_MODE(CACHED_WITH_LANGUAGE_MODE)
 
 
 const Operator* JSOperatorBuilder::CallFunction(size_t arity,
-                                                CallFunctionFlags flags) {
-  CallFunctionParameters parameters(arity, flags);
+                                                CallFunctionFlags flags,
+                                                LanguageMode language_mode) {
+  CallFunctionParameters parameters(arity, flags, language_mode);
   return new (zone()) Operator1<CallFunctionParameters>(   // --
       IrOpcode::kJSCallFunction, Operator::kNoProperties,  // opcode
       "JSCallFunction",                                    // name
index 739de6a38d30961ba04fa84791dea4fc6b4e400a..6b60028d49c2e61e785cdbef2f16bcc6f9429f01 100644 (file)
@@ -21,19 +21,35 @@ struct JSOperatorGlobalCache;
 // used as a parameter by JSCallFunction operators.
 class CallFunctionParameters final {
  public:
-  CallFunctionParameters(size_t arity, CallFunctionFlags flags)
-      : arity_(arity), flags_(flags) {}
-
-  size_t arity() const { return arity_; }
-  CallFunctionFlags flags() const { return flags_; }
+  CallFunctionParameters(size_t arity, CallFunctionFlags flags,
+                         LanguageMode language_mode)
+      : bit_field_(ArityField::encode(arity) | FlagsField::encode(flags) |
+                   LanguageModeField::encode(language_mode)) {}
+
+  size_t arity() const { return ArityField::decode(bit_field_); }
+  CallFunctionFlags flags() const { return FlagsField::decode(bit_field_); }
+  LanguageMode language_mode() const {
+    return LanguageModeField::decode(bit_field_);
+  }
+
+  bool operator==(CallFunctionParameters const& that) const {
+    return this->bit_field_ == that.bit_field_;
+  }
+  bool operator!=(CallFunctionParameters const& that) const {
+    return !(*this == that);
+  }
 
  private:
-  const size_t arity_;
-  const CallFunctionFlags flags_;
-};
+  friend size_t hash_value(CallFunctionParameters const& p) {
+    return p.bit_field_;
+  }
+
+  typedef BitField<unsigned, 0, 28> ArityField;
+  typedef BitField<CallFunctionFlags, 28, 2> FlagsField;
+  typedef BitField<LanguageMode, 30, 2> LanguageModeField;
 
-bool operator==(CallFunctionParameters const&, CallFunctionParameters const&);
-bool operator!=(CallFunctionParameters const&, CallFunctionParameters const&);
+  const uint32_t bit_field_;
+};
 
 size_t hash_value(CallFunctionParameters const&);
 
@@ -273,7 +289,8 @@ class JSOperatorBuilder final : public ZoneObject {
   const Operator* CreateLiteralArray(int literal_flags);
   const Operator* CreateLiteralObject(int literal_flags);
 
-  const Operator* CallFunction(size_t arity, CallFunctionFlags flags);
+  const Operator* CallFunction(size_t arity, CallFunctionFlags flags,
+                               LanguageMode language_mode);
   const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
 
   const Operator* CallConstruct(int arguments);
index 5c508a5d4bcd37cb3cd9be15d6134e2f12b9fd46..090f6100660ca63ff006a8dbb787c0a413ca5ef5 100644 (file)
@@ -30,7 +30,7 @@ class JSBuiltinReducerTest : public TypedGraphTest {
     return reducer.Reduce(node);
   }
 
-  Handle<JSFunction> MathFunction(const char* name) {
+  Node* MathFunction(const char* name) {
     Handle<Object> m =
         JSObject::GetProperty(isolate()->global_object(),
                               isolate()->factory()->NewStringFromAsciiChecked(
@@ -39,7 +39,7 @@ class JSBuiltinReducerTest : public TypedGraphTest {
         JSObject::GetProperty(
             m, isolate()->factory()->NewStringFromAsciiChecked(name))
             .ToHandleChecked());
-    return f;
+    return HeapConstant(Unique<JSFunction>::CreateUninitialized(f));
   }
 
   JSOperatorBuilder* javascript() { return &javascript_; }
@@ -51,6 +51,15 @@ class JSBuiltinReducerTest : public TypedGraphTest {
 
 namespace {
 
+Type* const kIntegral32Types[] = {Type::UnsignedSmall(), Type::Negative32(),
+                                  Type::Unsigned31(),    Type::SignedSmall(),
+                                  Type::Signed32(),      Type::Unsigned32(),
+                                  Type::Integral32()};
+
+
+const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};
+
+
 // TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering.
 Type* const kNumberTypes[] = {
     Type::UnsignedSmall(), Type::Negative32(),  Type::Unsigned31(),
@@ -66,56 +75,55 @@ Type* const kNumberTypes[] = {
 
 
 TEST_F(JSBuiltinReducerTest, MathMax0) {
-  Handle<JSFunction> f = MathFunction("max");
-
-  Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
-  Node* call =
-      graph()->NewNode(javascript()->CallFunction(2, NO_CALL_FUNCTION_FLAGS),
-                       fun, UndefinedConstant());
-  Reduction r = Reduce(call);
-
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
-}
-
+  Node* function = MathFunction("max");
 
-TEST_F(JSBuiltinReducerTest, MathMax1) {
-  Handle<JSFunction> f = MathFunction("max");
-
-  TRACED_FOREACH(Type*, t0, kNumberTypes) {
-    Node* p0 = Parameter(t0, 0);
-    Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
-    Node* call =
-        graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
-                         fun, UndefinedConstant(), p0);
+  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+    Node* call = graph()->NewNode(
+        javascript()->CallFunction(2, NO_CALL_FUNCTION_FLAGS, language_mode),
+        function, UndefinedConstant());
     Reduction r = Reduce(call);
 
     ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), p0);
+    EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
   }
 }
 
 
-TEST_F(JSBuiltinReducerTest, MathMax2) {
-  Handle<JSFunction> f = MathFunction("max");
+TEST_F(JSBuiltinReducerTest, MathMax1) {
+  Node* function = MathFunction("max");
 
-  TRACED_FOREACH(Type*, t0, kNumberTypes) {
-    TRACED_FOREACH(Type*, t1, kNumberTypes) {
+  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+    TRACED_FOREACH(Type*, t0, kNumberTypes) {
       Node* p0 = Parameter(t0, 0);
-      Node* p1 = Parameter(t1, 1);
-      Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
       Node* call = graph()->NewNode(
-          javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun,
-          UndefinedConstant(), p0, p1);
+          javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS, language_mode),
+          function, UndefinedConstant(), p0);
       Reduction r = Reduce(call);
 
-      if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) {
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(r.replacement(), p0);
+    }
+  }
+}
+
+
+TEST_F(JSBuiltinReducerTest, MathMax2) {
+  Node* function = MathFunction("max");
+
+  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+    TRACED_FOREACH(Type*, t0, kIntegral32Types) {
+      TRACED_FOREACH(Type*, t1, kIntegral32Types) {
+        Node* p0 = Parameter(t0, 0);
+        Node* p1 = Parameter(t1, 1);
+        Node* call =
+            graph()->NewNode(javascript()->CallFunction(
+                                 4, NO_CALL_FUNCTION_FLAGS, language_mode),
+                             function, UndefinedConstant(), p0, p1);
+        Reduction r = Reduce(call);
+
         ASSERT_TRUE(r.Changed());
         EXPECT_THAT(r.replacement(),
                     IsSelect(kMachNone, IsNumberLessThan(p1, p0), p0, p1));
-      } else {
-        ASSERT_FALSE(r.Changed());
-        EXPECT_EQ(IrOpcode::kJSCallFunction, call->opcode());
       }
     }
   }
@@ -127,24 +135,21 @@ TEST_F(JSBuiltinReducerTest, MathMax2) {
 
 
 TEST_F(JSBuiltinReducerTest, MathImul) {
-  Handle<JSFunction> f = MathFunction("imul");
-
-  TRACED_FOREACH(Type*, t0, kNumberTypes) {
-    TRACED_FOREACH(Type*, t1, kNumberTypes) {
-      Node* p0 = Parameter(t0, 0);
-      Node* p1 = Parameter(t1, 1);
-      Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
-      Node* call = graph()->NewNode(
-          javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun,
-          UndefinedConstant(), p0, p1);
-      Reduction r = Reduce(call);
+  Node* function = MathFunction("imul");
+
+  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+    TRACED_FOREACH(Type*, t0, kIntegral32Types) {
+      TRACED_FOREACH(Type*, t1, kIntegral32Types) {
+        Node* p0 = Parameter(t0, 0);
+        Node* p1 = Parameter(t1, 1);
+        Node* call =
+            graph()->NewNode(javascript()->CallFunction(
+                                 4, NO_CALL_FUNCTION_FLAGS, language_mode),
+                             function, UndefinedConstant(), p0, p1);
+        Reduction r = Reduce(call);
 
-      if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) {
         ASSERT_TRUE(r.Changed());
         EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
-      } else {
-        ASSERT_FALSE(r.Changed());
-        EXPECT_EQ(IrOpcode::kJSCallFunction, call->opcode());
       }
     }
   }
@@ -156,18 +161,19 @@ TEST_F(JSBuiltinReducerTest, MathImul) {
 
 
 TEST_F(JSBuiltinReducerTest, MathFround) {
-  Handle<JSFunction> f = MathFunction("fround");
-
-  TRACED_FOREACH(Type*, t0, kNumberTypes) {
-    Node* p0 = Parameter(t0, 0);
-    Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
-    Node* call =
-        graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
-                         fun, UndefinedConstant(), p0);
-    Reduction r = Reduce(call);
+  Node* function = MathFunction("fround");
 
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
+  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+    TRACED_FOREACH(Type*, t0, kNumberTypes) {
+      Node* p0 = Parameter(t0, 0);
+      Node* call = graph()->NewNode(
+          javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS, language_mode),
+          function, UndefinedConstant(), p0);
+      Reduction r = Reduce(call);
+
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
+    }
   }
 }