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)
REPLACE_STUB_CALL(NotEqual)
REPLACE_STUB_CALL(StrictEqual)
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
void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
......@@ -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) {
Node* closure = NodeProperties::GetValueInput(node, 2);
Node* effect = NodeProperties::GetEffectInput(node);
......
......@@ -15,7 +15,6 @@
#include "src/compiler/operator-properties.h"
#include "src/counters.h"
#include "src/objects-inl.h"
#include "src/type-cache.h"
namespace v8 {
namespace internal {
......@@ -23,11 +22,7 @@ namespace compiler {
JSIntrinsicLowering::JSIntrinsicLowering(Editor* editor, JSGraph* jsgraph,
DeoptimizationMode mode)
: AdvancedReducer(editor),
jsgraph_(jsgraph),
mode_(mode),
type_cache_(TypeCache::Get()) {}
: AdvancedReducer(editor), jsgraph_(jsgraph), mode_(mode) {}
Reduction JSIntrinsicLowering::Reduce(Node* node) {
if (node->opcode() != IrOpcode::kJSCallRuntime) return NoChange();
......@@ -351,16 +346,8 @@ Reduction JSIntrinsicLowering::ReduceSubString(Node* node) {
Reduction JSIntrinsicLowering::ReduceToInteger(Node* node) {
Node* value = NodeProperties::GetValueInput(node, 0);
// 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);
NodeProperties::ChangeOp(node, javascript()->ToInteger());
return Changed(node);
}
......@@ -377,38 +364,8 @@ Reduction JSIntrinsicLowering::ReduceToNumber(Node* node) {
Reduction JSIntrinsicLowering::ReduceToLength(Node* node) {
Node* value = NodeProperties::GetValueInput(node, 0);
Type* value_type = NodeProperties::GetType(value);
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);
NodeProperties::ChangeOp(node, javascript()->ToLength());
return Changed(node);
}
......
......@@ -13,7 +13,6 @@ namespace internal {
// Forward declarations.
class Callable;
class TypeCache;
namespace compiler {
......@@ -83,11 +82,9 @@ class JSIntrinsicLowering final : public AdvancedReducer {
MachineOperatorBuilder* machine() const;
SimplifiedOperatorBuilder* simplified() const;
DeoptimizationMode mode() const { return mode_; }
TypeCache const& type_cache() const { return type_cache_; }
JSGraph* const jsgraph_;
DeoptimizationMode const mode_;
TypeCache const& type_cache_;
};
} // namespace compiler
......
......@@ -385,10 +385,12 @@ const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) {
V(GreaterThan, Operator::kNoProperties, 2, 1) \
V(LessThanOrEqual, Operator::kNoProperties, 2, 1) \
V(GreaterThanOrEqual, Operator::kNoProperties, 2, 1) \
V(ToNumber, Operator::kNoProperties, 1, 1) \
V(ToString, Operator::kNoProperties, 1, 1) \
V(ToInteger, Operator::kNoProperties, 1, 1) \
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(ToString, Operator::kNoProperties, 1, 1) \
V(Yield, Operator::kNoProperties, 1, 1) \
V(Create, Operator::kEliminatable, 2, 1) \
V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \
......
......@@ -404,10 +404,12 @@ class JSOperatorBuilder final : public ZoneObject {
const Operator* Modulus(BinaryOperationHints hints);
const Operator* ToBoolean(ToBooleanHints hints);
const Operator* ToNumber();
const Operator* ToString();
const Operator* ToInteger();
const Operator* ToLength();
const Operator* ToName();
const Operator* ToNumber();
const Operator* ToObject();
const Operator* ToString();
const Operator* Yield();
const Operator* Create();
......
......@@ -644,6 +644,51 @@ Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
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) {
if (input->opcode() == IrOpcode::kJSToNumber) {
......@@ -1683,6 +1728,10 @@ Reduction JSTypedLowering::Reduce(Node* node) {
return ReduceJSModulus(node);
case IrOpcode::kJSToBoolean:
return ReduceJSToBoolean(node);
case IrOpcode::kJSToInteger:
return ReduceJSToInteger(node);
case IrOpcode::kJSToLength:
return ReduceJSToLength(node);
case IrOpcode::kJSToNumber:
return ReduceJSToNumber(node);
case IrOpcode::kJSToString:
......
......@@ -62,6 +62,8 @@ class JSTypedLowering final : public AdvancedReducer {
Reduction ReduceJSEqual(Node* node, bool invert);
Reduction ReduceJSStrictEqual(Node* node, bool invert);
Reduction ReduceJSToBoolean(Node* node);
Reduction ReduceJSToInteger(Node* node);
Reduction ReduceJSToLength(Node* node);
Reduction ReduceJSToNumberInput(Node* input);
Reduction ReduceJSToNumber(Node* node);
Reduction ReduceJSToStringInput(Node* input);
......
......@@ -96,10 +96,12 @@
#define JS_CONVERSION_UNOP_LIST(V) \
V(JSToBoolean) \
V(JSToNumber) \
V(JSToString) \
V(JSToInteger) \
V(JSToLength) \
V(JSToName) \
V(JSToObject)
V(JSToNumber) \
V(JSToObject) \
V(JSToString)
#define JS_OTHER_UNOP_LIST(V) \
V(JSTypeOf)
......
......@@ -58,6 +58,8 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
case IrOpcode::kJSCreateScriptContext:
// Conversions
case IrOpcode::kJSToInteger:
case IrOpcode::kJSToLength:
case IrOpcode::kJSToName:
case IrOpcode::kJSToNumber:
case IrOpcode::kJSToObject:
......
......@@ -421,6 +421,11 @@ Type* Typer::Visitor::ToInteger(Type* type, Typer* t) {
// ES6 section 7.1.4 ToInteger ( argument )
type = ToNumber(type, t);
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;
}
......@@ -1245,26 +1250,29 @@ Type* Typer::Visitor::TypeJSToBoolean(Node* node) {
return TypeUnaryOp(node, ToBoolean);
}
Type* Typer::Visitor::TypeJSToNumber(Node* node) {
return TypeUnaryOp(node, ToNumber);
Type* Typer::Visitor::TypeJSToInteger(Node* node) {
return TypeUnaryOp(node, ToInteger);
}
Type* Typer::Visitor::TypeJSToString(Node* node) {
return TypeUnaryOp(node, ToString);
Type* Typer::Visitor::TypeJSToLength(Node* node) {
return TypeUnaryOp(node, ToLength);
}
Type* Typer::Visitor::TypeJSToName(Node* node) {
return TypeUnaryOp(node, ToName);
}
Type* Typer::Visitor::TypeJSToNumber(Node* node) {
return TypeUnaryOp(node, ToNumber);
}
Type* Typer::Visitor::TypeJSToObject(Node* node) {
return TypeUnaryOp(node, ToObject);
}
Type* Typer::Visitor::TypeJSToString(Node* node) {
return TypeUnaryOp(node, ToString);
}
// JS object operators.
......
......@@ -492,6 +492,18 @@ void Verifier::Visitor::Check(Node* node) {
// Type is Boolean.
CheckUpperIs(node, Type::Boolean());
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:
// Type is Number.
CheckUpperIs(node, Type::Number());
......@@ -500,10 +512,6 @@ void Verifier::Visitor::Check(Node* node) {
// Type is String.
CheckUpperIs(node, Type::String());
break;
case IrOpcode::kJSToName:
// Type is Name.
CheckUpperIs(node, Type::Name());
break;
case IrOpcode::kJSToObject:
// Type is 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