[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}
This commit is contained in:
Sigurd Schneider 2018-02-22 09:16:52 +01:00 committed by Commit Bot
parent 15c0c3a8ba
commit ccbbdb93a1
6 changed files with 132 additions and 37 deletions

View File

@ -756,6 +756,8 @@ const Operator* JSOperatorBuilder::Call(size_t arity, CallFrequency frequency,
VectorSlotPair const& feedback,
ConvertReceiverMode convert_mode,
SpeculationMode speculation_mode) {
DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
feedback.IsValid());
CallParameters parameters(arity, frequency, feedback, convert_mode,
speculation_mode);
return new (zone()) Operator1<CallParameters>( // --
@ -776,6 +778,8 @@ const Operator* JSOperatorBuilder::CallWithArrayLike(CallFrequency frequency) {
const Operator* JSOperatorBuilder::CallWithSpread(
uint32_t arity, CallFrequency frequency, VectorSlotPair const& feedback,
SpeculationMode speculation_mode) {
DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
feedback.IsValid());
CallParameters parameters(arity, frequency, feedback,
ConvertReceiverMode::kAny, speculation_mode);
return new (zone()) Operator1<CallParameters>( // --

View File

@ -677,12 +677,12 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
size_t arity, CallFrequency frequency = CallFrequency(),
VectorSlotPair const& feedback = VectorSlotPair(),
ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny,
SpeculationMode speculation_mode = SpeculationMode::kAllowSpeculation);
SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation);
const Operator* CallWithArrayLike(CallFrequency frequency);
const Operator* CallWithSpread(
uint32_t arity, CallFrequency frequency = CallFrequency(),
VectorSlotPair const& feedback = VectorSlotPair(),
SpeculationMode speculation_mode = SpeculationMode::kAllowSpeculation);
SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation);
const Operator* CallRuntime(Runtime::FunctionId id);
const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
const Operator* CallRuntime(const Runtime::Function* function, size_t arity);

View File

@ -1753,7 +1753,7 @@ Reduction JSTypedLowering::ReduceJSCall(Node* node) {
if (p.convert_mode() != convert_mode) {
NodeProperties::ChangeOp(
node, javascript()->Call(p.arity(), p.frequency(), p.feedback(),
convert_mode));
convert_mode, p.speculation_mode()));
return Changed(node);
}

View File

