Index: src/code-stubs.cc |
diff --git a/src/code-stubs.cc b/src/code-stubs.cc |
index 06b7afcaeb28cd90b182e374225ab9a66dfa030a..70a46972daa1d0f1ddb691517289d4d681dc6ab7 100644 |
--- a/src/code-stubs.cc |
+++ b/src/code-stubs.cc |
@@ -1491,13 +1491,39 @@ compiler::Node* IncStub::Generate(CodeStubAssembler* assembler, |
assembler->Bind(&if_valuenotnumber); |
{ |
- // Convert to a Number first and try again. |
- Callable callable = |
- CodeFactory::NonNumberToNumber(assembler->isolate()); |
- var_type_feedback.Bind( |
- assembler->Int32Constant(BinaryOperationFeedback::kAny)); |
- value_var.Bind(assembler->CallStub(callable, context, value)); |
- assembler->Goto(&start); |
+ // We do not require an Or with earlier feedback here because once we |
+ // convert the value to a number, we cannot reach this path. We can |
+ // only reach this path on the first pass when the feedback is kNone. |
+ assembler->Assert(assembler->Word32Equal( |
+ var_type_feedback.value(), |
+ assembler->Int32Constant(BinaryOperationFeedback::kNone))); |
+ |
+ Label if_valueisoddball(assembler), if_valuenotoddball(assembler); |
+ Node* instance_type = assembler->LoadMapInstanceType(value_map); |
+ Node* is_oddball = assembler->Word32Equal( |
+ instance_type, assembler->Int32Constant(ODDBALL_TYPE)); |
+ assembler->Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball); |
+ |
+ assembler->Bind(&if_valueisoddball); |
+ { |
+ // Convert Oddball to Number and check again. |
+ value_var.Bind( |
+ assembler->LoadObjectField(value, Oddball::kToNumberOffset)); |
+ var_type_feedback.Bind(assembler->Int32Constant( |
+ BinaryOperationFeedback::kNumberOrOddball)); |
+ assembler->Goto(&start); |
+ } |
+ |
+ assembler->Bind(&if_valuenotoddball); |
+ { |
+ // Convert to a Number first and try again. |
+ Callable callable = |
+ CodeFactory::NonNumberToNumber(assembler->isolate()); |
+ var_type_feedback.Bind( |
+ assembler->Int32Constant(BinaryOperationFeedback::kAny)); |
+ value_var.Bind(assembler->CallStub(callable, context, value)); |
+ assembler->Goto(&start); |
+ } |
} |
} |
} |
@@ -1601,13 +1627,39 @@ compiler::Node* DecStub::Generate(CodeStubAssembler* assembler, |
assembler->Bind(&if_valuenotnumber); |
{ |
- // Convert to a Number first and try again. |
- Callable callable = |
- CodeFactory::NonNumberToNumber(assembler->isolate()); |
- var_type_feedback.Bind( |
- assembler->Int32Constant(BinaryOperationFeedback::kAny)); |
- value_var.Bind(assembler->CallStub(callable, context, value)); |
- assembler->Goto(&start); |
+ // We do not require an Or with earlier feedback here because once we |
+ // convert the value to a number, we cannot reach this path. We can |
+ // only reach this path on the first pass when the feedback is kNone. |
+ assembler->Assert(assembler->Word32Equal( |
+ var_type_feedback.value(), |
+ assembler->Int32Constant(BinaryOperationFeedback::kNone))); |
+ |
+ Label if_valueisoddball(assembler), if_valuenotoddball(assembler); |
+ Node* instance_type = assembler->LoadMapInstanceType(value_map); |
+ Node* is_oddball = assembler->Word32Equal( |
+ instance_type, assembler->Int32Constant(ODDBALL_TYPE)); |
+ assembler->Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball); |
+ |
+ assembler->Bind(&if_valueisoddball); |
+ { |
+ // Convert Oddball to Number and check again. |
+ value_var.Bind( |
+ assembler->LoadObjectField(value, Oddball::kToNumberOffset)); |
+ var_type_feedback.Bind(assembler->Int32Constant( |
+ BinaryOperationFeedback::kNumberOrOddball)); |
+ assembler->Goto(&start); |
+ } |
+ |
+ assembler->Bind(&if_valuenotoddball); |
+ { |
+ // Convert to a Number first and try again. |
+ Callable callable = |
+ CodeFactory::NonNumberToNumber(assembler->isolate()); |
+ var_type_feedback.Bind( |
+ assembler->Int32Constant(BinaryOperationFeedback::kAny)); |
+ value_var.Bind(assembler->CallStub(callable, context, value)); |
+ assembler->Goto(&start); |
+ } |
} |
} |
} |