Commit 10b365ab authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Introduce JSToInteger and JSToLength operators.

These operators will be easier to optimize, and we can remove some
unnecessary clutter from the intrinsic lowering.

Drive-by-cleanup: Some alpha sorting of the type conversion operator
business.

R=mstarzinger@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#35197}
parent cb7aa79b
...@@ -106,6 +106,13 @@ REPLACE_STUB_CALL(Equal) ...@@ -106,6 +106,13 @@ REPLACE_STUB_CALL(Equal)
REPLACE_STUB_CALL(NotEqual) REPLACE_STUB_CALL(NotEqual)
REPLACE_STUB_CALL(StrictEqual) REPLACE_STUB_CALL(StrictEqual)
REPLACE_STUB_CALL(StrictNotEqual) REPLACE_STUB_CALL(StrictNotEqual)
REPLACE_STUB_CALL(ToBoolean)
REPLACE_STUB_CALL(ToInteger)
REPLACE_STUB_CALL(ToLength)
REPLACE_STUB_CALL(ToNumber)
REPLACE_STUB_CALL(ToName)
REPLACE_STUB_CALL(ToObject)
REPLACE_STUB_CALL(ToString)
#undef REPLACE_STUB_CALL #undef REPLACE_STUB_CALL
void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable, void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
...@@ -144,41 +151,6 @@ void JSGenericLowering::LowerJSTypeOf(Node* node) { ...@@ -144,41 +151,6 @@ void JSGenericLowering::LowerJSTypeOf(Node* node) {
} }
void JSGenericLowering::LowerJSToBoolean(Node* node) {
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Callable callable = CodeFactory::ToBoolean(isolate());
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSToNumber(Node* node) {
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Callable callable = CodeFactory::ToNumber(isolate());
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSToString(Node* node) {
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Callable callable = CodeFactory::ToString(isolate());
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSToName(Node* node) {
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Callable callable = CodeFactory::ToName(isolate());
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSToObject(Node* node) {
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Callable callable = CodeFactory::ToObject(isolate());
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSLoadProperty(Node* node) { void JSGenericLowering::LowerJSLoadProperty(Node* node) {
Node* closure = NodeProperties::GetValueInput(node, 2); Node* closure = NodeProperties::GetValueInput(node, 2);
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "src/compiler/operator-properties.h" #include "src/compiler/operator-properties.h"
#include "src/counters.h" #include "src/counters.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
#include "src/type-cache.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -23,11 +22,7 @@ namespace compiler { ...@@ -23,11 +22,7 @@ namespace compiler {
JSIntrinsicLowering::JSIntrinsicLowering(Editor* editor, JSGraph* jsgraph, JSIntrinsicLowering::JSIntrinsicLowering(Editor* editor, JSGraph* jsgraph,
DeoptimizationMode mode) DeoptimizationMode mode)
: AdvancedReducer(editor), : AdvancedReducer(editor), jsgraph_(jsgraph), mode_(mode) {}
jsgraph_(jsgraph),
mode_(mode),
type_cache_(TypeCache::Get()) {}
Reduction JSIntrinsicLowering::Reduce(Node* node) { Reduction JSIntrinsicLowering::Reduce(Node* node) {
if (node->opcode() != IrOpcode::kJSCallRuntime) return NoChange(); if (node->opcode() != IrOpcode::kJSCallRuntime) return NoChange();
...@@ -351,16 +346,8 @@ Reduction JSIntrinsicLowering::ReduceSubString(Node* node) { ...@@ -351,16 +346,8 @@ Reduction JSIntrinsicLowering::ReduceSubString(Node* node) {
Reduction JSIntrinsicLowering::ReduceToInteger(Node* node) { Reduction JSIntrinsicLowering::ReduceToInteger(Node* node) {
Node* value = NodeProperties::GetValueInput(node, 0); NodeProperties::ChangeOp(node, javascript()->ToInteger());
return Changed(node);
// ToInteger is a no-op on integer values and -0.
Type* value_type = NodeProperties::GetType(value);
if (value_type->Is(type_cache().kIntegerOrMinusZero)) {
ReplaceWithValue(node, value);
return Replace(value);
}
return Change(node, CodeFactory::ToInteger(isolate()), 0);
} }
...@@ -377,38 +364,8 @@ Reduction JSIntrinsicLowering::ReduceToNumber(Node* node) { ...@@ -377,38 +364,8 @@ Reduction JSIntrinsicLowering::ReduceToNumber(Node* node) {
Reduction JSIntrinsicLowering::ReduceToLength(Node* node) { Reduction JSIntrinsicLowering::ReduceToLength(Node* node) {
Node* value = NodeProperties::GetValueInput(node, 0); NodeProperties::ChangeOp(node, javascript()->ToLength());
Type* value_type = NodeProperties::GetType(value); return Changed(node);
if (value_type->Is(type_cache().kIntegerOrMinusZero)) {
if (value_type->Max() <= 0.0) {
value = jsgraph()->ZeroConstant();
} else if (value_type->Min() >= kMaxSafeInteger) {
value = jsgraph()->Constant(kMaxSafeInteger);
} else {
if (value_type->Min() <= 0.0) {
value = graph()->NewNode(
common()->Select(MachineRepresentation::kTagged),
graph()->NewNode(simplified()->NumberLessThanOrEqual(), value,
jsgraph()->ZeroConstant()),
jsgraph()->ZeroConstant(), value);
value_type = Type::Range(0.0, value_type->Max(), graph()->zone());
NodeProperties::SetType(value, value_type);
}
if (value_type->Max() > kMaxSafeInteger) {
value = graph()->NewNode(
common()->Select(MachineRepresentation::kTagged),
graph()->NewNode(simplified()->NumberLessThanOrEqual(),
jsgraph()->Constant(kMaxSafeInteger), value),
jsgraph()->Constant(kMaxSafeInteger), value);
value_type =
Type::Range(value_type->Min(), kMaxSafeInteger, graph()->zone());
NodeProperties::SetType(value, value_type);
}
}
ReplaceWithValue(node, value);
return Replace(value);
}
return Change(node, CodeFactory::ToLength(isolate()), 0);
} }
......
...@@ -13,7 +13,6 @@ namespace internal { ...@@ -13,7 +13,6 @@ namespace internal {
// Forward declarations. // Forward declarations.
class Callable; class Callable;
class TypeCache;
namespace compiler { namespace compiler {
...@@ -83,11 +82,9 @@ class JSIntrinsicLowering final : public AdvancedReducer { ...@@ -83,11 +82,9 @@ class JSIntrinsicLowering final : public AdvancedReducer {
MachineOperatorBuilder* machine() const; MachineOperatorBuilder* machine() const;
SimplifiedOperatorBuilder* simplified() const; SimplifiedOperatorBuilder* simplified() const;
DeoptimizationMode mode() const { return mode_; } DeoptimizationMode mode() const { return mode_; }
TypeCache const& type_cache() const { return type_cache_; }
JSGraph* const jsgraph_; JSGraph* const jsgraph_;
DeoptimizationMode const mode_; DeoptimizationMode const mode_;
TypeCache const& type_cache_;
}; };
} // namespace compiler } // namespace compiler
......
...@@ -385,10 +385,12 @@ const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) { ...@@ -385,10 +385,12 @@ const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) {
V(GreaterThan, Operator::kNoProperties, 2, 1) \ V(GreaterThan, Operator::kNoProperties, 2, 1) \
V(LessThanOrEqual, Operator::kNoProperties, 2, 1) \ V(LessThanOrEqual, Operator::kNoProperties, 2, 1) \
V(GreaterThanOrEqual, Operator::kNoProperties, 2, 1) \ V(GreaterThanOrEqual, Operator::kNoProperties, 2, 1) \
V(ToNumber, Operator::kNoProperties, 1, 1) \ V(ToInteger, Operator::kNoProperties, 1, 1) \
V(ToString, Operator::kNoProperties, 1, 1) \ V(ToLength, Operator::kNoProperties, 1, 1) \
V(ToName, 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::kNoProperties, 1, 1) \
V(ToString, Operator::kNoProperties, 1, 1) \
V(Yield, Operator::kNoProperties, 1, 1) \ V(Yield, Operator::kNoProperties, 1, 1) \
V(Create, Operator::kEliminatable, 2, 1) \ V(Create, Operator::kEliminatable, 2, 1) \
V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \ V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \
......
...@@ -404,10 +404,12 @@ class JSOperatorBuilder final : public ZoneObject { ...@@ -404,10 +404,12 @@ class JSOperatorBuilder final : public ZoneObject {
const Operator* Modulus(BinaryOperationHints hints); const Operator* Modulus(BinaryOperationHints hints);
const Operator* ToBoolean(ToBooleanHints hints); const Operator* ToBoolean(ToBooleanHints hints);
const Operator* ToNumber(); const Operator* ToInteger();
const Operator* ToString(); const Operator* ToLength();
const Operator* ToName(); const Operator* ToName();
const Operator* ToNumber();
const Operator* ToObject(); const Operator* ToObject();
const Operator* ToString();
const Operator* Yield(); const Operator* Yield();
const Operator* Create(); const Operator* Create();
......
...@@ -644,6 +644,51 @@ Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { ...@@ -644,6 +644,51 @@ Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
return NoChange(); return NoChange();
} }
Reduction JSTypedLowering::ReduceJSToInteger(Node* node) {
Node* const input = NodeProperties::GetValueInput(node, 0);
Type* const input_type = NodeProperties::GetType(input);
if (input_type->Is(type_cache_.kIntegerOrMinusZero)) {
// JSToInteger(x:integer) => x
ReplaceWithValue(node, input);
return Replace(input);
}
return NoChange();
}
Reduction JSTypedLowering::ReduceJSToLength(Node* node) {
Node* input = NodeProperties::GetValueInput(node, 0);
Type* input_type = NodeProperties::GetType(input);
if (input_type->Is(type_cache_.kIntegerOrMinusZero)) {
if (input_type->Max() <= 0.0) {
input = jsgraph()->ZeroConstant();
} else if (input_type->Min() >= kMaxSafeInteger) {
input = jsgraph()->Constant(kMaxSafeInteger);
} else {
if (input_type->Min() <= 0.0) {
input = graph()->NewNode(
common()->Select(MachineRepresentation::kTagged),
graph()->NewNode(simplified()->NumberLessThanOrEqual(), input,
jsgraph()->ZeroConstant()),
jsgraph()->ZeroConstant(), input);
input_type = Type::Range(0.0, input_type->Max(), graph()->zone());
NodeProperties::SetType(input, input_type);
}
if (input_type->Max() > kMaxSafeInteger) {
input = graph()->NewNode(
common()->Select(MachineRepresentation::kTagged),
graph()->NewNode(simplified()->NumberLessThanOrEqual(),
jsgraph()->Constant(kMaxSafeInteger), input),
jsgraph()->Constant(kMaxSafeInteger), input);
input_type =
Type::Range(input_type->Min(), kMaxSafeInteger, graph()->zone());
NodeProperties::SetType(input, input_type);
}
}
ReplaceWithValue(node, input);
return Replace(input);
}
return NoChange();
}
Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
if (input->opcode() == IrOpcode::kJSToNumber) { if (input->opcode() == IrOpcode::kJSToNumber) {
...@@ -1683,6 +1728,10 @@ Reduction JSTypedLowering::Reduce(Node* node) { ...@@ -1683,6 +1728,10 @@ Reduction JSTypedLowering::Reduce(Node* node) {
return ReduceJSModulus(node); return ReduceJSModulus(node);
case IrOpcode::kJSToBoolean: case IrOpcode::kJSToBoolean:
return ReduceJSToBoolean(node); return ReduceJSToBoolean(node);
case IrOpcode::kJSToInteger:
return ReduceJSToInteger(node);
case IrOpcode::kJSToLength:
return ReduceJSToLength(node);
case IrOpcode::kJSToNumber: case IrOpcode::kJSToNumber:
return ReduceJSToNumber(node); return ReduceJSToNumber(node);
case IrOpcode::kJSToString: case IrOpcode::kJSToString:
......
...@@ -62,6 +62,8 @@ class JSTypedLowering final : public AdvancedReducer { ...@@ -62,6 +62,8 @@ class JSTypedLowering final : public AdvancedReducer {
Reduction ReduceJSEqual(Node* node, bool invert); Reduction ReduceJSEqual(Node* node, bool invert);
Reduction ReduceJSStrictEqual(Node* node, bool invert); Reduction ReduceJSStrictEqual(Node* node, bool invert);
Reduction ReduceJSToBoolean(Node* node); Reduction ReduceJSToBoolean(Node* node);
Reduction ReduceJSToInteger(Node* node);
Reduction ReduceJSToLength(Node* node);
Reduction ReduceJSToNumberInput(Node* input); Reduction ReduceJSToNumberInput(Node* input);
Reduction ReduceJSToNumber(Node* node); Reduction ReduceJSToNumber(Node* node);
Reduction ReduceJSToStringInput(Node* input); Reduction ReduceJSToStringInput(Node* input);
......
...@@ -96,10 +96,12 @@ ...@@ -96,10 +96,12 @@
#define JS_CONVERSION_UNOP_LIST(V) \ #define JS_CONVERSION_UNOP_LIST(V) \
V(JSToBoolean) \ V(JSToBoolean) \
V(JSToNumber) \ V(JSToInteger) \
V(JSToString) \ V(JSToLength) \
V(JSToName) \ V(JSToName) \
V(JSToObject) V(JSToNumber) \
V(JSToObject) \
V(JSToString)
#define JS_OTHER_UNOP_LIST(V) \ #define JS_OTHER_UNOP_LIST(V) \
V(JSTypeOf) V(JSTypeOf)
......
...@@ -58,6 +58,8 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) { ...@@ -58,6 +58,8 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
case IrOpcode::kJSCreateScriptContext: case IrOpcode::kJSCreateScriptContext:
// Conversions // Conversions
case IrOpcode::kJSToInteger:
case IrOpcode::kJSToLength:
case IrOpcode::kJSToName: case IrOpcode::kJSToName:
case IrOpcode::kJSToNumber: case IrOpcode::kJSToNumber:
case IrOpcode::kJSToObject: case IrOpcode::kJSToObject:
......
...@@ -421,6 +421,11 @@ Type* Typer::Visitor::ToInteger(Type* type, Typer* t) { ...@@ -421,6 +421,11 @@ Type* Typer::Visitor::ToInteger(Type* type, Typer* t) {
// ES6 section 7.1.4 ToInteger ( argument ) // ES6 section 7.1.4 ToInteger ( argument )
type = ToNumber(type, t); type = ToNumber(type, t);
if (type->Is(t->cache_.kIntegerOrMinusZero)) return type; if (type->Is(t->cache_.kIntegerOrMinusZero)) return type;
if (type->Is(t->cache_.kIntegerOrMinusZeroOrNaN)) {
return Type::Union(
Type::Intersect(type, t->cache_.kIntegerOrMinusZero, t->zone()),
t->cache_.kSingletonZero, t->zone());
}
return t->cache_.kIntegerOrMinusZero; return t->cache_.kIntegerOrMinusZero;
} }
...@@ -1245,26 +1250,29 @@ Type* Typer::Visitor::TypeJSToBoolean(Node* node) { ...@@ -1245,26 +1250,29 @@ Type* Typer::Visitor::TypeJSToBoolean(Node* node) {
return TypeUnaryOp(node, ToBoolean); return TypeUnaryOp(node, ToBoolean);
} }
Type* Typer::Visitor::TypeJSToInteger(Node* node) {
Type* Typer::Visitor::TypeJSToNumber(Node* node) { return TypeUnaryOp(node, ToInteger);
return TypeUnaryOp(node, ToNumber);
} }
Type* Typer::Visitor::TypeJSToLength(Node* node) {
Type* Typer::Visitor::TypeJSToString(Node* node) { return TypeUnaryOp(node, ToLength);
return TypeUnaryOp(node, ToString);
} }
Type* Typer::Visitor::TypeJSToName(Node* node) { Type* Typer::Visitor::TypeJSToName(Node* node) {
return TypeUnaryOp(node, ToName); return TypeUnaryOp(node, ToName);
} }
Type* Typer::Visitor::TypeJSToNumber(Node* node) {
return TypeUnaryOp(node, ToNumber);
}
Type* Typer::Visitor::TypeJSToObject(Node* node) { Type* Typer::Visitor::TypeJSToObject(Node* node) {
return TypeUnaryOp(node, ToObject); return TypeUnaryOp(node, ToObject);
} }
Type* Typer::Visitor::TypeJSToString(Node* node) {
return TypeUnaryOp(node, ToString);
}
// JS object operators. // JS object operators.
......
...@@ -492,6 +492,18 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -492,6 +492,18 @@ void Verifier::Visitor::Check(Node* node) {
// Type is Boolean. // Type is Boolean.
CheckUpperIs(node, Type::Boolean()); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kJSToInteger:
// Type is OrderedNumber.
CheckUpperIs(node, Type::OrderedNumber());
break;
case IrOpcode::kJSToLength:
// Type is OrderedNumber.
CheckUpperIs(node, Type::OrderedNumber());
break;
case IrOpcode::kJSToName:
// Type is Name.
CheckUpperIs(node, Type::Name());
break;
case IrOpcode::kJSToNumber: case IrOpcode::kJSToNumber:
// Type is Number. // Type is Number.
CheckUpperIs(node, Type::Number()); CheckUpperIs(node, Type::Number());
...@@ -500,10 +512,6 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -500,10 +512,6 @@ void Verifier::Visitor::Check(Node* node) {
// Type is String. // Type is String.
CheckUpperIs(node, Type::String()); CheckUpperIs(node, Type::String());
break; break;
case IrOpcode::kJSToName:
// Type is Name.
CheckUpperIs(node, Type::Name());
break;
case IrOpcode::kJSToObject: case IrOpcode::kJSToObject:
// Type is Receiver. // Type is Receiver.
CheckUpperIs(node, Type::Receiver()); CheckUpperIs(node, Type::Receiver());
......
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