[turbofan] Various cleanups.

- Decouple JSBuiltinReducer from JSTypedLowering.
- Unify JSTypedLowering::ReduceJSToXXX() lowering.
- Cleanup several includes and forward declarations.
- Unify helper methods.

TEST=cctest
R=svenpanne@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25790}
This commit is contained in:
Benedikt Meurer 2014-12-12 08:43:55 +01:00
parent c78a65967a
commit 4c583fee26
9 changed files with 295 additions and 212 deletions

View File

@ -16,8 +16,10 @@ namespace v8 {
namespace internal {
namespace compiler {
// Forward declarations.
class GraphDecorator;
class Graph : public ZoneObject {
public:
explicit Graph(Zone* zone);
@ -28,7 +30,7 @@ class Graph : public ZoneObject {
// Factories for nodes with static input counts.
Node* NewNode(const Operator* op) {
return NewNode(op, 0, static_cast<Node**>(NULL));
return NewNode(op, 0, static_cast<Node**>(nullptr));
}
Node* NewNode(const Operator* op, Node* n1) { return NewNode(op, 1, &n1); }
Node* NewNode(const Operator* op, Node* n1, Node* n2) {
@ -60,7 +62,7 @@ class Graph : public ZoneObject {
}
template <class Visitor>
void VisitNodeInputsFromEnd(Visitor* visitor);
inline void VisitNodeInputsFromEnd(Visitor* visitor);
Zone* zone() const { return zone_; }
Node* start() const { return start_; }

View File

@ -5,6 +5,7 @@
#include "src/compiler/diamond.h"
#include "src/compiler/graph-inl.h"
#include "src/compiler/js-builtin-reducer.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/node-properties-inl.h"
#include "src/types.h"
@ -96,6 +97,10 @@ class JSCallReduction {
};
JSBuiltinReducer::JSBuiltinReducer(JSGraph* jsgraph)
: jsgraph_(jsgraph), simplified_(jsgraph->zone()) {}
// ECMA-262, section 15.8.2.1.
Reduction JSBuiltinReducer::ReduceMathAbs(Node* node) {
JSCallReduction r(node);
@ -232,6 +237,19 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
return NoChange();
}
Graph* JSBuiltinReducer::graph() const { return jsgraph()->graph(); }
CommonOperatorBuilder* JSBuiltinReducer::common() const {
return jsgraph()->common();
}
MachineOperatorBuilder* JSBuiltinReducer::machine() const {
return jsgraph()->machine();
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -6,30 +6,26 @@
#define V8_COMPILER_JS_BUILTIN_REDUCER_H_
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
#include "src/compiler/simplified-operator.h"
namespace v8 {
namespace internal {
namespace compiler {
// Forward declarations.
class CommonOperatorBuilder;
class JSGraph;
class MachineOperatorBuilder;
class JSBuiltinReducer FINAL : public Reducer {
public:
explicit JSBuiltinReducer(JSGraph* jsgraph)
: jsgraph_(jsgraph), simplified_(jsgraph->zone()) {}
virtual ~JSBuiltinReducer() {}
explicit JSBuiltinReducer(JSGraph* jsgraph);
~JSBuiltinReducer() FINAL {}
virtual Reduction Reduce(Node* node) OVERRIDE;
Reduction Reduce(Node* node) FINAL;
private:
JSGraph* jsgraph() const { return jsgraph_; }
Graph* graph() const { return jsgraph_->graph(); }
CommonOperatorBuilder* common() const { return jsgraph_->common(); }
MachineOperatorBuilder* machine() const { return jsgraph_->machine(); }
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
Reduction ReduceMathAbs(Node* node);
Reduction ReduceMathSqrt(Node* node);
Reduction ReduceMathMax(Node* node);
@ -38,6 +34,12 @@ class JSBuiltinReducer FINAL : public Reducer {
Reduction ReduceMathFloor(Node* node);
Reduction ReduceMathCeil(Node* node);
JSGraph* jsgraph() const { return jsgraph_; }
Graph* graph() const;
CommonOperatorBuilder* common() const;
MachineOperatorBuilder* machine() const;
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
JSGraph* jsgraph_;
SimplifiedOperatorBuilder simplified_;
};

View File

@ -115,6 +115,7 @@ class JSGraph : public ZoneObject {
Graph* graph() { return graph_; }
Zone* zone() { return graph()->zone(); }
Isolate* isolate() { return zone()->isolate(); }
Factory* factory() { return isolate()->factory(); }
void GetCachedNodes(NodeVector* nodes);
@ -140,8 +141,6 @@ class JSGraph : public ZoneObject {
Node* ImmovableHeapConstant(Handle<HeapObject> value);
Node* NumberConstant(double value);
Factory* factory() { return isolate()->factory(); }
DISALLOW_COPY_AND_ASSIGN(JSGraph);
};

View File

@ -4,7 +4,7 @@
#include "src/compiler/access-builder.h"
#include "src/compiler/graph-inl.h"
#include "src/compiler/js-builtin-reducer.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-typed-lowering.h"
#include "src/compiler/node-aux-data-inl.h"
#include "src/compiler/node-matchers.h"
@ -32,28 +32,27 @@ static void RelaxEffects(Node* node) {
JSTypedLowering::JSTypedLowering(JSGraph* jsgraph)
: jsgraph_(jsgraph), simplified_(jsgraph->zone()) {
Factory* factory = zone()->isolate()->factory();
Handle<Object> zero = factory->NewNumber(0.0);
Handle<Object> one = factory->NewNumber(1.0);
zero_range_ = Type::Range(zero, zero, zone());
one_range_ = Type::Range(one, one, zone());
Handle<Object> thirtyone = factory->NewNumber(31.0);
zero_thirtyone_range_ = Type::Range(zero, thirtyone, zone());
Handle<Object> zero = factory()->NewNumber(0.0);
Handle<Object> one = factory()->NewNumber(1.0);
zero_range_ = Type::Range(zero, zero, graph()->zone());
one_range_ = Type::Range(one, one, graph()->zone());
Handle<Object> thirtyone = factory()->NewNumber(31.0);
zero_thirtyone_range_ = Type::Range(zero, thirtyone, graph()->zone());
// TODO(jarin): Can we have a correctification of the stupid type system?
// These stupid work-arounds are just stupid!
shifted_int32_ranges_[0] = Type::Signed32();
if (SmiValuesAre31Bits()) {
shifted_int32_ranges_[1] = Type::SignedSmall();
for (size_t k = 2; k < arraysize(shifted_int32_ranges_); ++k) {
Handle<Object> min = factory->NewNumber(kMinInt / (1 << k));
Handle<Object> max = factory->NewNumber(kMaxInt / (1 << k));
shifted_int32_ranges_[k] = Type::Range(min, max, zone());
Handle<Object> min = factory()->NewNumber(kMinInt / (1 << k));
Handle<Object> max = factory()->NewNumber(kMaxInt / (1 << k));
shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
}
} else {
for (size_t k = 1; k < arraysize(shifted_int32_ranges_); ++k) {
Handle<Object> min = factory->NewNumber(kMinInt / (1 << k));
Handle<Object> max = factory->NewNumber(kMaxInt / (1 << k));
shifted_int32_ranges_[k] = Type::Range(min, max, zone());
Handle<Object> min = factory()->NewNumber(kMinInt / (1 << k));
Handle<Object> max = factory()->NewNumber(kMaxInt / (1 << k));
shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
}
}
}
@ -69,7 +68,7 @@ Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) {
// JSOperator. This class manages the rewriting of context, control, and effect
// dependencies during lowering of a binop and contains numerous helper
// functions for matching the types of inputs to an operation.
class JSBinopReduction {
class JSBinopReduction FINAL {
public:
JSBinopReduction(JSTypedLowering* lowering, Node* node)
: lowering_(lowering),
@ -82,9 +81,10 @@ class JSBinopReduction {
node_->ReplaceInput(1, ConvertToNumber(right()));
}
void ConvertInputsToInt32(bool left_signed, bool right_signed) {
node_->ReplaceInput(0, ConvertToI32(left_signed, left()));
node_->ReplaceInput(1, ConvertToI32(right_signed, right()));
void ConvertInputsToUI32(Signedness left_signedness,
Signedness right_signedness) {
node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness));
node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness));
}
void ConvertInputsToString() {
@ -93,9 +93,9 @@ class JSBinopReduction {
}
// Convert inputs for bitwise shift operation (ES5 spec 11.7).
void ConvertInputsForShift(bool left_signed) {
node_->ReplaceInput(0, ConvertToI32(left_signed, left()));
Node* rnum = ConvertToI32(false, right());
void ConvertInputsForShift(Signedness left_signedness) {
node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness));
Node* rnum = ConvertToUI32(right(), kUnsigned);
Type* rnum_type = NodeProperties::GetBounds(rnum).upper;
if (!rnum_type->Is(lowering_->zero_thirtyone_range_)) {
rnum = graph()->NewNode(machine()->Word32And(), rnum,
@ -205,18 +205,21 @@ class JSBinopReduction {
return n;
}
Node* ConvertToI32(bool is_signed, Node* node) {
Node* ConvertToUI32(Node* node, Signedness signedness) {
// Avoid introducing too many eager NumberToXXnt32() operations.
node = ConvertToNumber(node);
Type* type = is_signed ? Type::Signed32() : Type::Unsigned32();
Type* input_type = NodeProperties::GetBounds(node).upper;
if (input_type->Is(type)) return node; // already in the value range.
const Operator* op = is_signed ? simplified()->NumberToInt32()
: simplified()->NumberToUint32();
Node* n = graph()->NewNode(op, node);
return n;
Type* type = NodeProperties::GetBounds(node).upper;
if (signedness == kSigned) {
if (!type->Is(Type::Signed32())) {
node = graph()->NewNode(simplified()->NumberToInt32(), node);
}
} else {
DCHECK_EQ(kUnsigned, signedness);
if (!type->Is(Type::Unsigned32())) {
node = graph()->NewNode(simplified()->NumberToUint32(), node);
}
}
return node;
}
void update_effect(Node* effect) {
@ -231,8 +234,8 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
// JSAdd(x:number, y:number) => NumberAdd(x, y)
return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
}
Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone());
if (r.BothInputsAre(Type::Primitive()) && r.NeitherInputCanBe(maybe_string)) {
if (r.BothInputsAre(Type::Primitive()) &&
r.NeitherInputCanBe(Type::StringOrReceiver())) {
// JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
r.ConvertInputsToNumber();
return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
@ -273,7 +276,7 @@ Reduction JSTypedLowering::ReduceJSBitwiseOr(Node* node) {
// operations
// on some platforms.
// TODO(turbofan): make this heuristic configurable for code size.
r.ConvertInputsToInt32(true, true);
r.ConvertInputsToUI32(kSigned, kSigned);
return r.ChangeToPureOperator(machine()->Word32Or(), Type::Integral32());
}
return NoChange();
@ -318,9 +321,7 @@ Reduction JSTypedLowering::ReduceNumberBinop(Node* node,
}
Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed,
bool right_signed,
const Operator* intOp) {
Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) {
JSBinopReduction r(this, node);
if (r.BothInputsAre(Type::Primitive())) {
// TODO(titzer): some Smi bitwise operations don't really require going
@ -328,18 +329,19 @@ Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed,
// operations
// on some platforms.
// TODO(turbofan): make this heuristic configurable for code size.
r.ConvertInputsToInt32(left_signed, right_signed);
r.ConvertInputsToUI32(kSigned, kSigned);
return r.ChangeToPureOperator(intOp, Type::Integral32());
}
return NoChange();
}
Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed,
const Operator* shift_op) {
Reduction JSTypedLowering::ReduceUI32Shift(Node* node,
Signedness left_signedness,
const Operator* shift_op) {
JSBinopReduction r(this, node);
if (r.BothInputsAre(Type::Primitive())) {
r.ConvertInputsForShift(left_signed);
r.ConvertInputsForShift(left_signedness);
return r.ChangeToPureOperator(shift_op, Type::Integral32());
}
return NoChange();
@ -381,8 +383,8 @@ Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
...
}
#endif
Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone());
if (r.BothInputsAre(Type::Primitive()) && r.OneInputCannotBe(maybe_string)) {
if (r.BothInputsAre(Type::Primitive()) &&
r.OneInputCannotBe(Type::StringOrReceiver())) {
const Operator* less_than;
const Operator* less_than_or_equal;
if (r.BothInputsAre(Type::Unsigned32())) {
@ -451,8 +453,7 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
return ReplaceEagerly(node, jsgraph()->BooleanConstant(!invert));
}
}
Type* string_or_number = Type::Union(Type::String(), Type::Number(), zone());
if (r.OneInputCannotBe(string_or_number)) {
if (r.OneInputCannotBe(Type::NumberOrString())) {
// For values with canonical representation (i.e. not string nor number) an
// empty type intersection means the values cannot be strictly equal.
if (!r.left_type()->Maybe(r.right_type())) {
@ -490,115 +491,6 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
}
Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
if (input->opcode() == IrOpcode::kJSToNumber) {
// Recursively try to reduce the input first.
Reduction result = ReduceJSToNumber(input);
if (result.Changed()) return result;
return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x)
}
Type* input_type = NodeProperties::GetBounds(input).upper;
if (input_type->Is(Type::Number())) {
// JSToNumber(x:number) => x
return Changed(input);
}
if (input_type->Is(Type::Undefined())) {
// JSToNumber(undefined) => #NaN
return Replace(jsgraph()->NaNConstant());
}
if (input_type->Is(Type::Null())) {
// JSToNumber(null) => #0
return Replace(jsgraph()->ZeroConstant());
}
if (input_type->Is(Type::Boolean())) {
// JSToNumber(x:boolean) => BooleanToNumber(x)
return Replace(graph()->NewNode(simplified()->BooleanToNumber(), input));
}
// TODO(turbofan): js-typed-lowering of ToNumber(x:string)
return NoChange();
}
Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
// Try to reduce the input first.
Node* const input = node->InputAt(0);
Reduction reduction = ReduceJSToNumberInput(input);
if (reduction.Changed()) {
NodeProperties::ReplaceWithValue(node, reduction.replacement());
return reduction;
}
Type* const input_type = NodeProperties::GetBounds(input).upper;
if (input_type->Is(Type::PlainPrimitive())) {
// Converting a plain primitive to a number has no observable side effects.
RelaxEffects(node);
// JSToNumber(phi(x1,...,xn,control):plain-primitive,context)
// => phi(JSToNumber(x1,no-context),...,JSToNumber(xn,no-context),control)
if (input->opcode() == IrOpcode::kPhi) {
int const input_count = input->InputCount() - 1;
Node* const control = input->InputAt(input_count);
DCHECK_LE(0, input_count);
DCHECK(NodeProperties::IsControl(control));
DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number()));
DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number()));
node->set_op(common()->Phi(kMachAnyTagged, input_count));
for (int i = 0; i < input_count; ++i) {
Node* value = input->InputAt(i);
// Recursively try to reduce the value first.
Reduction reduction = ReduceJSToNumberInput(value);
if (reduction.Changed()) {
value = reduction.replacement();
} else {
value = graph()->NewNode(javascript()->ToNumber(), value,
jsgraph()->NoContextConstant(),
graph()->start(), graph()->start());
}
if (i < node->InputCount()) {
node->ReplaceInput(i, value);
} else {
node->AppendInput(graph()->zone(), value);
}
}
if (input_count < node->InputCount()) {
node->ReplaceInput(input_count, control);
} else {
node->AppendInput(graph()->zone(), control);
}
node->TrimInputCount(input_count + 1);
}
return Changed(node);
}
return NoChange();
}
Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
if (input->opcode() == IrOpcode::kJSToString) {
// Recursively try to reduce the input first.
Reduction result = ReduceJSToStringInput(input->InputAt(0));
if (result.Changed()) {
RelaxEffects(input);
return result;
}
return Changed(input); // JSToString(JSToString(x)) => JSToString(x)
}
Type* input_type = NodeProperties::GetBounds(input).upper;
if (input_type->Is(Type::String())) {
return Changed(input); // JSToString(x:string) => x
}
if (input_type->Is(Type::Undefined())) {
return Replace(jsgraph()->HeapConstant(
graph()->zone()->isolate()->factory()->undefined_string()));
}
if (input_type->Is(Type::Null())) {
return Replace(jsgraph()->HeapConstant(
graph()->zone()->isolate()->factory()->null_string()));
}
// TODO(turbofan): js-typed-lowering of ToString(x:boolean)
// TODO(turbofan): js-typed-lowering of ToString(x:number)
return NoChange();
}
Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) {
if (input->opcode() == IrOpcode::kJSToBoolean) {
// Recursively try to reduce the input first.
@ -727,6 +619,160 @@ Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
}
Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
if (input->opcode() == IrOpcode::kJSToNumber) {
// Recursively try to reduce the input first.
Reduction result = ReduceJSToNumber(input);
if (result.Changed()) return result;
return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x)
}
Type* input_type = NodeProperties::GetBounds(input).upper;
if (input_type->Is(Type::Number())) {
// JSToNumber(x:number) => x
return Changed(input);
}
if (input_type->Is(Type::Undefined())) {
// JSToNumber(undefined) => #NaN
return Replace(jsgraph()->NaNConstant());
}
if (input_type->Is(Type::Null())) {
// JSToNumber(null) => #0
return Replace(jsgraph()->ZeroConstant());
}
if (input_type->Is(Type::Boolean())) {
// JSToNumber(x:boolean) => BooleanToNumber(x)
return Replace(graph()->NewNode(simplified()->BooleanToNumber(), input));
}
// TODO(turbofan): js-typed-lowering of ToNumber(x:string)
return NoChange();
}
Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
// Try to reduce the input first.
Node* const input = node->InputAt(0);
Reduction reduction = ReduceJSToNumberInput(input);
if (reduction.Changed()) {
NodeProperties::ReplaceWithValue(node, reduction.replacement());
return reduction;
}
Type* const input_type = NodeProperties::GetBounds(input).upper;
if (input_type->Is(Type::PlainPrimitive())) {
// Converting a plain primitive to a number has no observable side effects.
RelaxEffects(node);
if (input->opcode() == IrOpcode::kPhi) {
// JSToNumber(phi(x1,...,xn,control):plain-primitive,context)
// => phi(JSToNumber(x1,no-context),
// ...,
// JSToNumber(xn,no-context),control)
int const input_count = input->InputCount() - 1;
Node* const control = input->InputAt(input_count);
DCHECK_LE(0, input_count);
DCHECK(NodeProperties::IsControl(control));
DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number()));
DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number()));
node->set_op(common()->Phi(kMachAnyTagged, input_count));
for (int i = 0; i < input_count; ++i) {
Node* value = input->InputAt(i);
// Recursively try to reduce the value first.
Reduction reduction = ReduceJSToNumberInput(value);
if (reduction.Changed()) {
value = reduction.replacement();
} else {
// We must be very careful not to introduce cycles when pushing
// operations into phis. It is safe for {value}, since it appears
// as input to the phi that we are replacing, but it's not safe
// to simply reuse the context of the {node}. However, ToNumber()
// does not require a context anyways, so it's safe to discard it
// here and pass the dummy context.
value = graph()->NewNode(javascript()->ToNumber(), value,
jsgraph()->NoContextConstant(),
graph()->start(), graph()->start());
}
if (i < node->InputCount()) {
node->ReplaceInput(i, value);
} else {
node->AppendInput(graph()->zone(), value);
}
}
if (input_count < node->InputCount()) {
node->ReplaceInput(input_count, control);
} else {
node->AppendInput(graph()->zone(), control);
}
node->TrimInputCount(input_count + 1);
} else if (input->opcode() == IrOpcode::kSelect) {
// JSToNumber(select(c,x1,x2):plain-primitive,context)
// => select(c,JSToNumber(x1,no-context),JSToNumber(x2,no-context))
int const input_count = input->InputCount();
BranchHint const input_hint = SelectParametersOf(input->op()).hint();
DCHECK_EQ(3, input_count);
DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number()));
DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number()));
node->set_op(common()->Select(kMachAnyTagged, input_hint));
node->ReplaceInput(0, input->InputAt(0));
for (int i = 1; i < input_count; ++i) {
Node* value = input->InputAt(i);
// Recursively try to reduce the value first.
Reduction reduction = ReduceJSToNumberInput(value);
if (reduction.Changed()) {
value = reduction.replacement();
} else {
// We must be very careful not to introduce cycles when pushing
// operations into selects. It is safe for {value}, since it appears
// as input to the select that we are replacing, but it's not safe
// to simply reuse the context of the {node}. However, ToNumber()
// does not require a context anyways, so it's safe to discard it
// here and pass the dummy context.
value = graph()->NewNode(javascript()->ToNumber(), value,
jsgraph()->NoContextConstant(),
graph()->start(), graph()->start());
}
node->ReplaceInput(i, value);
}
node->TrimInputCount(input_count);
}
return Changed(node);
}
return NoChange();
}
Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
if (input->opcode() == IrOpcode::kJSToString) {
// Recursively try to reduce the input first.
Reduction result = ReduceJSToString(input);
if (result.Changed()) return result;
return Changed(input); // JSToString(JSToString(x)) => JSToString(x)
}
Type* input_type = NodeProperties::GetBounds(input).upper;
if (input_type->Is(Type::String())) {
return Changed(input); // JSToString(x:string) => x
}
if (input_type->Is(Type::Undefined())) {
return Replace(jsgraph()->HeapConstant(factory()->undefined_string()));
}
if (input_type->Is(Type::Null())) {
return Replace(jsgraph()->HeapConstant(factory()->null_string()));
}
// TODO(turbofan): js-typed-lowering of ToString(x:boolean)
// TODO(turbofan): js-typed-lowering of ToString(x:number)
return NoChange();
}
Reduction JSTypedLowering::ReduceJSToString(Node* node) {
// Try to reduce the input first.
Node* const input = node->InputAt(0);
Reduction reduction = ReduceJSToStringInput(input);
if (reduction.Changed()) {
NodeProperties::ReplaceWithValue(node, reduction.replacement());
return reduction;
}
return NoChange();
}
Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
Node* key = NodeProperties::GetValueInput(node, 1);
Node* base = NodeProperties::GetValueInput(node, 0);
@ -888,15 +934,6 @@ Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
}
static Reduction ReplaceWithReduction(Node* node, Reduction reduction) {
if (reduction.Changed()) {
NodeProperties::ReplaceWithValue(node, reduction.replacement());
return reduction;
}
return Reducer::NoChange();
}
Reduction JSTypedLowering::Reduce(Node* node) {
// Check if the output type is a singleton. In that case we already know the
// result value and can simply replace the node unless there are effects.
@ -925,15 +962,15 @@ Reduction JSTypedLowering::Reduce(Node* node) {
case IrOpcode::kJSBitwiseOr:
return ReduceJSBitwiseOr(node);
case IrOpcode::kJSBitwiseXor:
return ReduceI32Binop(node, true, true, machine()->Word32Xor());
return ReduceInt32Binop(node, machine()->Word32Xor());
case IrOpcode::kJSBitwiseAnd:
return ReduceI32Binop(node, true, true, machine()->Word32And());
return ReduceInt32Binop(node, machine()->Word32And());
case IrOpcode::kJSShiftLeft:
return ReduceI32Shift(node, true, machine()->Word32Shl());
return ReduceUI32Shift(node, kSigned, machine()->Word32Shl());
case IrOpcode::kJSShiftRight:
return ReduceI32Shift(node, true, machine()->Word32Sar());
return ReduceUI32Shift(node, kSigned, machine()->Word32Sar());
case IrOpcode::kJSShiftRightLogical:
return ReduceI32Shift(node, false, machine()->Word32Shr());
return ReduceUI32Shift(node, kUnsigned, machine()->Word32Shr());
case IrOpcode::kJSAdd:
return ReduceJSAdd(node);
case IrOpcode::kJSSubtract:
@ -961,8 +998,7 @@ Reduction JSTypedLowering::Reduce(Node* node) {
case IrOpcode::kJSToNumber:
return ReduceJSToNumber(node);
case IrOpcode::kJSToString:
return ReplaceWithReduction(node,
ReduceJSToStringInput(node->InputAt(0)));
return ReduceJSToString(node);
case IrOpcode::kJSLoadProperty:
return ReduceJSLoadProperty(node);
case IrOpcode::kJSStoreProperty:
@ -971,8 +1007,6 @@ Reduction JSTypedLowering::Reduce(Node* node) {
return ReduceJSLoadContext(node);
case IrOpcode::kJSStoreContext:
return ReduceJSStoreContext(node);
case IrOpcode::kJSCallFunction:
return JSBuiltinReducer(jsgraph()).Reduce(node);
default:
break;
}
@ -986,6 +1020,27 @@ Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) {
jsgraph()->Int32Constant(rhs));
}
Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); }
JSOperatorBuilder* JSTypedLowering::javascript() const {
return jsgraph()->javascript();
}
CommonOperatorBuilder* JSTypedLowering::common() const {
return jsgraph()->common();
}
MachineOperatorBuilder* JSTypedLowering::machine() const {
return jsgraph()->machine();
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -6,26 +6,26 @@
#define V8_COMPILER_JS_TYPED_LOWERING_H_
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
#include "src/compiler/simplified-operator.h"
namespace v8 {
namespace internal {
namespace compiler {
// Forward declarations.
class CommonOperatorBuilder;
class JSGraph;
class JSOperatorBuilder;
class MachineOperatorBuilder;
// Lowers JS-level operators to simplified operators based on types.
class JSTypedLowering FINAL : public Reducer {
public:
explicit JSTypedLowering(JSGraph* jsgraph);
~JSTypedLowering() {}
~JSTypedLowering() FINAL {}
Reduction Reduce(Node* node) OVERRIDE;
JSGraph* jsgraph() { return jsgraph_; }
Graph* graph() { return jsgraph_->graph(); }
Zone* zone() { return jsgraph_->zone(); }
Reduction Reduce(Node* node) FINAL;
private:
friend class JSBinopReduction;
@ -41,23 +41,26 @@ class JSTypedLowering FINAL : public Reducer {
Reduction ReduceJSStoreContext(Node* node);
Reduction ReduceJSEqual(Node* node, bool invert);
Reduction ReduceJSStrictEqual(Node* node, bool invert);
Reduction ReduceJSToBooleanInput(Node* input);
Reduction ReduceJSToBoolean(Node* node);
Reduction ReduceJSToNumberInput(Node* input);
Reduction ReduceJSToNumber(Node* node);
Reduction ReduceJSToStringInput(Node* input);
Reduction ReduceJSToBooleanInput(Node* input);
Reduction ReduceJSToBoolean(Node* node);
Reduction ReduceJSToString(Node* node);
Reduction ReduceNumberBinop(Node* node, const Operator* numberOp);
Reduction ReduceI32Binop(Node* node, bool left_signed, bool right_signed,
const Operator* intOp);
Reduction ReduceI32Shift(Node* node, bool left_signed,
const Operator* shift_op);
Reduction ReduceInt32Binop(Node* node, const Operator* intOp);
Reduction ReduceUI32Shift(Node* node, Signedness left_signedness,
const Operator* shift_op);
Node* Word32Shl(Node* const lhs, int32_t const rhs);
JSOperatorBuilder* javascript() { return jsgraph_->javascript(); }
CommonOperatorBuilder* common() { return jsgraph_->common(); }
Factory* factory() const;
Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
JSOperatorBuilder* javascript() const;
CommonOperatorBuilder* common() const;
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
MachineOperatorBuilder* machine() { return jsgraph_->machine(); }
MachineOperatorBuilder* machine() const;
JSGraph* jsgraph_;
SimplifiedOperatorBuilder simplified_;

View File

@ -18,6 +18,7 @@
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/instruction.h"
#include "src/compiler/instruction-selector.h"
#include "src/compiler/js-builtin-reducer.h"
#include "src/compiler/js-context-specialization.h"
#include "src/compiler/js-generic-lowering.h"
#include "src/compiler/js-inlining.h"
@ -417,11 +418,13 @@ struct TypedLoweringPhase {
SourcePosition::Unknown());
ValueNumberingReducer vn_reducer(temp_zone);
LoadElimination load_elimination;
JSTypedLowering lowering(data->jsgraph());
JSBuiltinReducer builtin_reducer(data->jsgraph());
JSTypedLowering typed_lowering(data->jsgraph());
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
GraphReducer graph_reducer(data->graph(), temp_zone);
graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&lowering);
graph_reducer.AddReducer(&builtin_reducer);
graph_reducer.AddReducer(&typed_lowering);
graph_reducer.AddReducer(&load_elimination);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.ReduceGraph();

View File

@ -231,6 +231,7 @@ namespace internal {
V(Detectable, kDetectableReceiver | kNumber | kName) \
V(Object, kDetectableObject | kUndetectable) \
V(Receiver, kObject | kProxy) \
V(StringOrReceiver, kString | kReceiver) \
V(Unique, kBoolean | kUniqueName | kNull | kUndefined | \
kReceiver) \
V(NonNumber, kUnique | kString | kInternal) \

View File

@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/v8.h"
#include "test/cctest/cctest.h"
#include "src/compiler/graph-inl.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-typed-lowering.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-properties-inl.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/typer.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
using namespace v8::internal::compiler;