@ -206,8 +206,8 @@ class FeedbackVector : public HeapObject {
FeedbackSlot GetTypeProfileSlot() const;
static Handle<FeedbackVector> New(Isolate* isolate,
Handle<SharedFunctionInfo> shared);
V8_EXPORT_PRIVATE static Handle<FeedbackVector> New(
Isolate* isolate, Handle<SharedFunctionInfo> shared);
static Handle<FeedbackVector> Copy(Isolate* isolate,
Handle<FeedbackVector> vector);
@ -431,8 +431,8 @@ class FeedbackMetadata : public FixedArray {
FeedbackSlotKind GetKind(FeedbackSlot slot) const;
// If {spec} is null, then it is considered empty.
static Handle<FeedbackMetadata> New(Isolate* isolate,
const FeedbackVectorSpec* spec = nullptr);
V8_EXPORT_PRIVATE static Handle<FeedbackMetadata> New(
Isolate* isolate, const FeedbackVectorSpec* spec = nullptr);
#ifdef OBJECT_PRINT
// For gdb debugging.

View File

@ -0,0 +1,84 @@
// 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.
// Flags: --allow-natives-syntax --opt --no-always-opt
(()=> {
function f(a, b, c) {
return String.prototype.indexOf.call(a, b, c);
}
f("abc", "de", 1);
f("abc", "de", 1);
%OptimizeFunctionOnNextCall(f);
f("abc", "de", {});
%OptimizeFunctionOnNextCall(f);
f("abc", "de", {});
assertOptimized(f);
})();
(()=> {
function f(a, b, c) {
return String.prototype.indexOf.apply(a, [b, c]);
}
f("abc", "de", 1);
f("abc", "de", 1);
%OptimizeFunctionOnNextCall(f);
f("abc", {}, 1);
%OptimizeFunctionOnNextCall(f);
f("abc", {}, 1);
assertOptimized(f);
})();
(()=> {
function f(a, b, c) {
return Reflect.apply(String.prototype.indexOf, a, [b, c]);
}
f("abc", "de", 1);
f("abc", "de", 1);
%OptimizeFunctionOnNextCall(f);
f({}, "de", 1);
%OptimizeFunctionOnNextCall(f);
f({}, "de", 1);
assertOptimized(f);
})();
(()=> {
function f(a, b) {
return String.fromCharCode.call(a, b);
}
f("abc", 1);
f("abc", 1);
%OptimizeFunctionOnNextCall(f);
f("abc", {});
%OptimizeFunctionOnNextCall(f);
f({}, {});
assertOptimized(f);
})();
(()=> {
function f(a, b) {
return String.fromCharCode.apply(undefined, [b, {}]);
}
f("abc", 1);
f("abc", 1);
%OptimizeFunctionOnNextCall(f);
f("abc", {});
%OptimizeFunctionOnNextCall(f);
f("abc", {});
assertOptimized(f);
})();
(()=> {
function f(a, b) {
return Reflect.apply(String.fromCharCode, a, [b, {}]);
}
f("abc", 1);
f("abc", 1);
%OptimizeFunctionOnNextCall(f);
f("abc", {});
%OptimizeFunctionOnNextCall(f);
f("abc", {});
assertOptimized(f);
})();

View File

@ -8,6 +8,8 @@
#include "src/compiler/js-call-reducer.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/simplified-operator.h"
#include "src/factory.h"
#include "src/feedback-vector.h"
#include "src/isolate.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
@ -72,6 +74,21 @@ class JSCallReducerTest : public TypedGraphTest {
string_fnc.substr(1, std::string::npos);
}
const Operator* Call(int arity) {
FeedbackVectorSpec spec(zone());
spec.AddCallICSlot();
Handle<FeedbackMetadata> metadata = FeedbackMetadata::New(isolate(), &spec);
Handle<SharedFunctionInfo> shared =
isolate()->factory()->NewSharedFunctionInfo(
isolate()->factory()->empty_string(), MaybeHandle<Code>(), false);
shared->set_feedback_metadata(*metadata);
Handle<FeedbackVector> vector = FeedbackVector::New(isolate(), shared);
VectorSlotPair feedback(vector, FeedbackSlot(0));
return javascript()->Call(arity, CallFrequency(), feedback,
ConvertReceiverMode::kAny,
SpeculationMode::kAllowSpeculation);
}
private:
JSOperatorBuilder javascript_;
CompilationDependencies deps_;
@ -180,9 +197,8 @@ TEST_F(JSCallReducerTest, MathUnaryWithNumber) {
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);
Node* call = graph()->NewNode(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())),
@ -209,9 +225,8 @@ TEST_F(JSCallReducerTest, MathBinaryWithNumber) {
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);
Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0,
p1, context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
@ -231,9 +246,8 @@ TEST_F(JSCallReducerTest, MathClz32WithUnsigned32) {
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);
Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0,
context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
@ -253,9 +267,8 @@ TEST_F(JSCallReducerTest, MathImulWithUnsigned32) {
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);
Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0,
p1, context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
@ -272,8 +285,7 @@ TEST_F(JSCallReducerTest, MathMinWithNoArguments) {
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
Node* call =
graph()->NewNode(javascript()->Call(2), jsfunction, UndefinedConstant(),
Node* call = graph()->NewNode(Call(2), jsfunction, UndefinedConstant(),
context, frame_state, effect, control);
Reduction r = Reduce(call);
@ -288,9 +300,8 @@ TEST_F(JSCallReducerTest, MathMinWithNumber) {
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);
Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0,
context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
@ -305,9 +316,8 @@ TEST_F(JSCallReducerTest, MathMinWithTwoArguments) {
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);
Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0,
p1, context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
@ -325,8 +335,7 @@ TEST_F(JSCallReducerTest, MathMaxWithNoArguments) {
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
Node* call =
graph()->NewNode(javascript()->Call(2), jsfunction, UndefinedConstant(),
Node* call = graph()->NewNode(Call(2), jsfunction, UndefinedConstant(),
context, frame_state, effect, control);
Reduction r = Reduce(call);
@ -341,9 +350,8 @@ TEST_F(JSCallReducerTest, MathMaxWithNumber) {
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);
Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0,
context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
@ -359,9 +367,8 @@ TEST_F(JSCallReducerTest, MathMaxWithTwoArguments) {
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);
Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0,
p1, context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());