Commit 662caac9 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] JSTypeOf, JSStrictEqual, JSStrictNotEqual and JSToBoolean are pure.

These operators are really pure on the JavaScript level, and were only
part of the effect chain to make sure we don't accidentially schedule
them right after raw allocations, which is no longer an issue since we
now have the concept of atomic regions.

R=jarin@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#35552}
parent d197ba5b
......@@ -326,9 +326,8 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
}
// Check that the {target} is still the {array_function}.
Node* check = effect =
graph()->NewNode(javascript()->StrictEqual(), target, array_function,
context, effect, control);
Node* check = graph()->NewNode(javascript()->StrictEqual(), target,
array_function, context);
control = graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
effect, control);
......@@ -344,15 +343,13 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
jsgraph()->Constant(handle(cell->value(), isolate()));
// Check that the {target} is still the {target_function}.
Node* check = effect =
graph()->NewNode(javascript()->StrictEqual(), target, target_function,
context, effect, control);
Node* check = graph()->NewNode(javascript()->StrictEqual(), target,
target_function, context);
control = graph()->NewNode(common()->DeoptimizeUnless(), check,
frame_state, effect, control);
// Specialize the JSCallFunction node to the {target_function}.
NodeProperties::ReplaceValueInput(node, target_function, 0);
NodeProperties::ReplaceEffectInput(node, effect);
NodeProperties::ReplaceControlInput(node, control);
// Try to further reduce the JSCallFunction {node}.
......@@ -454,9 +451,8 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
}
// Check that the {target} is still the {array_function}.
Node* check = effect =
graph()->NewNode(javascript()->StrictEqual(), target, array_function,
context, effect, control);
Node* check = graph()->NewNode(javascript()->StrictEqual(), target,
array_function, context);
control = graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
effect, control);
......@@ -478,9 +474,8 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
jsgraph()->Constant(handle(cell->value(), isolate()));
// Check that the {target} is still the {target_function}.
Node* check = effect =
graph()->NewNode(javascript()->StrictEqual(), target, target_function,
context, effect, control);
Node* check = graph()->NewNode(javascript()->StrictEqual(), target,
target_function, context);
control = graph()->NewNode(common()->DeoptimizeUnless(), check,
frame_state, effect, control);
......
......@@ -379,8 +379,8 @@ const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) {
#define CACHED_OP_LIST(V) \
V(Equal, Operator::kNoProperties, 2, 1) \
V(NotEqual, Operator::kNoProperties, 2, 1) \
V(StrictEqual, Operator::kNoThrow, 2, 1) \
V(StrictNotEqual, Operator::kNoThrow, 2, 1) \
V(StrictEqual, Operator::kPure, 2, 1) \
V(StrictNotEqual, Operator::kPure, 2, 1) \
V(LessThan, Operator::kNoProperties, 2, 1) \
V(GreaterThan, Operator::kNoProperties, 2, 1) \
V(LessThanOrEqual, Operator::kNoProperties, 2, 1) \
......@@ -389,13 +389,13 @@ const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) {
V(ToLength, Operator::kNoProperties, 1, 1) \
V(ToName, Operator::kNoProperties, 1, 1) \
V(ToNumber, Operator::kNoProperties, 1, 1) \
V(ToObject, Operator::kNoProperties, 1, 1) \
V(ToObject, Operator::kFoldable, 1, 1) \
V(ToString, Operator::kNoProperties, 1, 1) \
V(Yield, Operator::kNoProperties, 1, 1) \
V(Create, Operator::kEliminatable, 2, 1) \
V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \
V(HasProperty, Operator::kNoProperties, 2, 1) \
V(TypeOf, Operator::kEliminatable, 1, 1) \
V(TypeOf, Operator::kPure, 1, 1) \
V(InstanceOf, Operator::kNoProperties, 2, 1) \
V(ForInDone, Operator::kPure, 2, 1) \
V(ForInNext, Operator::kNoProperties, 4, 1) \
......@@ -541,11 +541,11 @@ const Operator* JSOperatorBuilder::Modulus(BinaryOperationHints hints) {
const Operator* JSOperatorBuilder::ToBoolean(ToBooleanHints hints) {
// TODO(turbofan): Cache most important versions of this operator.
return new (zone()) Operator1<ToBooleanHints>( //--
IrOpcode::kJSToBoolean, Operator::kEliminatable, // opcode
"JSToBoolean", // name
1, 1, 0, 1, 1, 0, // inputs/outputs
hints); // parameter
return new (zone()) Operator1<ToBooleanHints>( //--
IrOpcode::kJSToBoolean, Operator::kPure, // opcode
"JSToBoolean", // name
1, 0, 0, 1, 0, 0, // inputs/outputs
hints); // parameter
}
const Operator* JSOperatorBuilder::CallFunction(
......
......@@ -107,32 +107,6 @@ class JSBinopReduction final {
return lowering_->Changed(node_);
}
Reduction ChangeToStringComparisonOperator(const Operator* op,
bool invert = false) {
if (node_->op()->ControlInputCount() > 0) {
lowering_->RelaxControls(node_);
}
// String comparison operators need effect and control inputs, so copy them
// over.
Node* effect = NodeProperties::GetEffectInput(node_);
Node* control = NodeProperties::GetControlInput(node_);
node_->ReplaceInput(2, effect);
node_->ReplaceInput(3, control);
node_->TrimInputCount(4);
NodeProperties::ChangeOp(node_, op);
if (invert) {
// Insert a boolean-not to invert the value.
Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
node_->ReplaceUses(value);
// Note: ReplaceUses() smashes all uses, so smash it back here.
value->ReplaceInput(0, node_);
return lowering_->Replace(value);
}
return lowering_->Changed(node_);
}
Reduction ChangeToPureOperator(const Operator* op, Type* type) {
return ChangeToPureOperator(op, false, type);
}
......@@ -477,7 +451,7 @@ Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
default:
return NoChange();
}
r.ChangeToStringComparisonOperator(stringOp);
r.ChangeToPureOperator(stringOp);
return Changed(node);
}
if (r.OneInputCannotBe(Type::StringOrReceiver())) {
......@@ -531,8 +505,7 @@ Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
}
if (r.BothInputsAre(Type::String())) {
return r.ChangeToStringComparisonOperator(simplified()->StringEqual(),
invert);
return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
}
if (r.BothInputsAre(Type::Boolean())) {
return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
......@@ -611,8 +584,7 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
invert);
}
if (r.BothInputsAre(Type::String())) {
return r.ChangeToStringComparisonOperator(simplified()->StringEqual(),
invert);
return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
}
if (r.BothInputsAre(Type::NumberOrUndefined())) {
return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
......@@ -625,10 +597,8 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
Node* const input = node->InputAt(0);
Type* const input_type = NodeProperties::GetType(input);
Node* const effect = NodeProperties::GetEffectInput(node);
if (input_type->Is(Type::Boolean())) {
// JSToBoolean(x:boolean) => x
ReplaceWithValue(node, input, effect);
return Replace(input);
} else if (input_type->Is(Type::OrderedNumber())) {
// JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x,#0))
......@@ -642,11 +612,10 @@ Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
// JSToBoolean(x:string) => NumberLessThan(#0,x.length)
FieldAccess const access = AccessBuilder::ForStringLength();
Node* length = graph()->NewNode(simplified()->LoadField(access), input,
effect, graph()->start());
graph()->start(), graph()->start());
ReplaceWithValue(node, node, length);
node->ReplaceInput(0, jsgraph()->ZeroConstant());
node->ReplaceInput(1, length);
node->TrimInputCount(2);
NodeProperties::ChangeOp(node, simplified()->NumberLessThan());
return Changed(node);
}
......
......@@ -1044,7 +1044,7 @@ class RepresentationSelector {
flags, properties);
node->InsertInput(jsgraph_->zone(), 0,
jsgraph_->HeapConstant(callable.code()));
node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
}
break;
......@@ -1061,7 +1061,7 @@ class RepresentationSelector {
flags, properties);
node->InsertInput(jsgraph_->zone(), 0,
jsgraph_->HeapConstant(callable.code()));
node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
}
break;
......@@ -1080,7 +1080,7 @@ class RepresentationSelector {
flags, properties);
node->InsertInput(jsgraph_->zone(), 0,
jsgraph_->HeapConstant(callable.code()));
node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
}
break;
......
......@@ -194,12 +194,10 @@ const ElementAccess& ElementAccessOf(const Operator* op) {
V(ObjectIsReceiver, Operator::kNoProperties, 1) \
V(ObjectIsSmi, Operator::kNoProperties, 1) \
V(ObjectIsString, Operator::kNoProperties, 1) \
V(ObjectIsUndetectable, Operator::kNoProperties, 1)
#define NO_THROW_OP_LIST(V) \
V(StringEqual, Operator::kCommutative, 2) \
V(StringLessThan, Operator::kNoThrow, 2) \
V(StringLessThanOrEqual, Operator::kNoThrow, 2)
V(ObjectIsUndetectable, Operator::kNoProperties, 1) \
V(StringEqual, Operator::kCommutative, 2) \
V(StringLessThan, Operator::kNoProperties, 2) \
V(StringLessThanOrEqual, Operator::kNoProperties, 2)
struct SimplifiedOperatorGlobalCache final {
#define PURE(Name, properties, input_count) \
......@@ -212,16 +210,6 @@ struct SimplifiedOperatorGlobalCache final {
PURE_OP_LIST(PURE)
#undef PURE
#define NO_THROW(Name, properties, input_count) \
struct Name##Operator final : public Operator { \
Name##Operator() \
: Operator(IrOpcode::k##Name, Operator::kNoThrow | properties, #Name, \
input_count, 1, 1, 1, 1, 0) {} \
}; \
Name##Operator k##Name;
NO_THROW_OP_LIST(NO_THROW)
#undef NO_THROW
#define BUFFER_ACCESS(Type, type, TYPE, ctype, size) \
struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> { \
LoadBuffer##Type##Operator() \
......@@ -255,7 +243,6 @@ SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
#define GET_FROM_CACHE(Name, properties, input_count) \
const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
PURE_OP_LIST(GET_FROM_CACHE)
NO_THROW_OP_LIST(GET_FROM_CACHE)
#undef GET_FROM_CACHE
......
......@@ -150,8 +150,7 @@
'allocation-site-info': [PASS, NO_VARIANTS],
# TODO(turbofan): The escape analysis needs some investigation.
'compiler/escape-analysis-deopt-5': [PASS, NO_VARIANTS],
'compiler/escape-analysis-9': [PASS, NO_VARIANTS],
'compiler/escape-analysis-*': [PASS, NO_VARIANTS],
##############################################################################
# Too slow in debug mode with --stress-opt mode.
......
......@@ -42,8 +42,8 @@ const SharedOperator kSharedOperators[] = {
}
SHARED(Equal, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(NotEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(StrictEqual, Operator::kNoThrow, 2, 0, 1, 1, 1, 1, 0),
SHARED(StrictNotEqual, Operator::kNoThrow, 2, 0, 1, 1, 1, 1, 0),
SHARED(StrictEqual, Operator::kPure, 2, 0, 0, 0, 1, 0, 0),
SHARED(StrictNotEqual, Operator::kPure, 2, 0, 0, 0, 1, 0, 0),
SHARED(LessThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(GreaterThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
......@@ -51,11 +51,11 @@ const SharedOperator kSharedOperators[] = {
SHARED(ToNumber, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
SHARED(ToString, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
SHARED(ToName, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
SHARED(ToObject, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
SHARED(ToObject, Operator::kFoldable, 1, 1, 1, 1, 1, 1, 2),
SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1, 2),
SHARED(Create, Operator::kEliminatable, 2, 1, 1, 0, 1, 1, 0),
SHARED(HasProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(TypeOf, Operator::kEliminatable, 1, 0, 1, 0, 1, 1, 0),
SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0, 0),
SHARED(InstanceOf, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(CreateWithContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
SHARED(CreateModuleContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
......
......@@ -212,9 +212,8 @@ TEST_F(JSTypedLoweringTest, ParameterWithUndefined) {
TEST_F(JSTypedLoweringTest, JSToBooleanWithBoolean) {
Node* input = Parameter(Type::Boolean(), 0);
Node* context = Parameter(Type::Any(), 1);
Reduction r =
Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
input, context, graph()->start()));
Reduction r = Reduce(graph()->NewNode(
javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_EQ(input, r.replacement());
}
......@@ -242,9 +241,8 @@ TEST_F(JSTypedLoweringTest, JSToBooleanWithFalsish) {
zone()),
0);
Node* context = Parameter(Type::Any(), 1);
Reduction r =
Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
input, context, graph()->start()));
Reduction r = Reduce(graph()->NewNode(
javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFalseConstant());
}
......@@ -258,9 +256,8 @@ TEST_F(JSTypedLoweringTest, JSToBooleanWithTruish) {
zone()),
0);
Node* context = Parameter(Type::Any(), 1);
Reduction r =
Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
input, context, graph()->start()));
Reduction r = Reduce(graph()->NewNode(
javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsTrueConstant());
}
......@@ -269,9 +266,8 @@ TEST_F(JSTypedLoweringTest, JSToBooleanWithTruish) {
TEST_F(JSTypedLoweringTest, JSToBooleanWithNonZeroPlainNumber) {
Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0);
Node* context = Parameter(Type::Any(), 1);
Reduction r =
Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
input, context, graph()->start()));
Reduction r = Reduce(graph()->NewNode(
javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsTrueConstant());
}
......@@ -280,9 +276,8 @@ TEST_F(JSTypedLoweringTest, JSToBooleanWithNonZeroPlainNumber) {
TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumber) {
Node* input = Parameter(Type::OrderedNumber(), 0);
Node* context = Parameter(Type::Any(), 1);
Reduction r =
Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
input, context, graph()->start()));
Reduction r = Reduce(graph()->NewNode(
javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsBooleanNot(IsNumberEqual(input, IsNumberConstant(0.0))));
......@@ -292,9 +287,8 @@ TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumber) {
TEST_F(JSTypedLoweringTest, JSToBooleanWithString) {
Node* input = Parameter(Type::String(), 0);
Node* context = Parameter(Type::Any(), 1);
Reduction r =
Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
input, context, graph()->start()));
Reduction r = Reduce(graph()->NewNode(
javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
......@@ -307,9 +301,8 @@ TEST_F(JSTypedLoweringTest, JSToBooleanWithString) {
TEST_F(JSTypedLoweringTest, JSToBooleanWithAny) {
Node* input = Parameter(Type::Any(), 0);
Node* context = Parameter(Type::Any(), 1);
Reduction r =
Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
input, context, graph()->start()));
Reduction r = Reduce(graph()->NewNode(
javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_FALSE(r.Changed());
}
......@@ -391,9 +384,8 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) {
Node* const context = UndefinedConstant();
TRACED_FOREACH(Type*, type, kJSTypes) {
Node* const lhs = Parameter(type);
Reduction r =
Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, the_hole,
context, graph()->start(), graph()->start()));
Reduction r = Reduce(
graph()->NewNode(javascript()->StrictEqual(), lhs, the_hole, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFalseConstant());
}
......@@ -405,8 +397,7 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) {
Node* const rhs = Parameter(Type::Unique(), 1);
Node* const context = Parameter(Type::Any(), 2);
Reduction r =
Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, rhs, context,
graph()->start(), graph()->start()));
Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, rhs, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsReferenceEqual(Type::Unique(), lhs, rhs));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment