[turbofan] Add language mode to JSCallFunction operator.
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}
This commit is contained in:
parent
a4b7d45c7b
commit
2d827809e0
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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) {}
|
||||
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 arity_; }
|
||||
CallFunctionFlags flags() const { return flags_; }
|
||||
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_;
|
||||
}
|
||||
|
||||
bool operator==(CallFunctionParameters const&, CallFunctionParameters const&);
|
||||
bool operator!=(CallFunctionParameters const&, CallFunctionParameters const&);
|
||||
typedef BitField<unsigned, 0, 28> ArityField;
|
||||
typedef BitField<CallFunctionFlags, 28, 2> FlagsField;
|
||||
typedef BitField<LanguageMode, 30, 2> LanguageModeField;
|
||||
|
||||
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);
|
||||
|
@ -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* function = 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);
|
||||
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(), IsNumberConstant(-V8_INFINITY));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMax1) {
|
||||
Handle<JSFunction> f = MathFunction("max");
|
||||
Node* function = 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);
|
||||
Reduction r = Reduce(call);
|
||||
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(), p0);
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), p0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMax2) {
|
||||
Handle<JSFunction> f = MathFunction("max");
|
||||
Node* function = MathFunction("max");
|
||||
|
||||
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);
|
||||
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(),
|
||||
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");
|
||||
Node* function = 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);
|
||||
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");
|
||||
Node* function = 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);
|
||||
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));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user