// 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&);
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);
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(
JSObject::GetProperty(
m, isolate()->factory()->NewStringFromAsciiChecked(name))
.ToHandleChecked());
- return f;
+ return HeapConstant(Unique<JSFunction>::CreateUninitialized(f));
}
JSOperatorBuilder* javascript() { return &javascript_; }
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(),
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());
}
}
}
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());
}
}
}
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));
+ }
}
}