| 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
|
|
|