Index: src/interpreter/interpreter.cc |
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc |
index c33421f21351c875568f398533dae3ade9a0fe1d..b1fbd5882312cc47a40be050d05ab65d016e9498 100644 |
--- a/src/interpreter/interpreter.cc |
+++ b/src/interpreter/interpreter.cc |
@@ -1567,14 +1567,276 @@ void Interpreter::DoToObject(InterpreterAssembler* assembler) { |
// |
// Increments value in the accumulator by one. |
void Interpreter::DoInc(InterpreterAssembler* assembler) { |
- DoUnaryOpWithFeedback<IncStub>(assembler); |
+ typedef CodeStubAssembler::Label Label; |
+ typedef compiler::Node Node; |
+ typedef CodeStubAssembler::Variable Variable; |
+ |
+ Node* value = __ GetAccumulator(); |
+ Node* context = __ GetContext(); |
+ Node* slot_index = __ BytecodeOperandIdx(0); |
+ Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
+ |
+ // Shared entry for floating point increment. |
+ Label do_finc(assembler), end(assembler); |
+ Variable var_finc_value(assembler, MachineRepresentation::kFloat64); |
+ |
+ // We might need to try again due to ToNumber conversion. |
+ Variable value_var(assembler, MachineRepresentation::kTagged); |
+ Variable result_var(assembler, MachineRepresentation::kTagged); |
+ Variable var_type_feedback(assembler, MachineRepresentation::kWord32); |
+ Variable* loop_vars[] = {&value_var, &var_type_feedback}; |
+ Label start(assembler, 2, loop_vars); |
+ value_var.Bind(value); |
+ var_type_feedback.Bind( |
+ assembler->Int32Constant(BinaryOperationFeedback::kNone)); |
+ assembler->Goto(&start); |
+ assembler->Bind(&start); |
+ { |
+ value = value_var.value(); |
+ |
+ Label if_issmi(assembler), if_isnotsmi(assembler); |
+ assembler->Branch(assembler->TaggedIsSmi(value), &if_issmi, &if_isnotsmi); |
+ |
+ assembler->Bind(&if_issmi); |
+ { |
+ // Try fast Smi addition first. |
+ Node* one = assembler->SmiConstant(Smi::FromInt(1)); |
+ Node* pair = assembler->IntPtrAddWithOverflow( |
+ assembler->BitcastTaggedToWord(value), |
+ assembler->BitcastTaggedToWord(one)); |
+ Node* overflow = assembler->Projection(1, pair); |
+ |
+ // Check if the Smi addition overflowed. |
+ Label if_overflow(assembler), if_notoverflow(assembler); |
+ assembler->Branch(overflow, &if_overflow, &if_notoverflow); |
+ |
+ assembler->Bind(&if_notoverflow); |
+ var_type_feedback.Bind(assembler->Word32Or( |
+ var_type_feedback.value(), |
+ assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall))); |
+ result_var.Bind( |
+ assembler->BitcastWordToTaggedSigned(assembler->Projection(0, pair))); |
+ assembler->Goto(&end); |
+ |
+ assembler->Bind(&if_overflow); |
+ { |
+ var_finc_value.Bind(assembler->SmiToFloat64(value)); |
+ assembler->Goto(&do_finc); |
+ } |
+ } |
+ |
+ assembler->Bind(&if_isnotsmi); |
+ { |
+ // Check if the value is a HeapNumber. |
+ Label if_valueisnumber(assembler), |
+ if_valuenotnumber(assembler, Label::kDeferred); |
+ Node* value_map = assembler->LoadMap(value); |
+ assembler->Branch(assembler->IsHeapNumberMap(value_map), |
+ &if_valueisnumber, &if_valuenotnumber); |
+ |
+ assembler->Bind(&if_valueisnumber); |
+ { |
+ // Load the HeapNumber value. |
+ var_finc_value.Bind(assembler->LoadHeapNumberValue(value)); |
+ assembler->Goto(&do_finc); |
+ } |
+ |
+ assembler->Bind(&if_valuenotnumber); |
+ { |
+ // 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. |
+ CSA_ASSERT(assembler, |
+ 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); |
+ } |
+ } |
+ } |
+ } |
+ |
+ assembler->Bind(&do_finc); |
+ { |
+ Node* finc_value = var_finc_value.value(); |
+ Node* one = assembler->Float64Constant(1.0); |
+ Node* finc_result = assembler->Float64Add(finc_value, one); |
+ var_type_feedback.Bind(assembler->Word32Or( |
+ var_type_feedback.value(), |
+ assembler->Int32Constant(BinaryOperationFeedback::kNumber))); |
+ result_var.Bind(assembler->AllocateHeapNumberWithValue(finc_result)); |
+ assembler->Goto(&end); |
+ } |
+ |
+ assembler->Bind(&end); |
+ assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector, |
+ slot_index); |
+ |
+ __ SetAccumulator(result_var.value()); |
+ __ Dispatch(); |
} |
// Dec |
// |
// Decrements value in the accumulator by one. |
void Interpreter::DoDec(InterpreterAssembler* assembler) { |
- DoUnaryOpWithFeedback<DecStub>(assembler); |
+ typedef CodeStubAssembler::Label Label; |
+ typedef compiler::Node Node; |
+ typedef CodeStubAssembler::Variable Variable; |
+ |
+ Node* value = __ GetAccumulator(); |
+ Node* context = __ GetContext(); |
+ Node* slot_index = __ BytecodeOperandIdx(0); |
+ Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
+ |
+ // Shared entry for floating point decrement. |
+ Label do_fdec(assembler), end(assembler); |
+ Variable var_fdec_value(assembler, MachineRepresentation::kFloat64); |
+ |
+ // We might need to try again due to ToNumber conversion. |
+ Variable value_var(assembler, MachineRepresentation::kTagged); |
+ Variable result_var(assembler, MachineRepresentation::kTagged); |
+ Variable var_type_feedback(assembler, MachineRepresentation::kWord32); |
+ Variable* loop_vars[] = {&value_var, &var_type_feedback}; |
+ Label start(assembler, 2, loop_vars); |
+ var_type_feedback.Bind( |
+ assembler->Int32Constant(BinaryOperationFeedback::kNone)); |
+ value_var.Bind(value); |
+ assembler->Goto(&start); |
+ assembler->Bind(&start); |
+ { |
+ value = value_var.value(); |
+ |
+ Label if_issmi(assembler), if_isnotsmi(assembler); |
+ assembler->Branch(assembler->TaggedIsSmi(value), &if_issmi, &if_isnotsmi); |
+ |
+ assembler->Bind(&if_issmi); |
+ { |
+ // Try fast Smi subtraction first. |
+ Node* one = assembler->SmiConstant(Smi::FromInt(1)); |
+ Node* pair = assembler->IntPtrSubWithOverflow( |
+ assembler->BitcastTaggedToWord(value), |
+ assembler->BitcastTaggedToWord(one)); |
+ Node* overflow = assembler->Projection(1, pair); |
+ |
+ // Check if the Smi subtraction overflowed. |
+ Label if_overflow(assembler), if_notoverflow(assembler); |
+ assembler->Branch(overflow, &if_overflow, &if_notoverflow); |
+ |
+ assembler->Bind(&if_notoverflow); |
+ var_type_feedback.Bind(assembler->Word32Or( |
+ var_type_feedback.value(), |
+ assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall))); |
+ result_var.Bind( |
+ assembler->BitcastWordToTaggedSigned(assembler->Projection(0, pair))); |
+ assembler->Goto(&end); |
+ |
+ assembler->Bind(&if_overflow); |
+ { |
+ var_fdec_value.Bind(assembler->SmiToFloat64(value)); |
+ assembler->Goto(&do_fdec); |
+ } |
+ } |
+ |
+ assembler->Bind(&if_isnotsmi); |
+ { |
+ // Check if the value is a HeapNumber. |
+ Label if_valueisnumber(assembler), |
+ if_valuenotnumber(assembler, Label::kDeferred); |
+ Node* value_map = assembler->LoadMap(value); |
+ assembler->Branch(assembler->IsHeapNumberMap(value_map), |
+ &if_valueisnumber, &if_valuenotnumber); |
+ |
+ assembler->Bind(&if_valueisnumber); |
+ { |
+ // Load the HeapNumber value. |
+ var_fdec_value.Bind(assembler->LoadHeapNumberValue(value)); |
+ assembler->Goto(&do_fdec); |
+ } |
+ |
+ assembler->Bind(&if_valuenotnumber); |
+ { |
+ // 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. |
+ CSA_ASSERT(assembler, |
+ 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); |
+ } |
+ } |
+ } |
+ } |
+ |
+ assembler->Bind(&do_fdec); |
+ { |
+ Node* fdec_value = var_fdec_value.value(); |
+ Node* one = assembler->Float64Constant(1.0); |
+ Node* fdec_result = assembler->Float64Sub(fdec_value, one); |
+ var_type_feedback.Bind(assembler->Word32Or( |
+ var_type_feedback.value(), |
+ assembler->Int32Constant(BinaryOperationFeedback::kNumber))); |
+ result_var.Bind(assembler->AllocateHeapNumberWithValue(fdec_result)); |
+ assembler->Goto(&end); |
+ } |
+ |
+ assembler->Bind(&end); |
+ assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector, |
+ slot_index); |
+ |
+ __ SetAccumulator(result_var.value()); |
+ __ Dispatch(); |
} |
// LogicalNot |