aa7ccc233c
This reverts commit ccbbdb93a1
.
Reason for revert: https://logs.chromium.org/v/?s=chromium%2Fbb%2Fclient.v8%2FV8_Linux%2F23316%2F%2B%2Frecipes%2Fsteps%2FBisect_50a6e301%2F0%2Fsteps%2FRetry_-_nosse3%2F0%2Flogs%2FJSCallReducerTest.Mat..%2F0
Original change's description:
> [turbofan] Disable speculation for JSCall nodes by default
>
> Change-Id: I7360601f4e1b419cf8d35480b068418bdd700be9
> Reviewed-on: https://chromium-review.googlesource.com/928649
> Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#51467}
TBR=sigurds@chromium.org,bmeurer@chromium.org
Change-Id: I5a1988902730be9e962b17a434251db82d834b98
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/931401
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51471}
391 lines
13 KiB
C++
391 lines
13 KiB
C++
// Copyright 2018 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include <cctype>
|
|
|
|
#include "src/compilation-dependencies.h"
|
|
#include "src/compiler/js-call-reducer.h"
|
|
#include "src/compiler/js-graph.h"
|
|
#include "src/compiler/simplified-operator.h"
|
|
#include "src/isolate.h"
|
|
#include "test/unittests/compiler/graph-unittest.h"
|
|
#include "test/unittests/compiler/node-test-utils.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace compiler {
|
|
|
|
class JSCallReducerTest : public TypedGraphTest {
|
|
public:
|
|
JSCallReducerTest()
|
|
: TypedGraphTest(3), javascript_(zone()), deps_(isolate(), zone()) {}
|
|
~JSCallReducerTest() override {}
|
|
|
|
protected:
|
|
Reduction Reduce(Node* node) {
|
|
MachineOperatorBuilder machine(zone());
|
|
SimplifiedOperatorBuilder simplified(zone());
|
|
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
|
|
&machine);
|
|
// TODO(titzer): mock the GraphReducer here for better unit testing.
|
|
GraphReducer graph_reducer(zone(), graph());
|
|
|
|
JSCallReducer reducer(&graph_reducer, &jsgraph, JSCallReducer::kNoFlags,
|
|
native_context(), &deps_);
|
|
return reducer.Reduce(node);
|
|
}
|
|
|
|
JSOperatorBuilder* javascript() { return &javascript_; }
|
|
|
|
static void SetUpTestCase() {
|
|
old_flag_lazy_ = i::FLAG_lazy_deserialization;
|
|
old_flag_lazy_handler_ = i::FLAG_lazy_handler_deserialization;
|
|
i::FLAG_lazy_deserialization = false;
|
|
i::FLAG_lazy_handler_deserialization = false;
|
|
TypedGraphTest::SetUpTestCase();
|
|
}
|
|
|
|
static void TearDownTestCase() {
|
|
TypedGraphTest::TearDownTestCase();
|
|
i::FLAG_lazy_deserialization = old_flag_lazy_;
|
|
i::FLAG_lazy_handler_deserialization = old_flag_lazy_handler_;
|
|
}
|
|
|
|
Node* MathFunction(const std::string& name) {
|
|
Handle<Object> m =
|
|
JSObject::GetProperty(
|
|
isolate()->global_object(),
|
|
isolate()->factory()->NewStringFromAsciiChecked("Math"))
|
|
.ToHandleChecked();
|
|
Handle<JSFunction> f = Handle<JSFunction>::cast(
|
|
Object::GetProperty(
|
|
m, isolate()->factory()->NewStringFromAsciiChecked(name.c_str()))
|
|
.ToHandleChecked());
|
|
return HeapConstant(f);
|
|
}
|
|
|
|
std::string op_name_for(const char* fnc) {
|
|
std::string string_fnc(fnc);
|
|
char initial = std::toupper(fnc[0]);
|
|
return std::string("Number") + initial +
|
|
string_fnc.substr(1, std::string::npos);
|
|
}
|
|
|
|
private:
|
|
JSOperatorBuilder javascript_;
|
|
CompilationDependencies deps_;
|
|
|
|
static bool old_flag_lazy_;
|
|
static bool old_flag_lazy_handler_;
|
|
};
|
|
|
|
TEST_F(JSCallReducerTest, PromiseConstructorNoArgs) {
|
|
Node* promise = HeapConstant(handle(native_context()->promise_function()));
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
|
|
Node* construct =
|
|
graph()->NewNode(javascript()->Construct(2), promise, promise, context,
|
|
frame_state, effect, control);
|
|
|
|
Reduction r = Reduce(construct);
|
|
|
|
ASSERT_FALSE(r.Changed());
|
|
}
|
|
|
|
TEST_F(JSCallReducerTest, PromiseConstructorSubclass) {
|
|
Node* promise = HeapConstant(handle(native_context()->promise_function()));
|
|
Node* new_target = HeapConstant(handle(native_context()->array_function()));
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
|
|
Node* executor = UndefinedConstant();
|
|
Node* construct =
|
|
graph()->NewNode(javascript()->Construct(3), promise, executor,
|
|
new_target, context, frame_state, effect, control);
|
|
|
|
Reduction r = Reduce(construct);
|
|
|
|
ASSERT_FALSE(r.Changed());
|
|
}
|
|
|
|
TEST_F(JSCallReducerTest, PromiseConstructorBasic) {
|
|
Node* promise = HeapConstant(handle(native_context()->promise_function()));
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
|
|
Node* executor = UndefinedConstant();
|
|
Node* construct =
|
|
graph()->NewNode(javascript()->Construct(3), promise, executor, promise,
|
|
context, frame_state, effect, control);
|
|
|
|
Reduction r = Reduce(construct);
|
|
|
|
if (FLAG_experimental_inline_promise_constructor) {
|
|
ASSERT_TRUE(r.Changed());
|
|
} else {
|
|
ASSERT_FALSE(r.Changed());
|
|
}
|
|
}
|
|
|
|
// Exactly the same as PromiseConstructorBasic which expects a reduction,
|
|
// except that we invalidate the protector cell.
|
|
TEST_F(JSCallReducerTest, PromiseConstructorWithHook) {
|
|
Node* promise = HeapConstant(handle(native_context()->promise_function()));
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
|
|
Node* executor = UndefinedConstant();
|
|
Node* construct =
|
|
graph()->NewNode(javascript()->Construct(3), promise, executor, promise,
|
|
context, frame_state, effect, control);
|
|
|
|
isolate()->InvalidatePromiseHookProtector();
|
|
|
|
Reduction r = Reduce(construct);
|
|
|
|
ASSERT_FALSE(r.Changed());
|
|
}
|
|
|
|
bool JSCallReducerTest::old_flag_lazy_;
|
|
bool JSCallReducerTest::old_flag_lazy_handler_;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Math unaries
|
|
|
|
namespace {
|
|
|
|
const char* kMathUnaries[] = {
|
|
"abs", "acos", "acosh", "asin", "asinh", "atan", "cbrt",
|
|
"ceil", "cos", "cosh", "exp", "expm1", "floor", "fround",
|
|
"log", "log1p", "log10", "log2", "round", "sign", "sin",
|
|
"sinh", "sqrt", "tan", "tanh", "trunc"};
|
|
|
|
} // namespace
|
|
|
|
TEST_F(JSCallReducerTest, MathUnaryWithNumber) {
|
|
TRACED_FOREACH(const char*, fnc, kMathUnaries) {
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
Node* jsfunction = MathFunction(fnc);
|
|
Node* p0 = Parameter(Type::Any(), 0);
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(3), jsfunction, UndefinedConstant(),
|
|
p0, context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(std::string(IrOpcode::Mnemonic(r.replacement()->opcode())),
|
|
op_name_for(fnc));
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Math binaries
|
|
|
|
namespace {
|
|
|
|
const char* kMathBinaries[] = {"atan2", "pow"};
|
|
|
|
} // namespace
|
|
|
|
TEST_F(JSCallReducerTest, MathBinaryWithNumber) {
|
|
TRACED_FOREACH(const char*, fnc, kMathBinaries) {
|
|
Node* jsfunction = MathFunction(fnc);
|
|
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
Node* p0 = Parameter(Type::Any(), 0);
|
|
Node* p1 = Parameter(Type::Any(), 0);
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(4), jsfunction, UndefinedConstant(),
|
|
p0, p1, context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(std::string(IrOpcode::Mnemonic(r.replacement()->opcode())),
|
|
op_name_for(fnc));
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Math.clz32
|
|
|
|
TEST_F(JSCallReducerTest, MathClz32WithUnsigned32) {
|
|
Node* jsfunction = MathFunction("clz32");
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
|
|
Node* p0 = Parameter(Type::Unsigned32(), 0);
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(3), jsfunction, UndefinedConstant(),
|
|
p0, context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(),
|
|
IsNumberClz32(IsNumberToUint32(IsSpeculativeToNumber(p0))));
|
|
}
|
|
|
|
TEST_F(JSCallReducerTest, MathClz32WithUnsigned32NoArg) {
|
|
Node* jsfunction = MathFunction("clz32");
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(2), jsfunction, UndefinedConstant(),
|
|
context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsNumberConstant(32));
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Math.imul
|
|
|
|
TEST_F(JSCallReducerTest, MathImulWithUnsigned32) {
|
|
Node* jsfunction = MathFunction("imul");
|
|
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
Node* p0 = Parameter(Type::Unsigned32(), 0);
|
|
Node* p1 = Parameter(Type::Unsigned32(), 1);
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(4), jsfunction, UndefinedConstant(),
|
|
p0, p1, context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(std::string(IrOpcode::Mnemonic(r.replacement()->opcode())),
|
|
op_name_for("imul"));
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Math.min
|
|
|
|
TEST_F(JSCallReducerTest, MathMinWithNoArguments) {
|
|
Node* jsfunction = MathFunction("min");
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(2), jsfunction, UndefinedConstant(),
|
|
context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsNumberConstant(V8_INFINITY));
|
|
}
|
|
|
|
TEST_F(JSCallReducerTest, MathMinWithNumber) {
|
|
Node* jsfunction = MathFunction("min");
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
Node* p0 = Parameter(Type::Any(), 0);
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(3), jsfunction, UndefinedConstant(),
|
|
p0, context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsSpeculativeToNumber(p0));
|
|
}
|
|
|
|
TEST_F(JSCallReducerTest, MathMinWithTwoArguments) {
|
|
Node* jsfunction = MathFunction("min");
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
Node* p0 = Parameter(Type::Any(), 0);
|
|
Node* p1 = Parameter(Type::Any(), 1);
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(4), jsfunction, UndefinedConstant(),
|
|
p0, p1, context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsNumberMin(IsSpeculativeToNumber(p0),
|
|
IsSpeculativeToNumber(p1)));
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Math.max
|
|
|
|
TEST_F(JSCallReducerTest, MathMaxWithNoArguments) {
|
|
Node* jsfunction = MathFunction("max");
|
|
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(2), jsfunction, UndefinedConstant(),
|
|
context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
|
|
}
|
|
|
|
TEST_F(JSCallReducerTest, MathMaxWithNumber) {
|
|
Node* jsfunction = MathFunction("max");
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
Node* p0 = Parameter(Type::Any(), 0);
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(3), jsfunction, UndefinedConstant(),
|
|
p0, context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsSpeculativeToNumber(p0));
|
|
}
|
|
|
|
TEST_F(JSCallReducerTest, MathMaxWithTwoArguments) {
|
|
Node* jsfunction = MathFunction("max");
|
|
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
Node* context = UndefinedConstant();
|
|
Node* frame_state = graph()->start();
|
|
Node* p0 = Parameter(Type::Any(), 0);
|
|
Node* p1 = Parameter(Type::Any(), 1);
|
|
Node* call =
|
|
graph()->NewNode(javascript()->Call(4), jsfunction, UndefinedConstant(),
|
|
p0, p1, context, frame_state, effect, control);
|
|
Reduction r = Reduce(call);
|
|
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsNumberMax(IsSpeculativeToNumber(p0),
|
|
IsSpeculativeToNumber(p1)));
|
|
}
|
|
|
|
} // namespace compiler
|
|
} // namespace internal
|
|
} // namespace v8
|