Commit 2890137b authored by jarin's avatar jarin Committed by Commit bot

[turbofan] Introduce PlainPrimitiveToNumber.

This should solve the problem with missing checkpoints after JSToNumber
(PlainPrimitiveToNumber is marked no-write, so the frame-state
propagation should see through it.)

Unfortunately, this also duplicates the word32- and float64-truncation
magic that we have for JSToNumber in "simplified lowering".

Review-Url: https://codereview.chromium.org/2059653002
Cr-Commit-Position: refs/heads/master@{#36881}
parent d0c7775d
...@@ -454,6 +454,14 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, ...@@ -454,6 +454,14 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
break; break;
case IrOpcode::kCheckIf: case IrOpcode::kCheckIf:
state = LowerCheckIf(node, frame_state, *effect, *control); state = LowerCheckIf(node, frame_state, *effect, *control);
case IrOpcode::kPlainPrimitiveToNumber:
state = LowerPlainPrimitiveToNumber(node, *effect, *control);
break;
case IrOpcode::kPlainPrimitiveToWord32:
state = LowerPlainPrimitiveToWord32(node, *effect, *control);
break;
case IrOpcode::kPlainPrimitiveToFloat64:
state = LowerPlainPrimitiveToFloat64(node, *effect, *control);
break; break;
default: default:
return false; return false;
...@@ -1330,7 +1338,6 @@ Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) { ...@@ -1330,7 +1338,6 @@ Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) {
} }
return value; return value;
} }
Node* EffectControlLinearizer::ObjectIsSmi(Node* value) { Node* EffectControlLinearizer::ObjectIsSmi(Node* value) {
return graph()->NewNode( return graph()->NewNode(
machine()->WordEqual(), machine()->WordEqual(),
...@@ -1347,6 +1354,128 @@ Node* EffectControlLinearizer::SmiShiftBitsConstant() { ...@@ -1347,6 +1354,128 @@ Node* EffectControlLinearizer::SmiShiftBitsConstant() {
return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize); return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
} }
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node, Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* result = effect =
graph()->NewNode(ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(),
value, jsgraph()->NoContextConstant(), effect, control);
return ValueEffectControl(result, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node, Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* check0 = ObjectIsSmi(value);
Node* branch0 =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
Node* etrue0 = effect;
Node* vtrue0 = ChangeSmiToInt32(value);
Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
Node* efalse0 = effect;
Node* vfalse0;
{
vfalse0 = efalse0 = graph()->NewNode(
ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(), value,
jsgraph()->NoContextConstant(), efalse0, if_false0);
Node* check1 = ObjectIsSmi(vfalse0);
Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
Node* etrue1 = efalse0;
Node* vtrue1 = ChangeSmiToInt32(vfalse0);
Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
Node* efalse1 = efalse0;
Node* vfalse1;
{
vfalse1 = efalse1 = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
efalse1, if_false1);
vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
}
if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
efalse0 =
graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
vtrue1, vfalse1, if_false0);
}
control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
vtrue0, vfalse0, control);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node, Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* check0 = ObjectIsSmi(value);
Node* branch0 =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
Node* etrue0 = effect;
Node* vtrue0;
{
vtrue0 = ChangeSmiToInt32(value);
vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
}
Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
Node* efalse0 = effect;
Node* vfalse0;
{
vfalse0 = efalse0 = graph()->NewNode(
ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(), value,
jsgraph()->NoContextConstant(), efalse0, if_false0);
Node* check1 = ObjectIsSmi(vfalse0);
Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
Node* etrue1 = efalse0;
Node* vtrue1;
{
vtrue1 = ChangeSmiToInt32(vfalse0);
vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
}
Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
Node* efalse1 = efalse0;
Node* vfalse1;
{
vfalse1 = efalse1 = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
efalse1, if_false1);
}
if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
efalse0 =
graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
vfalse0 =
graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
vtrue1, vfalse1, if_false0);
}
control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
vtrue0, vfalse0, control);
return ValueEffectControl(value, effect, control);
}
Factory* EffectControlLinearizer::factory() const { Factory* EffectControlLinearizer::factory() const {
return isolate()->factory(); return isolate()->factory();
} }
...@@ -1355,6 +1484,18 @@ Isolate* EffectControlLinearizer::isolate() const { ...@@ -1355,6 +1484,18 @@ Isolate* EffectControlLinearizer::isolate() const {
return jsgraph()->isolate(); return jsgraph()->isolate();
} }
Operator const* EffectControlLinearizer::ToNumberOperator() {
if (!to_number_operator_.is_set()) {
Callable callable = CodeFactory::ToNumber(isolate());
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0, flags,
Operator::kNoThrow);
to_number_operator_.set(common()->Call(desc));
}
return to_number_operator_.get();
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -91,6 +91,13 @@ class EffectControlLinearizer { ...@@ -91,6 +91,13 @@ class EffectControlLinearizer {
Node* control); Node* control);
ValueEffectControl LowerCheckIf(Node* node, Node* frame_state, Node* effect, ValueEffectControl LowerCheckIf(Node* node, Node* frame_state, Node* effect,
Node* control); Node* control);
ValueEffectControl LowerPlainPrimitiveToNumber(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerPlainPrimitiveToWord32(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerPlainPrimitiveToFloat64(Node* node, Node* effect,
Node* control);
ValueEffectControl AllocateHeapNumberWithValue(Node* node, Node* effect, ValueEffectControl AllocateHeapNumberWithValue(Node* node, Node* effect,
Node* control); Node* control);
ValueEffectControl BuildCheckedFloat64ToInt32(Node* value, Node* frame_state, ValueEffectControl BuildCheckedFloat64ToInt32(Node* value, Node* frame_state,
...@@ -99,6 +106,7 @@ class EffectControlLinearizer { ...@@ -99,6 +106,7 @@ class EffectControlLinearizer {
Node* frame_state, Node* frame_state,
Node* effect, Node* effect,
Node* control); Node* control);
Node* ChangeInt32ToSmi(Node* value); Node* ChangeInt32ToSmi(Node* value);
Node* ChangeUint32ToSmi(Node* value); Node* ChangeUint32ToSmi(Node* value);
Node* ChangeInt32ToFloat64(Node* value); Node* ChangeInt32ToFloat64(Node* value);
...@@ -119,9 +127,13 @@ class EffectControlLinearizer { ...@@ -119,9 +127,13 @@ class EffectControlLinearizer {
SimplifiedOperatorBuilder* simplified() const; SimplifiedOperatorBuilder* simplified() const;
MachineOperatorBuilder* machine() const; MachineOperatorBuilder* machine() const;
Operator const* ToNumberOperator();
JSGraph* js_graph_; JSGraph* js_graph_;
Schedule* schedule_; Schedule* schedule_;
Zone* temp_zone_; Zone* temp_zone_;
SetOncePointer<Operator const> to_number_operator_;
}; };
} // namespace compiler } // namespace compiler
......
...@@ -24,6 +24,11 @@ Node* JSGraph::AllocateInOldSpaceStubConstant() { ...@@ -24,6 +24,11 @@ Node* JSGraph::AllocateInOldSpaceStubConstant() {
HeapConstant(isolate()->builtins()->AllocateInOldSpace())); HeapConstant(isolate()->builtins()->AllocateInOldSpace()));
} }
Node* JSGraph::ToNumberBuiltinConstant() {
return CACHED(kToNumberBuiltinConstant,
HeapConstant(isolate()->builtins()->ToNumber()));
}
Node* JSGraph::CEntryStubConstant(int result_size) { Node* JSGraph::CEntryStubConstant(int result_size) {
if (result_size == 1) { if (result_size == 1) {
return CACHED(kCEntryStubConstant, return CACHED(kCEntryStubConstant,
......
...@@ -41,6 +41,7 @@ class JSGraph : public ZoneObject { ...@@ -41,6 +41,7 @@ class JSGraph : public ZoneObject {
// Canonicalized global constants. // Canonicalized global constants.
Node* AllocateInNewSpaceStubConstant(); Node* AllocateInNewSpaceStubConstant();
Node* AllocateInOldSpaceStubConstant(); Node* AllocateInOldSpaceStubConstant();
Node* ToNumberBuiltinConstant();
Node* CEntryStubConstant(int result_size); Node* CEntryStubConstant(int result_size);
Node* EmptyFixedArrayConstant(); Node* EmptyFixedArrayConstant();
Node* EmptyLiteralsArrayConstant(); Node* EmptyLiteralsArrayConstant();
...@@ -146,6 +147,7 @@ class JSGraph : public ZoneObject { ...@@ -146,6 +147,7 @@ class JSGraph : public ZoneObject {
enum CachedNode { enum CachedNode {
kAllocateInNewSpaceStubConstant, kAllocateInNewSpaceStubConstant,
kAllocateInOldSpaceStubConstant, kAllocateInOldSpaceStubConstant,
kToNumberBuiltinConstant,
kCEntryStubConstant, kCEntryStubConstant,
kEmptyFixedArrayConstant, kEmptyFixedArrayConstant,
kEmptyLiteralsArrayConstant, kEmptyLiteralsArrayConstant,
......
...@@ -289,10 +289,7 @@ class JSBinopReduction final { ...@@ -289,10 +289,7 @@ class JSBinopReduction final {
if (NodeProperties::GetType(node)->Is(Type::NumberOrUndefined())) { if (NodeProperties::GetType(node)->Is(Type::NumberOrUndefined())) {
return node; return node;
} }
// TODO(bmeurer): Introduce PlainPrimitiveToNumber here. return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), node);
return graph()->NewNode(
javascript()->ToNumber(), node, jsgraph()->NoContextConstant(),
lowering_->EmptyFrameState(), graph()->start(), graph()->start());
} }
Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) { Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) {
...@@ -869,21 +866,11 @@ Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { ...@@ -869,21 +866,11 @@ Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
} }
Type* const input_type = NodeProperties::GetType(input); Type* const input_type = NodeProperties::GetType(input);
if (input_type->Is(Type::PlainPrimitive())) { if (input_type->Is(Type::PlainPrimitive())) {
if (NodeProperties::GetContextInput(node) !=
jsgraph()->NoContextConstant() ||
NodeProperties::GetEffectInput(node) != graph()->start() ||
NodeProperties::GetControlInput(node) != graph()->start()) {
// JSToNumber(x:plain-primitive,context,effect,control)
// => JSToNumber(x,no-context,start,start)
RelaxEffectsAndControls(node); RelaxEffectsAndControls(node);
NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); node->TrimInputCount(1);
NodeProperties::ReplaceControlInput(node, graph()->start()); NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber());
NodeProperties::ReplaceEffectInput(node, graph()->start());
DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
NodeProperties::ReplaceFrameStateInput(node, 0, EmptyFrameState());
return Changed(node); return Changed(node);
} }
}
return NoChange(); return NoChange();
} }
......
...@@ -175,6 +175,9 @@ ...@@ -175,6 +175,9 @@
#define SIMPLIFIED_OP_LIST(V) \ #define SIMPLIFIED_OP_LIST(V) \
SIMPLIFIED_COMPARE_BINOP_LIST(V) \ SIMPLIFIED_COMPARE_BINOP_LIST(V) \
V(PlainPrimitiveToNumber) \
V(PlainPrimitiveToWord32) \
V(PlainPrimitiveToFloat64) \
V(BooleanNot) \ V(BooleanNot) \
V(BooleanToNumber) \ V(BooleanToNumber) \
V(SpeculativeNumberAdd) \ V(SpeculativeNumberAdd) \
......
...@@ -1639,6 +1639,24 @@ class RepresentationSelector { ...@@ -1639,6 +1639,24 @@ class RepresentationSelector {
} }
return; return;
} }
case IrOpcode::kPlainPrimitiveToNumber:
ProcessInput(node, 0, UseInfo::AnyTagged());
if (truncation.TruncatesToWord32()) {
SetOutput(node, MachineRepresentation::kWord32);
if (lower()) {
NodeProperties::ChangeOp(node,
simplified()->PlainPrimitiveToWord32());
}
} else if (truncation.TruncatesToFloat64()) {
SetOutput(node, MachineRepresentation::kFloat64);
if (lower()) {
NodeProperties::ChangeOp(node,
simplified()->PlainPrimitiveToFloat64());
}
} else {
SetOutput(node, MachineRepresentation::kTagged);
}
return;
case IrOpcode::kObjectIsCallable: case IrOpcode::kObjectIsCallable:
case IrOpcode::kObjectIsNumber: case IrOpcode::kObjectIsNumber:
case IrOpcode::kObjectIsReceiver: case IrOpcode::kObjectIsReceiver:
...@@ -1808,6 +1826,8 @@ class RepresentationSelector { ...@@ -1808,6 +1826,8 @@ class RepresentationSelector {
case IrOpcode::kCheckedFloat64ToInt32: case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedTaggedToInt32: case IrOpcode::kCheckedTaggedToInt32:
case IrOpcode::kCheckedTaggedToFloat64: case IrOpcode::kCheckedTaggedToFloat64:
case IrOpcode::kPlainPrimitiveToWord32:
case IrOpcode::kPlainPrimitiveToFloat64:
FATAL("Representation inference: unsupported opcodes."); FATAL("Representation inference: unsupported opcodes.");
break; break;
......
...@@ -212,6 +212,9 @@ BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op) { ...@@ -212,6 +212,9 @@ BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op) {
V(NumberIsHoleNaN, Operator::kNoProperties, 1) \ V(NumberIsHoleNaN, Operator::kNoProperties, 1) \
V(StringFromCharCode, Operator::kNoProperties, 1) \ V(StringFromCharCode, Operator::kNoProperties, 1) \
V(StringToNumber, Operator::kNoProperties, 1) \ V(StringToNumber, Operator::kNoProperties, 1) \
V(PlainPrimitiveToNumber, Operator::kNoWrite, 1) \
V(PlainPrimitiveToWord32, Operator::kNoWrite, 1) \
V(PlainPrimitiveToFloat64, Operator::kNoWrite, 1) \
V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1) \ V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1) \
V(ChangeTaggedToInt32, Operator::kNoProperties, 1) \ V(ChangeTaggedToInt32, Operator::kNoProperties, 1) \
V(ChangeTaggedToUint32, Operator::kNoProperties, 1) \ V(ChangeTaggedToUint32, Operator::kNoProperties, 1) \
......
...@@ -172,6 +172,10 @@ class SimplifiedOperatorBuilder final : public ZoneObject { ...@@ -172,6 +172,10 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* StringFromCharCode(); const Operator* StringFromCharCode();
const Operator* StringToNumber(); const Operator* StringToNumber();
const Operator* PlainPrimitiveToNumber();
const Operator* PlainPrimitiveToWord32();
const Operator* PlainPrimitiveToFloat64();
const Operator* ChangeTaggedSignedToInt32(); const Operator* ChangeTaggedSignedToInt32();
const Operator* ChangeTaggedToInt32(); const Operator* ChangeTaggedToInt32();
const Operator* ChangeTaggedToUint32(); const Operator* ChangeTaggedToUint32();
......
...@@ -1759,6 +1759,18 @@ Type* Typer::Visitor::TypeNumberShiftRightLogical(Node* node) { ...@@ -1759,6 +1759,18 @@ Type* Typer::Visitor::TypeNumberShiftRightLogical(Node* node) {
return Type::Unsigned32(); return Type::Unsigned32();
} }
Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
return TypeUnaryOp(node, ToNumber);
}
Type* Typer::Visitor::TypePlainPrimitiveToWord32(Node* node) {
return Type::Integral32();
}
Type* Typer::Visitor::TypePlainPrimitiveToFloat64(Node* node) {
return Type::Number();
}
Type* Typer::Visitor::TypeNumberImul(Node* node) { return Type::Signed32(); } Type* Typer::Visitor::TypeNumberImul(Node* node) { return Type::Signed32(); }
Type* Typer::Visitor::TypeNumberClz32(Node* node) { Type* Typer::Visitor::TypeNumberClz32(Node* node) {
......
...@@ -762,6 +762,16 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -762,6 +762,16 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 0, Type::Number()); CheckValueInputIs(node, 0, Type::Number());
CheckUpperIs(node, Type::Boolean()); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kPlainPrimitiveToNumber:
// Type is Number.
CheckUpperIs(node, Type::Number());
break;
case IrOpcode::kPlainPrimitiveToWord32:
CheckUpperIs(node, Type::Number());
break;
case IrOpcode::kPlainPrimitiveToFloat64:
CheckUpperIs(node, Type::Number());
break;
case IrOpcode::kStringEqual: case IrOpcode::kStringEqual:
case IrOpcode::kStringLessThan: case IrOpcode::kStringLessThan:
case IrOpcode::kStringLessThanOrEqual: case IrOpcode::kStringLessThanOrEqual:
......
...@@ -492,7 +492,7 @@ TEST(JSToNumberOfNumberOrOtherPrimitive) { ...@@ -492,7 +492,7 @@ TEST(JSToNumberOfNumberOrOtherPrimitive) {
for (size_t i = 0; i < arraysize(others); i++) { for (size_t i = 0; i < arraysize(others); i++) {
Type* t = Type::Union(Type::Number(), others[i], R.main_zone()); Type* t = Type::Union(Type::Number(), others[i], R.main_zone());
Node* r = R.ReduceUnop(R.javascript.ToNumber(), t); Node* r = R.ReduceUnop(R.javascript.ToNumber(), t);
CHECK_EQ(IrOpcode::kJSToNumber, r->opcode()); CHECK_EQ(IrOpcode::kPlainPrimitiveToNumber, r->opcode());
} }
} }
......
...@@ -321,8 +321,7 @@ TEST_F(JSTypedLoweringTest, JSToNumberWithPlainPrimitive) { ...@@ -321,8 +321,7 @@ TEST_F(JSTypedLoweringTest, JSToNumberWithPlainPrimitive) {
Reduce(graph()->NewNode(javascript()->ToNumber(), input, context, Reduce(graph()->NewNode(javascript()->ToNumber(), input, context,
EmptyFrameState(), effect, control)); EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsToNumber(input, IsNumberConstant(BitEq(0.0)), EXPECT_THAT(r.replacement(), IsPlainPrimitiveToNumber(input));
graph()->start(), control));
} }
......
...@@ -2311,6 +2311,7 @@ IS_UNOP_MATCHER(Float64ExtractLowWord32) ...@@ -2311,6 +2311,7 @@ IS_UNOP_MATCHER(Float64ExtractLowWord32)
IS_UNOP_MATCHER(Float64ExtractHighWord32) IS_UNOP_MATCHER(Float64ExtractHighWord32)
IS_UNOP_MATCHER(NumberToInt32) IS_UNOP_MATCHER(NumberToInt32)
IS_UNOP_MATCHER(NumberToUint32) IS_UNOP_MATCHER(NumberToUint32)
IS_UNOP_MATCHER(PlainPrimitiveToNumber)
IS_UNOP_MATCHER(ObjectIsReceiver) IS_UNOP_MATCHER(ObjectIsReceiver)
IS_UNOP_MATCHER(ObjectIsSmi) IS_UNOP_MATCHER(ObjectIsSmi)
IS_UNOP_MATCHER(StringFromCharCode) IS_UNOP_MATCHER(StringFromCharCode)
......
...@@ -375,6 +375,7 @@ Matcher<Node*> IsNumberToUint32(const Matcher<Node*>& input_matcher); ...@@ -375,6 +375,7 @@ Matcher<Node*> IsNumberToUint32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsParameter(const Matcher<int> index_matcher); Matcher<Node*> IsParameter(const Matcher<int> index_matcher);
Matcher<Node*> IsLoadFramePointer(); Matcher<Node*> IsLoadFramePointer();
Matcher<Node*> IsLoadParentFramePointer(); Matcher<Node*> IsLoadParentFramePointer();
Matcher<Node*> IsPlainPrimitiveToNumber(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsInt32PairAdd(const Matcher<Node*>& a_matcher, Matcher<Node*> IsInt32PairAdd(const Matcher<Node*>& a_matcher,
const Matcher<Node*>& b_matcher, const Matcher<Node*>& b_matcher,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment