[turbofan] Unify the PlainPrimitive as Number treatment.
Now that we have the PlainPrimitiveToNumber operator(s), we can unify all the places where we expect a number, but can also safely handle any plain-primitive (via ToNumber truncation). Drive-by-fix: Also handle Math.min consistently with Math.max. R=jarin@chromium.org Review-Url: https://codereview.chromium.org/2064953004 Cr-Commit-Position: refs/heads/master@{#36984}
This commit is contained in:
parent
05a663e605
commit
ed0039a72e
@ -91,16 +91,131 @@ JSBuiltinReducer::JSBuiltinReducer(Editor* editor, JSGraph* jsgraph)
|
||||
jsgraph_(jsgraph),
|
||||
type_cache_(TypeCache::Get()) {}
|
||||
|
||||
// ECMA-262, section 15.8.2.11.
|
||||
// ES6 section 20.2.2.6 Math.atan ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathAtan(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.atan(a:plain-primitive) -> NumberAtan(ToNumber(a))
|
||||
Node* input = ToNumber(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->NumberAtan(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.8 Math.atan2 ( y, x )
|
||||
Reduction JSBuiltinReducer::ReduceMathAtan2(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchTwo(Type::PlainPrimitive(), Type::PlainPrimitive())) {
|
||||
// Math.atan2(a:plain-primitive,
|
||||
// b:plain-primitive) -> NumberAtan2(ToNumber(a),
|
||||
// ToNumber(b))
|
||||
Node* left = ToNumber(r.left());
|
||||
Node* right = ToNumber(r.right());
|
||||
Node* value = graph()->NewNode(simplified()->NumberAtan2(), left, right);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.10 Math.ceil ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathCeil(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.ceil(a:plain-primitive) -> NumberCeil(ToNumber(a))
|
||||
Node* input = ToNumber(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->NumberCeil(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.11 Math.clz32 ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathClz32(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.clz32(a:plain-primitive) -> NumberClz32(ToUint32(a))
|
||||
Node* input = ToUint32(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->NumberClz32(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.16 Math.floor ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathFloor(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.floor(a:plain-primitive) -> NumberFloor(ToNumber(a))
|
||||
Node* input = ToNumber(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->NumberFloor(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.17 Math.fround ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathFround(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.fround(a:plain-primitive) -> NumberFround(ToNumber(a))
|
||||
Node* input = ToNumber(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->NumberFround(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.19 Math.imul ( x, y )
|
||||
Reduction JSBuiltinReducer::ReduceMathImul(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchTwo(Type::PlainPrimitive(), Type::PlainPrimitive())) {
|
||||
// Math.imul(a:plain-primitive,
|
||||
// b:plain-primitive) -> NumberImul(ToUint32(a),
|
||||
// ToUint32(b))
|
||||
Node* left = ToUint32(r.left());
|
||||
Node* right = ToUint32(r.right());
|
||||
Node* value = graph()->NewNode(simplified()->NumberImul(), left, right);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.20 Math.log ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathLog(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.log(a:plain-primitive) -> NumberLog(ToNumber(a))
|
||||
Node* input = ToNumber(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->NumberLog(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.21 Math.log1p ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathLog1p(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.log1p(a:plain-primitive) -> NumberLog1p(ToNumber(a))
|
||||
Node* input = ToNumber(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->NumberLog1p(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.24 Math.max ( value1, value2, ...values )
|
||||
Reduction JSBuiltinReducer::ReduceMathMax(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchZero()) {
|
||||
// Math.max() -> -Infinity
|
||||
return Replace(jsgraph()->Constant(-V8_INFINITY));
|
||||
}
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// Math.max(a:number) -> a
|
||||
return Replace(r.left());
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.max(a:plain-primitive) -> ToNumber(a)
|
||||
Node* value = ToNumber(r.GetJSCallInput(0));
|
||||
return Replace(value);
|
||||
}
|
||||
if (r.InputsMatchAll(Type::Integral32())) {
|
||||
// Math.max(a:int32, b:int32, ...)
|
||||
@ -117,112 +232,28 @@ Reduction JSBuiltinReducer::ReduceMathMax(Node* node) {
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.19 Math.imul ( x, y )
|
||||
Reduction JSBuiltinReducer::ReduceMathImul(Node* node) {
|
||||
// ES6 section 20.2.2.25 Math.min ( value1, value2, ...values )
|
||||
Reduction JSBuiltinReducer::ReduceMathMin(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchTwo(Type::Number(), Type::Number())) {
|
||||
// Math.imul(a:number, b:number) -> NumberImul(NumberToUint32(a),
|
||||
// NumberToUint32(b))
|
||||
Node* a = graph()->NewNode(simplified()->NumberToUint32(), r.left());
|
||||
Node* b = graph()->NewNode(simplified()->NumberToUint32(), r.right());
|
||||
Node* value = graph()->NewNode(simplified()->NumberImul(), a, b);
|
||||
if (r.InputsMatchZero()) {
|
||||
// Math.min() -> Infinity
|
||||
return Replace(jsgraph()->Constant(V8_INFINITY));
|
||||
}
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.min(a:plain-primitive) -> ToNumber(a)
|
||||
Node* value = ToNumber(r.GetJSCallInput(0));
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.10 Math.ceil ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathCeil(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// Math.ceil(a:number) -> NumberCeil(a)
|
||||
Node* value = graph()->NewNode(simplified()->NumberCeil(), r.left());
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.11 Math.clz32 ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathClz32(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::Unsigned32())) {
|
||||
// Math.clz32(a:unsigned32) -> NumberClz32(a)
|
||||
Node* value = graph()->NewNode(simplified()->NumberClz32(), r.left());
|
||||
return Replace(value);
|
||||
}
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// Math.clz32(a:number) -> NumberClz32(NumberToUint32(a))
|
||||
Node* value = graph()->NewNode(
|
||||
simplified()->NumberClz32(),
|
||||
graph()->NewNode(simplified()->NumberToUint32(), r.left()));
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 draft 08-24-14, section 20.2.2.16.
|
||||
Reduction JSBuiltinReducer::ReduceMathFloor(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// Math.floor(a:number) -> NumberFloor(a)
|
||||
Node* value = graph()->NewNode(simplified()->NumberFloor(), r.left());
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 draft 08-24-14, section 20.2.2.17.
|
||||
Reduction JSBuiltinReducer::ReduceMathFround(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::NumberOrUndefined())) {
|
||||
// Math.fround(a:number) -> TruncateFloat64ToFloat32(a)
|
||||
Node* value =
|
||||
graph()->NewNode(machine()->TruncateFloat64ToFloat32(), r.left());
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.6 Math.atan ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathAtan(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// Math.atan(a:number) -> NumberAtan(a)
|
||||
Node* value = graph()->NewNode(simplified()->NumberAtan(), r.left());
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.8 Math.atan2 ( y, x )
|
||||
Reduction JSBuiltinReducer::ReduceMathAtan2(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchTwo(Type::Number(), Type::Number())) {
|
||||
// Math.atan2(a:number, b:number) -> NumberAtan2(a, b)
|
||||
Node* value =
|
||||
graph()->NewNode(simplified()->NumberAtan2(), r.left(), r.right());
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.20 Math.log ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathLog(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// Math.log(a:number) -> NumberLog(a)
|
||||
Node* value = graph()->NewNode(simplified()->NumberLog(), r.left());
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.21 Math.log1p ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathLog1p(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// Math.log1p(a:number) -> NumberLog1p(a)
|
||||
Node* value = graph()->NewNode(simplified()->NumberLog1p(), r.left());
|
||||
if (r.InputsMatchAll(Type::Integral32())) {
|
||||
// Math.min(a:int32, b:int32, ...)
|
||||
Node* value = r.GetJSCallInput(0);
|
||||
for (int i = 1; i < r.GetJSCallArity(); i++) {
|
||||
Node* const input = r.GetJSCallInput(i);
|
||||
value = graph()->NewNode(
|
||||
common()->Select(MachineRepresentation::kNone),
|
||||
graph()->NewNode(simplified()->NumberLessThan(), input, value), input,
|
||||
value);
|
||||
}
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
@ -231,9 +262,10 @@ Reduction JSBuiltinReducer::ReduceMathLog1p(Node* node) {
|
||||
// ES6 section 20.2.2.28 Math.round ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathRound(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// Math.round(a:number) -> NumberRound(a)
|
||||
Node* value = graph()->NewNode(simplified()->NumberRound(), r.left());
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.round(a:plain-primitive) -> NumberRound(ToNumber(a))
|
||||
Node* input = ToNumber(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->NumberRound(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
@ -242,9 +274,10 @@ Reduction JSBuiltinReducer::ReduceMathRound(Node* node) {
|
||||
// ES6 section 20.2.2.32 Math.sqrt ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathSqrt(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// Math.sqrt(a:number) -> Float64Sqrt(a)
|
||||
Node* value = graph()->NewNode(machine()->Float64Sqrt(), r.left());
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.sqrt(a:plain-primitive) -> NumberSqrt(ToNumber(a))
|
||||
Node* input = ToNumber(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->NumberSqrt(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
@ -253,9 +286,10 @@ Reduction JSBuiltinReducer::ReduceMathSqrt(Node* node) {
|
||||
// ES6 section 20.2.2.35 Math.trunc ( x )
|
||||
Reduction JSBuiltinReducer::ReduceMathTrunc(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// Math.trunc(a:number) -> NumberTrunc(a)
|
||||
Node* value = graph()->NewNode(simplified()->NumberTrunc(), r.left());
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// Math.trunc(a:plain-primitive) -> NumberTrunc(ToNumber(a))
|
||||
Node* input = ToNumber(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->NumberTrunc(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
@ -264,10 +298,10 @@ Reduction JSBuiltinReducer::ReduceMathTrunc(Node* node) {
|
||||
// ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
|
||||
Reduction JSBuiltinReducer::ReduceStringFromCharCode(Node* node) {
|
||||
JSCallReduction r(node);
|
||||
if (r.InputsMatchOne(Type::Number())) {
|
||||
// String.fromCharCode(a:number) -> StringFromCharCode(a)
|
||||
Node* value =
|
||||
graph()->NewNode(simplified()->StringFromCharCode(), r.left());
|
||||
if (r.InputsMatchOne(Type::PlainPrimitive())) {
|
||||
// String.fromCharCode(a:plain-primitive) -> StringFromCharCode(a)
|
||||
Node* input = ToNumber(r.GetJSCallInput(0));
|
||||
Node* value = graph()->NewNode(simplified()->StringFromCharCode(), input);
|
||||
return Replace(value);
|
||||
}
|
||||
return NoChange();
|
||||
@ -280,11 +314,11 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
|
||||
// Dispatch according to the BuiltinFunctionId if present.
|
||||
if (!r.HasBuiltinFunctionId()) return NoChange();
|
||||
switch (r.GetBuiltinFunctionId()) {
|
||||
case kMathMax:
|
||||
reduction = ReduceMathMax(node);
|
||||
case kMathAtan:
|
||||
reduction = ReduceMathAtan(node);
|
||||
break;
|
||||
case kMathImul:
|
||||
reduction = ReduceMathImul(node);
|
||||
case kMathAtan2:
|
||||
reduction = ReduceMathAtan2(node);
|
||||
break;
|
||||
case kMathClz32:
|
||||
reduction = ReduceMathClz32(node);
|
||||
@ -298,11 +332,8 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
|
||||
case kMathFround:
|
||||
reduction = ReduceMathFround(node);
|
||||
break;
|
||||
case kMathAtan:
|
||||
reduction = ReduceMathAtan(node);
|
||||
break;
|
||||
case kMathAtan2:
|
||||
reduction = ReduceMathAtan2(node);
|
||||
case kMathImul:
|
||||
reduction = ReduceMathImul(node);
|
||||
break;
|
||||
case kMathLog:
|
||||
reduction = ReduceMathLog(node);
|
||||
@ -310,6 +341,12 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
|
||||
case kMathLog1p:
|
||||
reduction = ReduceMathLog1p(node);
|
||||
break;
|
||||
case kMathMax:
|
||||
reduction = ReduceMathMax(node);
|
||||
break;
|
||||
case kMathMin:
|
||||
reduction = ReduceMathMin(node);
|
||||
break;
|
||||
case kMathRound:
|
||||
reduction = ReduceMathRound(node);
|
||||
break;
|
||||
@ -333,6 +370,18 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
|
||||
return reduction;
|
||||
}
|
||||
|
||||
Node* JSBuiltinReducer::ToNumber(Node* input) {
|
||||
Type* input_type = NodeProperties::GetType(input);
|
||||
if (input_type->Is(Type::Number())) return input;
|
||||
return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), input);
|
||||
}
|
||||
|
||||
Node* JSBuiltinReducer::ToUint32(Node* input) {
|
||||
input = ToNumber(input);
|
||||
Type* input_type = NodeProperties::GetType(input);
|
||||
if (input_type->Is(Type::Unsigned32())) return input;
|
||||
return graph()->NewNode(simplified()->NumberToUint32(), input);
|
||||
}
|
||||
|
||||
Graph* JSBuiltinReducer::graph() const { return jsgraph()->graph(); }
|
||||
|
||||
@ -345,11 +394,6 @@ CommonOperatorBuilder* JSBuiltinReducer::common() const {
|
||||
}
|
||||
|
||||
|
||||
MachineOperatorBuilder* JSBuiltinReducer::machine() const {
|
||||
return jsgraph()->machine();
|
||||
}
|
||||
|
||||
|
||||
SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const {
|
||||
return jsgraph()->simplified();
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ namespace compiler {
|
||||
// Forward declarations.
|
||||
class CommonOperatorBuilder;
|
||||
class JSGraph;
|
||||
class MachineOperatorBuilder;
|
||||
class SimplifiedOperatorBuilder;
|
||||
|
||||
|
||||
@ -30,27 +29,29 @@ class JSBuiltinReducer final : public AdvancedReducer {
|
||||
Reduction Reduce(Node* node) final;
|
||||
|
||||
private:
|
||||
Reduction ReduceFunctionCall(Node* node);
|
||||
Reduction ReduceMathMax(Node* node);
|
||||
Reduction ReduceMathImul(Node* node);
|
||||
Reduction ReduceMathAtan(Node* node);
|
||||
Reduction ReduceMathAtan2(Node* node);
|
||||
Reduction ReduceMathCeil(Node* node);
|
||||
Reduction ReduceMathClz32(Node* node);
|
||||
Reduction ReduceMathFloor(Node* node);
|
||||
Reduction ReduceMathFround(Node* node);
|
||||
Reduction ReduceMathAtan(Node* node);
|
||||
Reduction ReduceMathAtan2(Node* node);
|
||||
Reduction ReduceMathImul(Node* node);
|
||||
Reduction ReduceMathLog(Node* node);
|
||||
Reduction ReduceMathLog1p(Node* node);
|
||||
Reduction ReduceMathMax(Node* node);
|
||||
Reduction ReduceMathMin(Node* node);
|
||||
Reduction ReduceMathRound(Node* node);
|
||||
Reduction ReduceMathSqrt(Node* node);
|
||||
Reduction ReduceMathTrunc(Node* node);
|
||||
Reduction ReduceStringFromCharCode(Node* node);
|
||||
|
||||
Node* ToNumber(Node* value);
|
||||
Node* ToUint32(Node* value);
|
||||
|
||||
Graph* graph() const;
|
||||
JSGraph* jsgraph() const { return jsgraph_; }
|
||||
Isolate* isolate() const;
|
||||
CommonOperatorBuilder* common() const;
|
||||
MachineOperatorBuilder* machine() const;
|
||||
SimplifiedOperatorBuilder* simplified() const;
|
||||
|
||||
JSGraph* const jsgraph_;
|
||||
|
@ -45,7 +45,7 @@ class JSBinopReduction final {
|
||||
return BinaryOperationHints::kAny;
|
||||
}
|
||||
|
||||
void ConvertInputsToNumberOrUndefined(Node* frame_state) {
|
||||
void ConvertInputsToNumber(Node* frame_state) {
|
||||
// To convert the inputs to numbers, we have to provide frame states
|
||||
// for lazy bailouts in the ToNumber conversions.
|
||||
// We use a little hack here: we take the frame state before the binary
|
||||
@ -64,11 +64,11 @@ class JSBinopReduction final {
|
||||
ConvertBothInputsToNumber(&left_input, &right_input, frame_state);
|
||||
} else {
|
||||
left_input = left_is_primitive
|
||||
? ConvertPlainPrimitiveToNumberOrUndefined(left())
|
||||
? ConvertPlainPrimitiveToNumber(left())
|
||||
: ConvertSingleInputToNumber(
|
||||
left(), CreateFrameStateForLeftInput(frame_state));
|
||||
right_input = right_is_primitive
|
||||
? ConvertPlainPrimitiveToNumberOrUndefined(right())
|
||||
? ConvertPlainPrimitiveToNumber(right())
|
||||
: ConvertSingleInputToNumber(
|
||||
right(), CreateFrameStateForRightInput(
|
||||
frame_state, left_input));
|
||||
@ -281,12 +281,12 @@ class JSBinopReduction final {
|
||||
frame_state->InputAt(kFrameStateOuterStateInput));
|
||||
}
|
||||
|
||||
Node* ConvertPlainPrimitiveToNumberOrUndefined(Node* node) {
|
||||
Node* ConvertPlainPrimitiveToNumber(Node* node) {
|
||||
DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
|
||||
// Avoid inserting too many eager ToNumber() operations.
|
||||
Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
|
||||
if (reduction.Changed()) return reduction.replacement();
|
||||
if (NodeProperties::GetType(node)->Is(Type::NumberOrUndefined())) {
|
||||
if (NodeProperties::GetType(node)->Is(Type::Number())) {
|
||||
return node;
|
||||
}
|
||||
return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), node);
|
||||
@ -409,16 +409,16 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
|
||||
return r.ChangeToSpeculativeOperator(
|
||||
simplified()->SpeculativeNumberAdd(feedback));
|
||||
}
|
||||
if (r.BothInputsAre(Type::NumberOrUndefined())) {
|
||||
if (r.BothInputsAre(Type::Number())) {
|
||||
// JSAdd(x:number, y:number) => NumberAdd(x, y)
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
|
||||
r.ConvertInputsToNumberOrUndefined(frame_state);
|
||||
r.ConvertInputsToNumber(frame_state);
|
||||
return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
|
||||
}
|
||||
if (r.NeitherInputCanBe(Type::StringOrReceiver())) {
|
||||
// JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
|
||||
r.ConvertInputsToNumberOrUndefined(frame_state);
|
||||
r.ConvertInputsToNumber(frame_state);
|
||||
return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
|
||||
}
|
||||
if (r.OneInputIs(Type::String())) {
|
||||
@ -468,7 +468,7 @@ Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
|
||||
simplified()->SpeculativeNumberSubtract(feedback));
|
||||
}
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
|
||||
r.ConvertInputsToNumberOrUndefined(frame_state);
|
||||
r.ConvertInputsToNumber(frame_state);
|
||||
return r.ChangeToPureOperator(simplified()->NumberSubtract(), Type::Number());
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
|
||||
if (flags() & kDisableBinaryOpReduction) return NoChange();
|
||||
JSBinopReduction r(this, node);
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
|
||||
r.ConvertInputsToNumberOrUndefined(frame_state);
|
||||
r.ConvertInputsToNumber(frame_state);
|
||||
return r.ChangeToPureOperator(simplified()->NumberMultiply(), Type::Number());
|
||||
}
|
||||
|
||||
@ -484,7 +484,7 @@ Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
|
||||
if (flags() & kDisableBinaryOpReduction) return NoChange();
|
||||
JSBinopReduction r(this, node);
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
|
||||
r.ConvertInputsToNumberOrUndefined(frame_state);
|
||||
r.ConvertInputsToNumber(frame_state);
|
||||
return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number());
|
||||
}
|
||||
|
||||
@ -494,7 +494,7 @@ Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) {
|
||||
|
||||
JSBinopReduction r(this, node);
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
|
||||
r.ConvertInputsToNumberOrUndefined(frame_state);
|
||||
r.ConvertInputsToNumber(frame_state);
|
||||
r.ConvertInputsToUI32(kSigned, kSigned);
|
||||
return r.ChangeToPureOperator(intOp, Type::Integral32());
|
||||
}
|
||||
@ -507,7 +507,7 @@ Reduction JSTypedLowering::ReduceUI32Shift(Node* node,
|
||||
|
||||
JSBinopReduction r(this, node);
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
|
||||
r.ConvertInputsToNumberOrUndefined(frame_state);
|
||||
r.ConvertInputsToNumber(frame_state);
|
||||
r.ConvertInputsToUI32(left_signedness, kUnsigned);
|
||||
return r.ChangeToPureOperator(shift_op);
|
||||
}
|
||||
@ -553,7 +553,7 @@ Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
|
||||
} else {
|
||||
// TODO(turbofan): mixed signed/unsigned int32 comparisons.
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
|
||||
r.ConvertInputsToNumberOrUndefined(frame_state);
|
||||
r.ConvertInputsToNumber(frame_state);
|
||||
less_than = simplified()->NumberLessThan();
|
||||
less_than_or_equal = simplified()->NumberLessThanOrEqual();
|
||||
}
|
||||
@ -722,7 +722,7 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
|
||||
if (r.BothInputsAre(Type::String())) {
|
||||
return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
|
||||
}
|
||||
if (r.BothInputsAre(Type::NumberOrUndefined())) {
|
||||
if (r.BothInputsAre(Type::Number())) {
|
||||
return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
|
||||
}
|
||||
// TODO(turbofan): js-typed-lowering of StrictEqual(mixed types)
|
||||
@ -1073,7 +1073,7 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
// Convert to a number first.
|
||||
if (!value_type->Is(Type::NumberOrUndefined())) {
|
||||
if (!value_type->Is(Type::Number())) {
|
||||
Reduction number_reduction = ReduceJSToNumberInput(value);
|
||||
if (number_reduction.Changed()) {
|
||||
value = number_reduction.replacement();
|
||||
|
@ -197,11 +197,13 @@
|
||||
V(NumberClz32) \
|
||||
V(NumberCeil) \
|
||||
V(NumberFloor) \
|
||||
V(NumberFround) \
|
||||
V(NumberAtan) \
|
||||
V(NumberAtan2) \
|
||||
V(NumberLog) \
|
||||
V(NumberLog1p) \
|
||||
V(NumberRound) \
|
||||
V(NumberSqrt) \
|
||||
V(NumberTrunc) \
|
||||
V(NumberToInt32) \
|
||||
V(NumberToUint32) \
|
||||
|
@ -663,10 +663,14 @@ const Operator* RepresentationChanger::Float64OperatorFor(
|
||||
return machine()->Float64Atan();
|
||||
case IrOpcode::kNumberAtan2:
|
||||
return machine()->Float64Atan2();
|
||||
case IrOpcode::kNumberFround:
|
||||
return machine()->TruncateFloat64ToFloat32();
|
||||
case IrOpcode::kNumberLog:
|
||||
return machine()->Float64Log();
|
||||
case IrOpcode::kNumberLog1p:
|
||||
return machine()->Float64Log1p();
|
||||
case IrOpcode::kNumberSqrt:
|
||||
return machine()->Float64Sqrt();
|
||||
case IrOpcode::kNumberSilenceNaN:
|
||||
return machine()->Float64SilenceNaN();
|
||||
default:
|
||||
|
@ -611,16 +611,17 @@ class RepresentationSelector {
|
||||
|
||||
Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
|
||||
|
||||
bool InputIs(Node* node, Type* type) {
|
||||
DCHECK_EQ(1, node->InputCount());
|
||||
return GetUpperBound(node->InputAt(0))->Is(type);
|
||||
}
|
||||
|
||||
bool BothInputsAreSigned32(Node* node) {
|
||||
DCHECK_EQ(2, node->InputCount());
|
||||
return GetUpperBound(node->InputAt(0))->Is(Type::Signed32()) &&
|
||||
GetUpperBound(node->InputAt(1))->Is(Type::Signed32());
|
||||
return BothInputsAre(node, Type::Signed32());
|
||||
}
|
||||
|
||||
bool BothInputsAreUnsigned32(Node* node) {
|
||||
DCHECK_EQ(2, node->InputCount());
|
||||
return GetUpperBound(node->InputAt(0))->Is(Type::Unsigned32()) &&
|
||||
GetUpperBound(node->InputAt(1))->Is(Type::Unsigned32());
|
||||
return BothInputsAre(node, Type::Unsigned32());
|
||||
}
|
||||
|
||||
bool BothInputsAre(Node* node, Type* type) {
|
||||
@ -1393,6 +1394,12 @@ class RepresentationSelector {
|
||||
if (lower()) DeferReplacement(node, lowering->Float64Floor(node));
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kNumberFround: {
|
||||
VisitUnop(node, UseInfo::TruncatingFloat64(),
|
||||
MachineRepresentation::kFloat32);
|
||||
if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kNumberAtan2: {
|
||||
VisitBinop(node, UseInfo::TruncatingFloat64(),
|
||||
MachineRepresentation::kFloat64);
|
||||
@ -1413,6 +1420,12 @@ class RepresentationSelector {
|
||||
if (lower()) DeferReplacement(node, lowering->Float64Round(node));
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kNumberSqrt: {
|
||||
VisitUnop(node, UseInfo::TruncatingFloat64(),
|
||||
MachineRepresentation::kFloat64);
|
||||
if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kNumberTrunc: {
|
||||
VisitUnop(node, UseInfo::TruncatingFloat64(),
|
||||
MachineRepresentation::kFloat64);
|
||||
@ -1683,21 +1696,36 @@ class RepresentationSelector {
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kPlainPrimitiveToNumber:
|
||||
ProcessInput(node, 0, UseInfo::AnyTagged());
|
||||
if (truncation.TruncatesToWord32()) {
|
||||
SetOutput(node, MachineRepresentation::kWord32);
|
||||
if (lower()) {
|
||||
NodeProperties::ChangeOp(node,
|
||||
simplified()->PlainPrimitiveToWord32());
|
||||
// TODO(jarin): Extend this to Number \/ Oddball
|
||||
if (InputIs(node, Type::NumberOrUndefined())) {
|
||||
VisitUnop(node, UseInfo::TruncatingWord32(),
|
||||
MachineRepresentation::kWord32);
|
||||
if (lower()) DeferReplacement(node, node->InputAt(0));
|
||||
} else {
|
||||
VisitUnop(node, UseInfo::AnyTagged(),
|
||||
MachineRepresentation::kWord32);
|
||||
if (lower()) {
|
||||
NodeProperties::ChangeOp(node,
|
||||
simplified()->PlainPrimitiveToWord32());
|
||||
}
|
||||
}
|
||||
} else if (truncation.TruncatesToFloat64()) {
|
||||
SetOutput(node, MachineRepresentation::kFloat64);
|
||||
if (lower()) {
|
||||
NodeProperties::ChangeOp(node,
|
||||
simplified()->PlainPrimitiveToFloat64());
|
||||
// TODO(jarin): Extend this to Number \/ Oddball
|
||||
if (InputIs(node, Type::NumberOrUndefined())) {
|
||||
VisitUnop(node, UseInfo::TruncatingFloat64(),
|
||||
MachineRepresentation::kFloat64);
|
||||
if (lower()) DeferReplacement(node, node->InputAt(0));
|
||||
} else {
|
||||
VisitUnop(node, UseInfo::AnyTagged(),
|
||||
MachineRepresentation::kFloat64);
|
||||
if (lower()) {
|
||||
NodeProperties::ChangeOp(node,
|
||||
simplified()->PlainPrimitiveToFloat64());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SetOutput(node, MachineRepresentation::kTagged);
|
||||
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
|
||||
}
|
||||
return;
|
||||
case IrOpcode::kObjectIsCallable:
|
||||
|
@ -204,11 +204,13 @@ BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op) {
|
||||
V(NumberClz32, Operator::kNoProperties, 1) \
|
||||
V(NumberCeil, Operator::kNoProperties, 1) \
|
||||
V(NumberFloor, Operator::kNoProperties, 1) \
|
||||
V(NumberFround, Operator::kNoProperties, 1) \
|
||||
V(NumberAtan, Operator::kNoProperties, 1) \
|
||||
V(NumberAtan2, Operator::kNoProperties, 2) \
|
||||
V(NumberLog, Operator::kNoProperties, 1) \
|
||||
V(NumberLog1p, Operator::kNoProperties, 1) \
|
||||
V(NumberRound, Operator::kNoProperties, 1) \
|
||||
V(NumberSqrt, Operator::kNoProperties, 1) \
|
||||
V(NumberTrunc, Operator::kNoProperties, 1) \
|
||||
V(NumberToInt32, Operator::kNoProperties, 1) \
|
||||
V(NumberToUint32, Operator::kNoProperties, 1) \
|
||||
@ -217,9 +219,9 @@ BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op) {
|
||||
V(NumberConvertHoleNaN, Operator::kNoProperties, 1) \
|
||||
V(StringFromCharCode, Operator::kNoProperties, 1) \
|
||||
V(StringToNumber, Operator::kNoProperties, 1) \
|
||||
V(PlainPrimitiveToNumber, Operator::kNoWrite, 1) \
|
||||
V(PlainPrimitiveToWord32, Operator::kNoWrite, 1) \
|
||||
V(PlainPrimitiveToFloat64, Operator::kNoWrite, 1) \
|
||||
V(PlainPrimitiveToNumber, Operator::kNoProperties, 1) \
|
||||
V(PlainPrimitiveToWord32, Operator::kNoProperties, 1) \
|
||||
V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1) \
|
||||
V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1) \
|
||||
V(ChangeTaggedToInt32, Operator::kNoProperties, 1) \
|
||||
V(ChangeTaggedToUint32, Operator::kNoProperties, 1) \
|
||||
|
@ -154,11 +154,13 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
|
||||
const Operator* NumberClz32();
|
||||
const Operator* NumberCeil();
|
||||
const Operator* NumberFloor();
|
||||
const Operator* NumberFround();
|
||||
const Operator* NumberAtan();
|
||||
const Operator* NumberAtan2();
|
||||
const Operator* NumberLog();
|
||||
const Operator* NumberLog1p();
|
||||
const Operator* NumberRound();
|
||||
const Operator* NumberSqrt();
|
||||
const Operator* NumberTrunc();
|
||||
const Operator* NumberToInt32();
|
||||
const Operator* NumberToUint32();
|
||||
|
@ -1788,6 +1788,8 @@ Type* Typer::Visitor::TypeNumberFloor(Node* node) {
|
||||
return TypeUnaryOp(node, NumberFloor);
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeNumberFround(Node* node) { return Type::Number(); }
|
||||
|
||||
Type* Typer::Visitor::TypeNumberAtan(Node* node) { return Type::Number(); }
|
||||
|
||||
Type* Typer::Visitor::TypeNumberAtan2(Node* node) { return Type::Number(); }
|
||||
@ -1800,6 +1802,8 @@ Type* Typer::Visitor::TypeNumberRound(Node* node) {
|
||||
return TypeUnaryOp(node, NumberRound);
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeNumberSqrt(Node* node) { return Type::Number(); }
|
||||
|
||||
Type* Typer::Visitor::TypeNumberTrunc(Node* node) {
|
||||
return TypeUnaryOp(node, NumberTrunc);
|
||||
}
|
||||
@ -1902,7 +1906,7 @@ Type* Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) {
|
||||
|
||||
Type* Typer::Visitor::TypeTruncateTaggedToFloat64(Node* node) {
|
||||
Type* arg = Operand(node, 0);
|
||||
DCHECK(arg->Is(Type::NumberOrUndefined()));
|
||||
DCHECK(arg->Is(Type::NumberOrOddball()));
|
||||
return ChangeRepresentation(arg, Type::UntaggedFloat64(), zone());
|
||||
}
|
||||
|
||||
|
@ -675,16 +675,16 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
CheckUpperIs(node, Type::Number());
|
||||
break;
|
||||
case IrOpcode::kNumberEqual:
|
||||
// (NumberOrUndefined, NumberOrUndefined) -> Boolean
|
||||
CheckValueInputIs(node, 0, Type::NumberOrUndefined());
|
||||
CheckValueInputIs(node, 1, Type::NumberOrUndefined());
|
||||
// (Number, Number) -> Boolean
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
CheckValueInputIs(node, 1, Type::Number());
|
||||
CheckUpperIs(node, Type::Boolean());
|
||||
break;
|
||||
case IrOpcode::kNumberLessThan:
|
||||
case IrOpcode::kNumberLessThanOrEqual:
|
||||
// (Number, Number) -> Boolean
|
||||
CheckValueInputIs(node, 0, Type::NumberOrUndefined());
|
||||
CheckValueInputIs(node, 1, Type::NumberOrUndefined());
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
CheckValueInputIs(node, 1, Type::Number());
|
||||
CheckUpperIs(node, Type::Boolean());
|
||||
break;
|
||||
case IrOpcode::kSpeculativeNumberAdd:
|
||||
@ -695,16 +695,15 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
case IrOpcode::kNumberMultiply:
|
||||
case IrOpcode::kNumberDivide:
|
||||
// (Number, Number) -> Number
|
||||
CheckValueInputIs(node, 0, Type::NumberOrUndefined());
|
||||
CheckValueInputIs(node, 1, Type::NumberOrUndefined());
|
||||
// CheckUpperIs(node, Type::Number());
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
CheckValueInputIs(node, 1, Type::Number());
|
||||
CheckUpperIs(node, Type::Number());
|
||||
break;
|
||||
case IrOpcode::kNumberModulus:
|
||||
// (Number, Number) -> Number
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
CheckValueInputIs(node, 1, Type::Number());
|
||||
// TODO(rossberg): activate once we retype after opcode changes.
|
||||
// CheckUpperIs(node, Type::Number());
|
||||
CheckUpperIs(node, Type::Number());
|
||||
break;
|
||||
case IrOpcode::kNumberBitwiseOr:
|
||||
case IrOpcode::kNumberBitwiseXor:
|
||||
@ -746,10 +745,12 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
break;
|
||||
case IrOpcode::kNumberCeil:
|
||||
case IrOpcode::kNumberFloor:
|
||||
case IrOpcode::kNumberFround:
|
||||
case IrOpcode::kNumberAtan:
|
||||
case IrOpcode::kNumberLog:
|
||||
case IrOpcode::kNumberLog1p:
|
||||
case IrOpcode::kNumberRound:
|
||||
case IrOpcode::kNumberSqrt:
|
||||
case IrOpcode::kNumberTrunc:
|
||||
// Number -> Number
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
@ -757,12 +758,12 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
break;
|
||||
case IrOpcode::kNumberToInt32:
|
||||
// Number -> Signed32
|
||||
CheckValueInputIs(node, 0, Type::NumberOrUndefined());
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
CheckUpperIs(node, Type::Signed32());
|
||||
break;
|
||||
case IrOpcode::kNumberToUint32:
|
||||
// Number -> Unsigned32
|
||||
CheckValueInputIs(node, 0, Type::NumberOrUndefined());
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
CheckUpperIs(node, Type::Unsigned32());
|
||||
break;
|
||||
case IrOpcode::kNumberIsHoleNaN:
|
||||
@ -851,7 +852,7 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kChangeTaggedToFloat64: {
|
||||
// Number /\ Tagged -> Number /\ UntaggedFloat64
|
||||
// NumberOrUndefined /\ Tagged -> Number /\ UntaggedFloat64
|
||||
// TODO(neis): Activate once ChangeRepresentation works in typer.
|
||||
// Type* from = Type::Intersect(Type::Number(), Type::Tagged());
|
||||
// Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
|
||||
@ -970,7 +971,7 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
CheckNotTyped(node);
|
||||
break;
|
||||
case IrOpcode::kNumberSilenceNaN:
|
||||
CheckValueInputIs(node, 0, Type::NumberOrUndefined());
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
CheckUpperIs(node, Type::Number());
|
||||
break;
|
||||
|
||||
|
@ -219,6 +219,7 @@ namespace internal {
|
||||
V(BooleanOrNullOrUndefined, kBoolean | kNull | kUndefined) \
|
||||
V(NullOrUndefined, kNull | kUndefined) \
|
||||
V(Undetectable, kNullOrUndefined | kOtherUndetectable) \
|
||||
V(NumberOrOddball, kNumber | kNullOrUndefined | kBoolean) \
|
||||
V(NumberOrSimdOrString, kNumber | kSimd | kString) \
|
||||
V(NumberOrString, kNumber | kString) \
|
||||
V(NumberOrUndefined, kNumber | kUndefined) \
|
||||
|
@ -86,11 +86,403 @@ Type* const kNumberTypes[] = {
|
||||
} // namespace
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.atan
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathAtanWithNumber) {
|
||||
Node* function = MathFunction("atan");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberAtan(p0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathAtanWithPlainPrimitive) {
|
||||
Node* function = MathFunction("atan");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberAtan(IsPlainPrimitiveToNumber(p0)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.atan2
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathAtan2WithNumber) {
|
||||
Node* function = MathFunction("atan2");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
TRACED_FOREACH(Type*, t1, kNumberTypes) {
|
||||
Node* p1 = Parameter(t1, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
|
||||
UndefinedConstant(), p0, p1, context,
|
||||
frame_state, effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberAtan2(p0, p1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathAtan2WithPlainPrimitive) {
|
||||
Node* function = MathFunction("atan2");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* p1 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
|
||||
UndefinedConstant(), p0, p1, context,
|
||||
frame_state, effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberAtan2(IsPlainPrimitiveToNumber(p0),
|
||||
IsPlainPrimitiveToNumber(p1)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.ceil
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathCeilWithNumber) {
|
||||
Node* function = MathFunction("ceil");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberCeil(p0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathCeilWithPlainPrimitive) {
|
||||
Node* function = MathFunction("ceil");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberCeil(IsPlainPrimitiveToNumber(p0)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.clz32
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathClz32WithUnsigned32) {
|
||||
Node* function = MathFunction("clz32");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::Unsigned32(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberClz32(p0));
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathClz32WithNumber) {
|
||||
Node* function = MathFunction("clz32");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::Number(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberClz32(IsNumberToUint32(p0)));
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathClz32WithPlainPrimitive) {
|
||||
Node* function = MathFunction("clz32");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(),
|
||||
IsNumberClz32(IsNumberToUint32(IsPlainPrimitiveToNumber(p0))));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.floor
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathFloorWithNumber) {
|
||||
Node* function = MathFunction("floor");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberFloor(p0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathFloorWithPlainPrimitive) {
|
||||
Node* function = MathFunction("floor");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberFloor(IsPlainPrimitiveToNumber(p0)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.fround
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathFroundWithNumber) {
|
||||
Node* function = MathFunction("fround");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberFround(p0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathFroundWithPlainPrimitive) {
|
||||
Node* function = MathFunction("fround");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberFround(IsPlainPrimitiveToNumber(p0)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.imul
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathImulWithUnsigned32) {
|
||||
Node* function = MathFunction("imul");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::Unsigned32(), 0);
|
||||
Node* p1 = Parameter(Type::Unsigned32(), 1);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
|
||||
UndefinedConstant(), p0, p1, context,
|
||||
frame_state, effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberImul(p0, p1));
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathImulWithNumber) {
|
||||
Node* function = MathFunction("imul");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::Number(), 0);
|
||||
Node* p1 = Parameter(Type::Number(), 1);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
|
||||
UndefinedConstant(), p0, p1, context,
|
||||
frame_state, effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(),
|
||||
IsNumberImul(IsNumberToUint32(p0), IsNumberToUint32(p1)));
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathImulWithPlainPrimitive) {
|
||||
Node* function = MathFunction("imul");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* p1 = Parameter(Type::PlainPrimitive(), 1);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
|
||||
UndefinedConstant(), p0, p1, context,
|
||||
frame_state, effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(),
|
||||
IsNumberImul(IsNumberToUint32(IsPlainPrimitiveToNumber(p0)),
|
||||
IsNumberToUint32(IsPlainPrimitiveToNumber(p1))));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.log
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathLogWithNumber) {
|
||||
Node* function = MathFunction("log");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberLog(p0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathLogWithPlainPrimitive) {
|
||||
Node* function = MathFunction("log");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberLog(IsPlainPrimitiveToNumber(p0)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.log1p
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathLog1pWithNumber) {
|
||||
Node* function = MathFunction("log1p");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberLog1p(p0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathLog1pWithPlainPrimitive) {
|
||||
Node* function = MathFunction("log1p");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberLog1p(IsPlainPrimitiveToNumber(p0)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.max
|
||||
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMax0) {
|
||||
TEST_F(JSBuiltinReducerTest, MathMaxWithNoArguments) {
|
||||
Node* function = MathFunction("max");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
@ -106,8 +498,7 @@ TEST_F(JSBuiltinReducerTest, MathMax0) {
|
||||
EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMax1) {
|
||||
TEST_F(JSBuiltinReducerTest, MathMaxWithNumber) {
|
||||
Node* function = MathFunction("max");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
@ -126,8 +517,24 @@ TEST_F(JSBuiltinReducerTest, MathMax1) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMaxWithPlainPrimitive) {
|
||||
Node* function = MathFunction("max");
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMax2) {
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsPlainPrimitiveToNumber(p0));
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMaxWithIntegral32) {
|
||||
Node* function = MathFunction("max");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
@ -150,20 +557,70 @@ TEST_F(JSBuiltinReducerTest, MathMax2) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.imul
|
||||
// Math.min
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMinWithNoArguments) {
|
||||
Node* function = MathFunction("min");
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathImul) {
|
||||
Node* function = MathFunction("imul");
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(2), function,
|
||||
UndefinedConstant(), context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberConstant(V8_INFINITY));
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMinWithNumber) {
|
||||
Node* function = MathFunction("min");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
TRACED_FOREACH(Type*, t1, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), p0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMinWithPlainPrimitive) {
|
||||
Node* function = MathFunction("min");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsPlainPrimitiveToNumber(p0));
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathMinWithIntegral32) {
|
||||
Node* function = MathFunction("min");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kIntegral32Types) {
|
||||
TRACED_FOREACH(Type*, t1, kIntegral32Types) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* p1 = Parameter(t1, 1);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
|
||||
@ -172,88 +629,17 @@ TEST_F(JSBuiltinReducerTest, MathImul) {
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(),
|
||||
IsNumberImul(IsNumberToUint32(p0), IsNumberToUint32(p1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.fround
|
||||
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathFround) {
|
||||
Node* function = MathFunction("fround");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.atan
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathAtan) {
|
||||
Node* function = MathFunction("atan");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberAtan(p0));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.atan2
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathAtan2) {
|
||||
Node* function = MathFunction("atan2");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
TRACED_FOREACH(Type*, t1, kNumberTypes) {
|
||||
Node* p1 = Parameter(t1, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
|
||||
UndefinedConstant(), p0, p1, context,
|
||||
frame_state, effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberAtan2(p0, p1));
|
||||
EXPECT_THAT(r.replacement(), IsSelect(MachineRepresentation::kNone,
|
||||
IsNumberLessThan(p1, p0), p1, p0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.log
|
||||
// Math.round
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathLog) {
|
||||
Node* function = MathFunction("log");
|
||||
TEST_F(JSBuiltinReducerTest, MathRoundWithNumber) {
|
||||
Node* function = MathFunction("round");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
@ -267,15 +653,32 @@ TEST_F(JSBuiltinReducerTest, MathLog) {
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberLog(p0));
|
||||
EXPECT_THAT(r.replacement(), IsNumberRound(p0));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.log1p
|
||||
TEST_F(JSBuiltinReducerTest, MathRoundWithPlainPrimitive) {
|
||||
Node* function = MathFunction("round");
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathLog1p) {
|
||||
Node* function = MathFunction("log1p");
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberRound(IsPlainPrimitiveToNumber(p0)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.sqrt
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathSqrtWithNumber) {
|
||||
Node* function = MathFunction("sqrt");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
@ -289,14 +692,70 @@ TEST_F(JSBuiltinReducerTest, MathLog1p) {
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberLog1p(p0));
|
||||
EXPECT_THAT(r.replacement(), IsNumberSqrt(p0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathSqrtWithPlainPrimitive) {
|
||||
Node* function = MathFunction("sqrt");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberSqrt(IsPlainPrimitiveToNumber(p0)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Math.trunc
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathTruncWithNumber) {
|
||||
Node* function = MathFunction("trunc");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
TRACED_FOREACH(Type*, t0, kNumberTypes) {
|
||||
Node* p0 = Parameter(t0, 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberTrunc(p0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, MathTruncWithPlainPrimitive) {
|
||||
Node* function = MathFunction("trunc");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsNumberTrunc(IsPlainPrimitiveToNumber(p0)));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// String.fromCharCode
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, StringFromCharCode) {
|
||||
TEST_F(JSBuiltinReducerTest, StringFromCharCodeWithNumber) {
|
||||
Node* function = StringFunction("fromCharCode");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
@ -315,6 +774,24 @@ TEST_F(JSBuiltinReducerTest, StringFromCharCode) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JSBuiltinReducerTest, StringFromCharCodeWithPlainPrimitive) {
|
||||
Node* function = StringFunction("fromCharCode");
|
||||
|
||||
Node* effect = graph()->start();
|
||||
Node* control = graph()->start();
|
||||
Node* context = UndefinedConstant();
|
||||
Node* frame_state = graph()->start();
|
||||
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
|
||||
Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
|
||||
UndefinedConstant(), p0, context, frame_state,
|
||||
effect, control);
|
||||
Reduction r = Reduce(call);
|
||||
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(),
|
||||
IsStringFromCharCode(IsPlainPrimitiveToNumber(p0)));
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -2311,8 +2311,15 @@ IS_UNOP_MATCHER(Float64RoundTiesAway)
|
||||
IS_UNOP_MATCHER(Float64ExtractLowWord32)
|
||||
IS_UNOP_MATCHER(Float64ExtractHighWord32)
|
||||
IS_UNOP_MATCHER(NumberAtan)
|
||||
IS_UNOP_MATCHER(NumberCeil)
|
||||
IS_UNOP_MATCHER(NumberClz32)
|
||||
IS_UNOP_MATCHER(NumberFloor)
|
||||
IS_UNOP_MATCHER(NumberFround)
|
||||
IS_UNOP_MATCHER(NumberLog)
|
||||
IS_UNOP_MATCHER(NumberLog1p)
|
||||
IS_UNOP_MATCHER(NumberRound)
|
||||
IS_UNOP_MATCHER(NumberSqrt)
|
||||
IS_UNOP_MATCHER(NumberTrunc)
|
||||
IS_UNOP_MATCHER(NumberToInt32)
|
||||
IS_UNOP_MATCHER(NumberToUint32)
|
||||
IS_UNOP_MATCHER(PlainPrimitiveToNumber)
|
||||
|
@ -227,8 +227,15 @@ Matcher<Node*> IsNumberImul(const Matcher<Node*>& lhs_matcher,
|
||||
Matcher<Node*> IsNumberAtan(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsNumberAtan2(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
Matcher<Node*> IsNumberCeil(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsNumberClz32(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsNumberFloor(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsNumberFround(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsNumberLog(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsNumberLog1p(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsNumberRound(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsNumberSqrt(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsNumberTrunc(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsStringFromCharCode(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsAllocate(const Matcher<Node*>& size_matcher,
|
||||
const Matcher<Node*>& effect_matcher,
|
||||
|
Loading…
Reference in New Issue
Block a user