diff options
Diffstat (limited to 'deps/v8/src/interpreter/interpreter-generator.cc')
-rw-r--r-- | deps/v8/src/interpreter/interpreter-generator.cc | 685 |
1 files changed, 222 insertions, 463 deletions
diff --git a/deps/v8/src/interpreter/interpreter-generator.cc b/deps/v8/src/interpreter/interpreter-generator.cc index 2a8f3c8810..b02e024d65 100644 --- a/deps/v8/src/interpreter/interpreter-generator.cc +++ b/deps/v8/src/interpreter/interpreter-generator.cc @@ -179,7 +179,7 @@ class InterpreterLoadGlobalAssembler : public InterpreterAssembler { feedback_vector, feedback_slot, &exit_point, &try_handler, &miss, CodeStubAssembler::INTPTR_PARAMETERS); - Bind(&done); + BIND(&done); SetAccumulator(var_result.value()); Dispatch(); } @@ -190,7 +190,7 @@ class InterpreterLoadGlobalAssembler : public InterpreterAssembler { Variable var_result(this, MachineRepresentation::kTagged); ExitPoint exit_point(this, &done, &var_result); - Bind(&try_handler); + BIND(&try_handler); { Node* context = GetContext(); Node* smi_slot = SmiTag(feedback_slot); @@ -203,7 +203,7 @@ class InterpreterLoadGlobalAssembler : public InterpreterAssembler { &exit_point, &miss); } - Bind(&miss); + BIND(&miss); { Node* context = GetContext(); Node* smi_slot = SmiTag(feedback_slot); @@ -215,7 +215,7 @@ class InterpreterLoadGlobalAssembler : public InterpreterAssembler { accessor_asm.LoadGlobalIC_MissCase(¶ms, &exit_point); } - Bind(&done); + BIND(&done); { SetAccumulator(var_result.value()); Dispatch(); @@ -414,7 +414,7 @@ class InterpreterLookupContextSlotAssembler : public InterpreterAssembler { } // Slow path when we have to call out to the runtime. - Bind(&slowpath); + BIND(&slowpath); { Node* name = LoadConstantPoolEntry(name_index); Node* result = CallRuntime(function_id, context, name); @@ -470,7 +470,7 @@ class InterpreterLookupGlobalAssembler : public InterpreterLoadGlobalAssembler { } // Slow path when we have to call out to the runtime - Bind(&slowpath); + BIND(&slowpath); { Node* name_index = BytecodeOperandIdx(0); Node* name = LoadConstantPoolEntry(name_index); @@ -557,7 +557,7 @@ IGNITION_HANDLER(LdaNamedProperty, InterpreterAssembler) { AccessorAssembler accessor_asm(state()); accessor_asm.LoadIC_BytecodeHandler(¶ms, &exit_point); - Bind(&done); + BIND(&done); { SetAccumulator(var_result.value()); Dispatch(); @@ -735,7 +735,7 @@ IGNITION_HANDLER(LdaModuleVariable, InterpreterAssembler) { Branch(IntPtrGreaterThan(cell_index, IntPtrConstant(0)), &if_export, &if_import); - Bind(&if_export); + BIND(&if_export); { Node* regular_exports = LoadObjectField(module, Module::kRegularExportsOffset); @@ -746,7 +746,7 @@ IGNITION_HANDLER(LdaModuleVariable, InterpreterAssembler) { Goto(&end); } - Bind(&if_import); + BIND(&if_import); { Node* regular_imports = LoadObjectField(module, Module::kRegularImportsOffset); @@ -757,7 +757,7 @@ IGNITION_HANDLER(LdaModuleVariable, InterpreterAssembler) { Goto(&end); } - Bind(&end); + BIND(&end); Dispatch(); } @@ -777,7 +777,7 @@ IGNITION_HANDLER(StaModuleVariable, InterpreterAssembler) { Branch(IntPtrGreaterThan(cell_index, IntPtrConstant(0)), &if_export, &if_import); - Bind(&if_export); + BIND(&if_export); { Node* regular_exports = LoadObjectField(module, Module::kRegularExportsOffset); @@ -788,14 +788,14 @@ IGNITION_HANDLER(StaModuleVariable, InterpreterAssembler) { Goto(&end); } - Bind(&if_import); + BIND(&if_import); { // Not supported (probably never). Abort(kUnsupportedModuleOperation); Goto(&end); } - Bind(&end); + BIND(&end); Dispatch(); } @@ -899,7 +899,7 @@ IGNITION_HANDLER(AddSmi, InterpreterAssembler) { // {right} is known to be a Smi. // Check if the {left} is a Smi take the fast path. Branch(TaggedIsSmi(left), &fastpath, &slowpath); - Bind(&fastpath); + BIND(&fastpath); { // Try fast Smi addition first. Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(left), @@ -909,7 +909,7 @@ IGNITION_HANDLER(AddSmi, InterpreterAssembler) { // Check if the Smi additon overflowed. Label if_notoverflow(this); Branch(overflow, &slowpath, &if_notoverflow); - Bind(&if_notoverflow); + BIND(&if_notoverflow); { UpdateFeedback(SmiConstant(BinaryOperationFeedback::kSignedSmall), feedback_vector, slot_index); @@ -917,7 +917,7 @@ IGNITION_HANDLER(AddSmi, InterpreterAssembler) { Goto(&end); } } - Bind(&slowpath); + BIND(&slowpath); { Node* context = GetContext(); // TODO(ishell): pass slot as word-size value. @@ -926,7 +926,7 @@ IGNITION_HANDLER(AddSmi, InterpreterAssembler) { feedback_vector)); Goto(&end); } - Bind(&end); + BIND(&end); { SetAccumulator(var_result.value()); Dispatch(); @@ -948,7 +948,7 @@ IGNITION_HANDLER(SubSmi, InterpreterAssembler) { // {right} is known to be a Smi. // Check if the {left} is a Smi take the fast path. Branch(TaggedIsSmi(left), &fastpath, &slowpath); - Bind(&fastpath); + BIND(&fastpath); { // Try fast Smi subtraction first. Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(left), @@ -958,7 +958,7 @@ IGNITION_HANDLER(SubSmi, InterpreterAssembler) { // Check if the Smi subtraction overflowed. Label if_notoverflow(this); Branch(overflow, &slowpath, &if_notoverflow); - Bind(&if_notoverflow); + BIND(&if_notoverflow); { UpdateFeedback(SmiConstant(BinaryOperationFeedback::kSignedSmall), feedback_vector, slot_index); @@ -966,7 +966,7 @@ IGNITION_HANDLER(SubSmi, InterpreterAssembler) { Goto(&end); } } - Bind(&slowpath); + BIND(&slowpath); { Node* context = GetContext(); // TODO(ishell): pass slot as word-size value. @@ -975,7 +975,7 @@ IGNITION_HANDLER(SubSmi, InterpreterAssembler) { feedback_vector)); Goto(&end); } - Bind(&end); + BIND(&end); { SetAccumulator(var_result.value()); Dispatch(); @@ -997,7 +997,7 @@ IGNITION_HANDLER(MulSmi, InterpreterAssembler) { // {right} is known to be a Smi. // Check if the {left} is a Smi take the fast path. Branch(TaggedIsSmi(left), &fastpath, &slowpath); - Bind(&fastpath); + BIND(&fastpath); { // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi, // in case of overflow. @@ -1008,7 +1008,7 @@ IGNITION_HANDLER(MulSmi, InterpreterAssembler) { UpdateFeedback(feedback, feedback_vector, slot_index); Goto(&end); } - Bind(&slowpath); + BIND(&slowpath); { Node* context = GetContext(); // TODO(ishell): pass slot as word-size value. @@ -1018,7 +1018,7 @@ IGNITION_HANDLER(MulSmi, InterpreterAssembler) { Goto(&end); } - Bind(&end); + BIND(&end); { SetAccumulator(var_result.value()); Dispatch(); @@ -1040,14 +1040,14 @@ IGNITION_HANDLER(DivSmi, InterpreterAssembler) { // {right} is known to be a Smi. // Check if the {left} is a Smi take the fast path. Branch(TaggedIsSmi(left), &fastpath, &slowpath); - Bind(&fastpath); + BIND(&fastpath); { var_result.Bind(TrySmiDiv(left, right, &slowpath)); UpdateFeedback(SmiConstant(BinaryOperationFeedback::kSignedSmall), feedback_vector, slot_index); Goto(&end); } - Bind(&slowpath); + BIND(&slowpath); { Node* context = GetContext(); // TODO(ishell): pass slot as word-size value. @@ -1057,7 +1057,7 @@ IGNITION_HANDLER(DivSmi, InterpreterAssembler) { Goto(&end); } - Bind(&end); + BIND(&end); { SetAccumulator(var_result.value()); Dispatch(); @@ -1079,7 +1079,7 @@ IGNITION_HANDLER(ModSmi, InterpreterAssembler) { // {right} is known to be a Smi. // Check if the {left} is a Smi take the fast path. Branch(TaggedIsSmi(left), &fastpath, &slowpath); - Bind(&fastpath); + BIND(&fastpath); { // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi. var_result.Bind(SmiMod(left, right)); @@ -1089,7 +1089,7 @@ IGNITION_HANDLER(ModSmi, InterpreterAssembler) { UpdateFeedback(feedback, feedback_vector, slot_index); Goto(&end); } - Bind(&slowpath); + BIND(&slowpath); { Node* context = GetContext(); // TODO(ishell): pass slot as word-size value. @@ -1099,7 +1099,7 @@ IGNITION_HANDLER(ModSmi, InterpreterAssembler) { Goto(&end); } - Bind(&end); + BIND(&end); { SetAccumulator(var_result.value()); Dispatch(); @@ -1172,7 +1172,7 @@ class InterpreterBitwiseBinaryOpAssembler : public InterpreterAssembler { AbortIfWordNotEqual(result_map, HeapNumberMapConstant(), kExpectedHeapNumber); Goto(&ok); - Bind(&ok); + BIND(&ok); } Node* input_feedback = @@ -1422,21 +1422,21 @@ IGNITION_HANDLER(ToNumber, InterpreterAssembler) { Node* object_map = LoadMap(object); Branch(IsHeapNumberMap(object_map), &if_objectisnumber, &if_objectisother); - Bind(&if_objectissmi); + BIND(&if_objectissmi); { var_result.Bind(object); var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall)); Goto(&if_done); } - Bind(&if_objectisnumber); + BIND(&if_objectisnumber); { var_result.Bind(object); var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber)); Goto(&if_done); } - Bind(&if_objectisother); + BIND(&if_objectisother); { // Convert the {object} to a Number. Callable callable = CodeFactory::NonNumberToNumber(isolate()); @@ -1445,7 +1445,7 @@ IGNITION_HANDLER(ToNumber, InterpreterAssembler) { Goto(&if_done); } - Bind(&if_done); + BIND(&if_done); StoreRegister(var_result.value(), BytecodeOperandReg(0)); // Record the type feedback collected for {object}. @@ -1495,14 +1495,14 @@ IGNITION_HANDLER(Inc, InterpreterAssembler) { value_var.Bind(value); var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNone)); Goto(&start); - Bind(&start); + BIND(&start); { value = value_var.value(); Label if_issmi(this), if_isnotsmi(this); Branch(TaggedIsSmi(value), &if_issmi, &if_isnotsmi); - Bind(&if_issmi); + BIND(&if_issmi); { // Try fast Smi addition first. Node* one = SmiConstant(Smi::FromInt(1)); @@ -1514,35 +1514,35 @@ IGNITION_HANDLER(Inc, InterpreterAssembler) { Label if_overflow(this), if_notoverflow(this); Branch(overflow, &if_overflow, &if_notoverflow); - Bind(&if_notoverflow); + BIND(&if_notoverflow); var_type_feedback.Bind( SmiOr(var_type_feedback.value(), SmiConstant(BinaryOperationFeedback::kSignedSmall))); result_var.Bind(BitcastWordToTaggedSigned(Projection(0, pair))); Goto(&end); - Bind(&if_overflow); + BIND(&if_overflow); { var_finc_value.Bind(SmiToFloat64(value)); Goto(&do_finc); } } - Bind(&if_isnotsmi); + BIND(&if_isnotsmi); { // Check if the value is a HeapNumber. Label if_valueisnumber(this), if_valuenotnumber(this, Label::kDeferred); Node* value_map = LoadMap(value); Branch(IsHeapNumberMap(value_map), &if_valueisnumber, &if_valuenotnumber); - Bind(&if_valueisnumber); + BIND(&if_valueisnumber); { // Load the HeapNumber value. var_finc_value.Bind(LoadHeapNumberValue(value)); Goto(&do_finc); } - Bind(&if_valuenotnumber); + 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 @@ -1556,7 +1556,7 @@ IGNITION_HANDLER(Inc, InterpreterAssembler) { Word32Equal(instance_type, Int32Constant(ODDBALL_TYPE)); Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball); - Bind(&if_valueisoddball); + BIND(&if_valueisoddball); { // Convert Oddball to Number and check again. value_var.Bind(LoadObjectField(value, Oddball::kToNumberOffset)); @@ -1565,7 +1565,7 @@ IGNITION_HANDLER(Inc, InterpreterAssembler) { Goto(&start); } - Bind(&if_valuenotoddball); + BIND(&if_valuenotoddball); { // Convert to a Number first and try again. Callable callable = CodeFactory::NonNumberToNumber(isolate()); @@ -1577,7 +1577,7 @@ IGNITION_HANDLER(Inc, InterpreterAssembler) { } } - Bind(&do_finc); + BIND(&do_finc); { Node* finc_value = var_finc_value.value(); Node* one = Float64Constant(1.0); @@ -1589,7 +1589,7 @@ IGNITION_HANDLER(Inc, InterpreterAssembler) { Goto(&end); } - Bind(&end); + BIND(&end); UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_index); SetAccumulator(result_var.value()); @@ -1622,14 +1622,14 @@ IGNITION_HANDLER(Dec, InterpreterAssembler) { var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNone)); value_var.Bind(value); Goto(&start); - Bind(&start); + BIND(&start); { value = value_var.value(); Label if_issmi(this), if_isnotsmi(this); Branch(TaggedIsSmi(value), &if_issmi, &if_isnotsmi); - Bind(&if_issmi); + BIND(&if_issmi); { // Try fast Smi subtraction first. Node* one = SmiConstant(Smi::FromInt(1)); @@ -1641,35 +1641,35 @@ IGNITION_HANDLER(Dec, InterpreterAssembler) { Label if_overflow(this), if_notoverflow(this); Branch(overflow, &if_overflow, &if_notoverflow); - Bind(&if_notoverflow); + BIND(&if_notoverflow); var_type_feedback.Bind( SmiOr(var_type_feedback.value(), SmiConstant(BinaryOperationFeedback::kSignedSmall))); result_var.Bind(BitcastWordToTaggedSigned(Projection(0, pair))); Goto(&end); - Bind(&if_overflow); + BIND(&if_overflow); { var_fdec_value.Bind(SmiToFloat64(value)); Goto(&do_fdec); } } - Bind(&if_isnotsmi); + BIND(&if_isnotsmi); { // Check if the value is a HeapNumber. Label if_valueisnumber(this), if_valuenotnumber(this, Label::kDeferred); Node* value_map = LoadMap(value); Branch(IsHeapNumberMap(value_map), &if_valueisnumber, &if_valuenotnumber); - Bind(&if_valueisnumber); + BIND(&if_valueisnumber); { // Load the HeapNumber value. var_fdec_value.Bind(LoadHeapNumberValue(value)); Goto(&do_fdec); } - Bind(&if_valuenotnumber); + 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 @@ -1683,7 +1683,7 @@ IGNITION_HANDLER(Dec, InterpreterAssembler) { Word32Equal(instance_type, Int32Constant(ODDBALL_TYPE)); Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball); - Bind(&if_valueisoddball); + BIND(&if_valueisoddball); { // Convert Oddball to Number and check again. value_var.Bind(LoadObjectField(value, Oddball::kToNumberOffset)); @@ -1692,7 +1692,7 @@ IGNITION_HANDLER(Dec, InterpreterAssembler) { Goto(&start); } - Bind(&if_valuenotoddball); + BIND(&if_valuenotoddball); { // Convert to a Number first and try again. Callable callable = CodeFactory::NonNumberToNumber(isolate()); @@ -1704,7 +1704,7 @@ IGNITION_HANDLER(Dec, InterpreterAssembler) { } } - Bind(&do_fdec); + BIND(&do_fdec); { Node* fdec_value = var_fdec_value.value(); Node* one = Float64Constant(1.0); @@ -1716,7 +1716,7 @@ IGNITION_HANDLER(Dec, InterpreterAssembler) { Goto(&end); } - Bind(&end); + BIND(&end); UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_index); SetAccumulator(result_var.value()); @@ -1735,17 +1735,17 @@ IGNITION_HANDLER(ToBooleanLogicalNot, InterpreterAssembler) { Node* true_value = BooleanConstant(true); Node* false_value = BooleanConstant(false); BranchIfToBooleanIsTrue(value, &if_true, &if_false); - Bind(&if_true); + BIND(&if_true); { result.Bind(false_value); Goto(&end); } - Bind(&if_false); + BIND(&if_false); { result.Bind(true_value); Goto(&end); } - Bind(&end); + BIND(&end); SetAccumulator(result.value()); Dispatch(); } @@ -1761,12 +1761,12 @@ IGNITION_HANDLER(LogicalNot, InterpreterAssembler) { Node* true_value = BooleanConstant(true); Node* false_value = BooleanConstant(false); Branch(WordEqual(value, true_value), &if_true, &if_false); - Bind(&if_true); + BIND(&if_true); { result.Bind(false_value); Goto(&end); } - Bind(&if_false); + BIND(&if_false); { if (FLAG_debug_code) { AbortIfWordNotEqual(value, false_value, @@ -1775,7 +1775,7 @@ IGNITION_HANDLER(LogicalNot, InterpreterAssembler) { result.Bind(true_value); Goto(&end); } - Bind(&end); + BIND(&end); SetAccumulator(result.value()); Dispatch(); } @@ -1800,8 +1800,8 @@ IGNITION_HANDLER(DeletePropertyStrict, InterpreterAssembler) { Node* object = LoadRegister(reg_index); Node* key = GetAccumulator(); Node* context = GetContext(); - Node* result = - CallRuntime(Runtime::kDeleteProperty_Strict, context, object, key); + Node* result = CallBuiltin(Builtins::kDeleteProperty, context, object, key, + SmiConstant(STRICT)); SetAccumulator(result); Dispatch(); } @@ -1815,8 +1815,8 @@ IGNITION_HANDLER(DeletePropertySloppy, InterpreterAssembler) { Node* object = LoadRegister(reg_index); Node* key = GetAccumulator(); Node* context = GetContext(); - Node* result = - CallRuntime(Runtime::kDeleteProperty_Sloppy, context, object, key); + Node* result = CallBuiltin(Builtins::kDeleteProperty, context, object, key, + SmiConstant(SLOPPY)); SetAccumulator(result); Dispatch(); } @@ -2124,313 +2124,41 @@ class InterpreterCompareOpAssembler : public InterpreterAssembler { Node* lhs = LoadRegister(reg_index); Node* rhs = GetAccumulator(); Node* context = GetContext(); - Node* slot_index = BytecodeOperandIdx(1); - Node* feedback_vector = LoadFeedbackVector(); - - Variable var_result(this, MachineRepresentation::kTagged), - var_fcmp_lhs(this, MachineRepresentation::kFloat64), - var_fcmp_rhs(this, MachineRepresentation::kFloat64), - non_number_value(this, MachineRepresentation::kTagged), - maybe_smi_value(this, MachineRepresentation::kTagged); - Label lhs_is_not_smi(this), do_fcmp(this), slow_path(this), - fast_path_dispatch(this); - - GotoIf(TaggedIsNotSmi(lhs), &lhs_is_not_smi); - { - Label rhs_is_not_smi(this); - GotoIf(TaggedIsNotSmi(rhs), &rhs_is_not_smi); - { - Comment("Do integer comparison"); - UpdateFeedback(SmiConstant(CompareOperationFeedback::kSignedSmall), - feedback_vector, slot_index); - Node* result; - switch (compare_op) { - case Token::LT: - result = SelectBooleanConstant(SmiLessThan(lhs, rhs)); - break; - case Token::LTE: - result = SelectBooleanConstant(SmiLessThanOrEqual(lhs, rhs)); - break; - case Token::GT: - result = SelectBooleanConstant(SmiLessThan(rhs, lhs)); - break; - case Token::GTE: - result = SelectBooleanConstant(SmiLessThanOrEqual(rhs, lhs)); - break; - case Token::EQ: - case Token::EQ_STRICT: - result = SelectBooleanConstant(WordEqual(lhs, rhs)); - break; - default: - UNREACHABLE(); - } - var_result.Bind(result); - Goto(&fast_path_dispatch); - } - - Bind(&rhs_is_not_smi); - { - Node* rhs_map = LoadMap(rhs); - Label rhs_is_not_number(this); - GotoIfNot(IsHeapNumberMap(rhs_map), &rhs_is_not_number); - - Comment("Convert lhs to float and load HeapNumber value from rhs"); - var_fcmp_lhs.Bind(SmiToFloat64(lhs)); - var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); - Goto(&do_fcmp); - - Bind(&rhs_is_not_number); - { - non_number_value.Bind(rhs); - maybe_smi_value.Bind(lhs); - Goto(&slow_path); - } - } - } - - Bind(&lhs_is_not_smi); - { - Label rhs_is_not_smi(this), lhs_is_not_number(this), - rhs_is_not_number(this); - - Node* lhs_map = LoadMap(lhs); - GotoIfNot(IsHeapNumberMap(lhs_map), &lhs_is_not_number); - - GotoIfNot(TaggedIsSmi(rhs), &rhs_is_not_smi); - Comment("Convert rhs to double and load HeapNumber value from lhs"); - var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); - var_fcmp_rhs.Bind(SmiToFloat64(rhs)); - Goto(&do_fcmp); - - Bind(&rhs_is_not_smi); - { - Node* rhs_map = LoadMap(rhs); - GotoIfNot(IsHeapNumberMap(rhs_map), &rhs_is_not_number); - - Comment("Load HeapNumber values from lhs and rhs"); - var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); - var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); - Goto(&do_fcmp); - } - - Bind(&lhs_is_not_number); - { - non_number_value.Bind(lhs); - maybe_smi_value.Bind(rhs); - Goto(&slow_path); - } - - Bind(&rhs_is_not_number); - { - non_number_value.Bind(rhs); - maybe_smi_value.Bind(lhs); - Goto(&slow_path); - } - } - - Bind(&do_fcmp); - { - Comment("Do floating point comparison"); - Node* lhs_float = var_fcmp_lhs.value(); - Node* rhs_float = var_fcmp_rhs.value(); - UpdateFeedback(SmiConstant(CompareOperationFeedback::kNumber), - feedback_vector, slot_index); - - // Perform a fast floating point comparison. - Node* result; - switch (compare_op) { - case Token::LT: - result = SelectBooleanConstant(Float64LessThan(lhs_float, rhs_float)); - break; - case Token::LTE: - result = SelectBooleanConstant( - Float64LessThanOrEqual(lhs_float, rhs_float)); - break; - case Token::GT: - result = - SelectBooleanConstant(Float64GreaterThan(lhs_float, rhs_float)); - break; - case Token::GTE: - result = SelectBooleanConstant( - Float64GreaterThanOrEqual(lhs_float, rhs_float)); - break; - case Token::EQ: - case Token::EQ_STRICT: { - Label check_nan(this); - var_result.Bind(BooleanConstant(false)); - Branch(Float64Equal(lhs_float, rhs_float), &check_nan, - &fast_path_dispatch); - Bind(&check_nan); - result = SelectBooleanConstant(Float64Equal(lhs_float, lhs_float)); - } break; - default: - UNREACHABLE(); - } - var_result.Bind(result); - Goto(&fast_path_dispatch); - } - - Bind(&fast_path_dispatch); - { - SetAccumulator(var_result.value()); - Dispatch(); + Variable var_type_feedback(this, MachineRepresentation::kTagged); + Node* result; + switch (compare_op) { + case Token::EQ: + result = Equal(lhs, rhs, context, &var_type_feedback); + break; + case Token::EQ_STRICT: + result = StrictEqual(lhs, rhs, &var_type_feedback); + break; + case Token::LT: + result = RelationalComparison(CodeStubAssembler::kLessThan, lhs, rhs, + context, &var_type_feedback); + break; + case Token::GT: + result = RelationalComparison(CodeStubAssembler::kGreaterThan, lhs, rhs, + context, &var_type_feedback); + break; + case Token::LTE: + result = RelationalComparison(CodeStubAssembler::kLessThanOrEqual, lhs, + rhs, context, &var_type_feedback); + break; + case Token::GTE: + result = RelationalComparison(CodeStubAssembler::kGreaterThanOrEqual, + lhs, rhs, context, &var_type_feedback); + break; + default: + UNREACHABLE(); } - // Marking a block with more than one predecessor causes register allocator - // to fail (v8:5998). Add a dummy block as a workaround. - Label slow_path_deferred(this, Label::kDeferred); - Bind(&slow_path); - Goto(&slow_path_deferred); - - Bind(&slow_path_deferred); - { - // When we reach here, one of the operands is not a Smi / HeapNumber and - // the other operand could be of any type. The cases where both of them - // are HeapNumbers / Smis are handled earlier. - Comment("Collect feedback for non HeapNumber cases."); - Label update_feedback_and_do_compare(this); - Variable var_type_feedback(this, MachineRepresentation::kTaggedSigned); - var_type_feedback.Bind(SmiConstant(CompareOperationFeedback::kAny)); - - if (Token::IsOrderedRelationalCompareOp(compare_op)) { - Label check_for_oddball(this); - // Check for NumberOrOddball feedback. - Node* non_number_instance_type = - LoadInstanceType(non_number_value.value()); - GotoIf( - Word32Equal(non_number_instance_type, Int32Constant(ODDBALL_TYPE)), - &check_for_oddball); - - // Check for string feedback. - GotoIfNot(IsStringInstanceType(non_number_instance_type), - &update_feedback_and_do_compare); - - GotoIf(TaggedIsSmi(maybe_smi_value.value()), - &update_feedback_and_do_compare); - - Node* maybe_smi_instance_type = - LoadInstanceType(maybe_smi_value.value()); - GotoIfNot(IsStringInstanceType(maybe_smi_instance_type), - &update_feedback_and_do_compare); - - var_type_feedback.Bind(SmiConstant(CompareOperationFeedback::kString)); - Goto(&update_feedback_and_do_compare); - - Bind(&check_for_oddball); - { - Label compare_with_oddball_feedback(this); - GotoIf(TaggedIsSmi(maybe_smi_value.value()), - &compare_with_oddball_feedback); - - Node* maybe_smi_instance_type = - LoadInstanceType(maybe_smi_value.value()); - GotoIf(Word32Equal(maybe_smi_instance_type, - Int32Constant(HEAP_NUMBER_TYPE)), - &compare_with_oddball_feedback); - - Branch( - Word32Equal(maybe_smi_instance_type, Int32Constant(ODDBALL_TYPE)), - &compare_with_oddball_feedback, &update_feedback_and_do_compare); - - Bind(&compare_with_oddball_feedback); - { - var_type_feedback.Bind( - SmiConstant(CompareOperationFeedback::kNumberOrOddball)); - Goto(&update_feedback_and_do_compare); - } - } - } else { - Label not_string(this), both_are_strings(this); - - DCHECK(Token::IsEqualityOp(compare_op)); - - // If one of them is a Smi and the other is not a number, record "Any" - // feedback. Equality comparisons do not need feedback about oddballs. - GotoIf(TaggedIsSmi(maybe_smi_value.value()), - &update_feedback_and_do_compare); - - Node* maybe_smi_instance_type = - LoadInstanceType(maybe_smi_value.value()); - Node* non_number_instance_type = - LoadInstanceType(non_number_value.value()); - GotoIfNot(IsStringInstanceType(maybe_smi_instance_type), ¬_string); - - // If one value is string and other isn't record "Any" feedback. - Branch(IsStringInstanceType(non_number_instance_type), - &both_are_strings, &update_feedback_and_do_compare); - - Bind(&both_are_strings); - { - Node* operand1_feedback = SelectSmiConstant( - Word32Equal(Word32And(maybe_smi_instance_type, - Int32Constant(kIsNotInternalizedMask)), - Int32Constant(kInternalizedTag)), - CompareOperationFeedback::kInternalizedString, - CompareOperationFeedback::kString); - - Node* operand2_feedback = SelectSmiConstant( - Word32Equal(Word32And(non_number_instance_type, - Int32Constant(kIsNotInternalizedMask)), - Int32Constant(kInternalizedTag)), - CompareOperationFeedback::kInternalizedString, - CompareOperationFeedback::kString); - - var_type_feedback.Bind(SmiOr(operand1_feedback, operand2_feedback)); - Goto(&update_feedback_and_do_compare); - } - - Bind(¬_string); - { - // Check if both operands are of type JSReceiver. - GotoIfNot(IsJSReceiverInstanceType(maybe_smi_instance_type), - &update_feedback_and_do_compare); - - GotoIfNot(IsJSReceiverInstanceType(non_number_instance_type), - &update_feedback_and_do_compare); - - var_type_feedback.Bind( - SmiConstant(CompareOperationFeedback::kReceiver)); - Goto(&update_feedback_and_do_compare); - } - } - - Bind(&update_feedback_and_do_compare); - { - Comment("Do the full compare operation"); - UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_index); - Node* result; - switch (compare_op) { - case Token::EQ: - result = Equal(lhs, rhs, context); - break; - case Token::EQ_STRICT: - result = StrictEqual(lhs, rhs); - break; - case Token::LT: - result = RelationalComparison(CodeStubAssembler::kLessThan, lhs, - rhs, context); - break; - case Token::GT: - result = RelationalComparison(CodeStubAssembler::kGreaterThan, lhs, - rhs, context); - break; - case Token::LTE: - result = RelationalComparison(CodeStubAssembler::kLessThanOrEqual, - lhs, rhs, context); - break; - case Token::GTE: - result = RelationalComparison( - CodeStubAssembler::kGreaterThanOrEqual, lhs, rhs, context); - break; - default: - UNREACHABLE(); - } - var_result.Bind(result); - SetAccumulator(var_result.value()); - Dispatch(); - } - } + Node* slot_index = BytecodeOperandIdx(1); + Node* feedback_vector = LoadFeedbackVector(); + UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_index); + SetAccumulator(result); + Dispatch(); } }; @@ -2543,7 +2271,7 @@ IGNITION_HANDLER(TestUndetectable, InterpreterAssembler) { SetAccumulator(result); Goto(&end); - Bind(&end); + BIND(&end); Dispatch(); } @@ -2594,37 +2322,37 @@ IGNITION_HANDLER(TestTypeOf, InterpreterAssembler) { Switch(literal_flag, &abort, cases, labels, arraysize(cases)); - Bind(&abort); + BIND(&abort); { Comment("Abort"); Abort(BailoutReason::kUnexpectedTestTypeofLiteralFlag); Goto(&if_false); } - Bind(&if_number); + BIND(&if_number); { Comment("IfNumber"); GotoIfNumber(object, &if_true); Goto(&if_false); } - Bind(&if_string); + BIND(&if_string); { Comment("IfString"); GotoIf(TaggedIsSmi(object), &if_false); Branch(IsString(object), &if_true, &if_false); } - Bind(&if_symbol); + BIND(&if_symbol); { Comment("IfSymbol"); GotoIf(TaggedIsSmi(object), &if_false); Branch(IsSymbol(object), &if_true, &if_false); } - Bind(&if_boolean); + BIND(&if_boolean); { Comment("IfBoolean"); GotoIf(WordEqual(object, BooleanConstant(true)), &if_true); Branch(WordEqual(object, BooleanConstant(false)), &if_true, &if_false); } - Bind(&if_undefined); + BIND(&if_undefined); { Comment("IfUndefined"); GotoIf(TaggedIsSmi(object), &if_false); @@ -2636,7 +2364,7 @@ IGNITION_HANDLER(TestTypeOf, InterpreterAssembler) { Branch(Word32Equal(undetectable_bit, Int32Constant(0)), &if_false, &if_true); } - Bind(&if_function); + BIND(&if_function); { Comment("IfFunction"); GotoIf(TaggedIsSmi(object), &if_false); @@ -2649,7 +2377,7 @@ IGNITION_HANDLER(TestTypeOf, InterpreterAssembler) { Int32Constant(1 << Map::kIsCallable)), &if_true, &if_false); } - Bind(&if_object); + BIND(&if_object); { Comment("IfObject"); GotoIf(TaggedIsSmi(object), &if_false); @@ -2667,29 +2395,29 @@ IGNITION_HANDLER(TestTypeOf, InterpreterAssembler) { Branch(Word32Equal(callable_undetectable, Int32Constant(0)), &if_true, &if_false); } - Bind(&if_other); + BIND(&if_other); { // Typeof doesn't return any other string value. Goto(&if_false); } - Bind(&if_false); + BIND(&if_false); { SetAccumulator(BooleanConstant(false)); Goto(&end); } - Bind(&if_true); + BIND(&if_true); { SetAccumulator(BooleanConstant(true)); Goto(&end); } - Bind(&end); + BIND(&end); Dispatch(); } // Jump <imm> // -// Jump by number of bytes represented by the immediate operand |imm|. +// Jump by the number of bytes represented by the immediate operand |imm|. IGNITION_HANDLER(Jump, InterpreterAssembler) { Node* relative_jump = BytecodeOperandUImmWord(0); Jump(relative_jump); @@ -2697,7 +2425,8 @@ IGNITION_HANDLER(Jump, InterpreterAssembler) { // JumpConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool. IGNITION_HANDLER(JumpConstant, InterpreterAssembler) { Node* index = BytecodeOperandIdx(0); Node* relative_jump = LoadAndUntagConstantPoolEntry(index); @@ -2706,7 +2435,7 @@ IGNITION_HANDLER(JumpConstant, InterpreterAssembler) { // JumpIfTrue <imm> // -// Jump by number of bytes represented by an immediate operand if the +// Jump by the number of bytes represented by an immediate operand if the // accumulator contains true. This only works for boolean inputs, and // will misbehave if passed arbitrary input values. IGNITION_HANDLER(JumpIfTrue, InterpreterAssembler) { @@ -2720,9 +2449,9 @@ IGNITION_HANDLER(JumpIfTrue, InterpreterAssembler) { // JumpIfTrueConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool -// if the accumulator contains true. This only works for boolean inputs, and -// will misbehave if passed arbitrary input values. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool if the accumulator contains true. This only works for boolean inputs, +// and will misbehave if passed arbitrary input values. IGNITION_HANDLER(JumpIfTrueConstant, InterpreterAssembler) { Node* accumulator = GetAccumulator(); Node* index = BytecodeOperandIdx(0); @@ -2735,7 +2464,7 @@ IGNITION_HANDLER(JumpIfTrueConstant, InterpreterAssembler) { // JumpIfFalse <imm> // -// Jump by number of bytes represented by an immediate operand if the +// Jump by the number of bytes represented by an immediate operand if the // accumulator contains false. This only works for boolean inputs, and // will misbehave if passed arbitrary input values. IGNITION_HANDLER(JumpIfFalse, InterpreterAssembler) { @@ -2749,9 +2478,9 @@ IGNITION_HANDLER(JumpIfFalse, InterpreterAssembler) { // JumpIfFalseConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool -// if the accumulator contains false. This only works for boolean inputs, and -// will misbehave if passed arbitrary input values. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool if the accumulator contains false. This only works for boolean inputs, +// and will misbehave if passed arbitrary input values. IGNITION_HANDLER(JumpIfFalseConstant, InterpreterAssembler) { Node* accumulator = GetAccumulator(); Node* index = BytecodeOperandIdx(0); @@ -2764,71 +2493,71 @@ IGNITION_HANDLER(JumpIfFalseConstant, InterpreterAssembler) { // JumpIfToBooleanTrue <imm> // -// Jump by number of bytes represented by an immediate operand if the object +// Jump by the number of bytes represented by an immediate operand if the object // referenced by the accumulator is true when the object is cast to boolean. IGNITION_HANDLER(JumpIfToBooleanTrue, InterpreterAssembler) { Node* value = GetAccumulator(); Node* relative_jump = BytecodeOperandUImmWord(0); Label if_true(this), if_false(this); BranchIfToBooleanIsTrue(value, &if_true, &if_false); - Bind(&if_true); + BIND(&if_true); Jump(relative_jump); - Bind(&if_false); + BIND(&if_false); Dispatch(); } // JumpIfToBooleanTrueConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool -// if the object referenced by the accumulator is true when the object is cast -// to boolean. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool if the object referenced by the accumulator is true when the object is +// cast to boolean. IGNITION_HANDLER(JumpIfToBooleanTrueConstant, InterpreterAssembler) { Node* value = GetAccumulator(); Node* index = BytecodeOperandIdx(0); Node* relative_jump = LoadAndUntagConstantPoolEntry(index); Label if_true(this), if_false(this); BranchIfToBooleanIsTrue(value, &if_true, &if_false); - Bind(&if_true); + BIND(&if_true); Jump(relative_jump); - Bind(&if_false); + BIND(&if_false); Dispatch(); } // JumpIfToBooleanFalse <imm> // -// Jump by number of bytes represented by an immediate operand if the object +// Jump by the number of bytes represented by an immediate operand if the object // referenced by the accumulator is false when the object is cast to boolean. IGNITION_HANDLER(JumpIfToBooleanFalse, InterpreterAssembler) { Node* value = GetAccumulator(); Node* relative_jump = BytecodeOperandUImmWord(0); Label if_true(this), if_false(this); BranchIfToBooleanIsTrue(value, &if_true, &if_false); - Bind(&if_true); + BIND(&if_true); Dispatch(); - Bind(&if_false); + BIND(&if_false); Jump(relative_jump); } // JumpIfToBooleanFalseConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool -// if the object referenced by the accumulator is false when the object is cast -// to boolean. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool if the object referenced by the accumulator is false when the object is +// cast to boolean. IGNITION_HANDLER(JumpIfToBooleanFalseConstant, InterpreterAssembler) { Node* value = GetAccumulator(); Node* index = BytecodeOperandIdx(0); Node* relative_jump = LoadAndUntagConstantPoolEntry(index); Label if_true(this), if_false(this); BranchIfToBooleanIsTrue(value, &if_true, &if_false); - Bind(&if_true); + BIND(&if_true); Dispatch(); - Bind(&if_false); + BIND(&if_false); Jump(relative_jump); } // JumpIfNull <imm> // -// Jump by number of bytes represented by an immediate operand if the object +// Jump by the number of bytes represented by an immediate operand if the object // referenced by the accumulator is the null constant. IGNITION_HANDLER(JumpIfNull, InterpreterAssembler) { Node* accumulator = GetAccumulator(); @@ -2839,8 +2568,8 @@ IGNITION_HANDLER(JumpIfNull, InterpreterAssembler) { // JumpIfNullConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool -// if the object referenced by the accumulator is the null constant. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool if the object referenced by the accumulator is the null constant. IGNITION_HANDLER(JumpIfNullConstant, InterpreterAssembler) { Node* accumulator = GetAccumulator(); Node* null_value = HeapConstant(isolate()->factory()->null_value()); @@ -2851,7 +2580,7 @@ IGNITION_HANDLER(JumpIfNullConstant, InterpreterAssembler) { // JumpIfNotNull <imm> // -// Jump by number of bytes represented by an immediate operand if the object +// Jump by the number of bytes represented by an immediate operand if the object // referenced by the accumulator is not the null constant. IGNITION_HANDLER(JumpIfNotNull, InterpreterAssembler) { Node* accumulator = GetAccumulator(); @@ -2862,8 +2591,8 @@ IGNITION_HANDLER(JumpIfNotNull, InterpreterAssembler) { // JumpIfNotNullConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool -// if the object referenced by the accumulator is not the null constant. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool if the object referenced by the accumulator is not the null constant. IGNITION_HANDLER(JumpIfNotNullConstant, InterpreterAssembler) { Node* accumulator = GetAccumulator(); Node* null_value = HeapConstant(isolate()->factory()->null_value()); @@ -2874,7 +2603,7 @@ IGNITION_HANDLER(JumpIfNotNullConstant, InterpreterAssembler) { // JumpIfUndefined <imm> // -// Jump by number of bytes represented by an immediate operand if the object +// Jump by the number of bytes represented by an immediate operand if the object // referenced by the accumulator is the undefined constant. IGNITION_HANDLER(JumpIfUndefined, InterpreterAssembler) { Node* accumulator = GetAccumulator(); @@ -2885,8 +2614,8 @@ IGNITION_HANDLER(JumpIfUndefined, InterpreterAssembler) { // JumpIfUndefinedConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool -// if the object referenced by the accumulator is the undefined constant. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool if the object referenced by the accumulator is the undefined constant. IGNITION_HANDLER(JumpIfUndefinedConstant, InterpreterAssembler) { Node* accumulator = GetAccumulator(); Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value()); @@ -2897,7 +2626,7 @@ IGNITION_HANDLER(JumpIfUndefinedConstant, InterpreterAssembler) { // JumpIfNotUndefined <imm> // -// Jump by number of bytes represented by an immediate operand if the object +// Jump by the number of bytes represented by an immediate operand if the object // referenced by the accumulator is not the undefined constant. IGNITION_HANDLER(JumpIfNotUndefined, InterpreterAssembler) { Node* accumulator = GetAccumulator(); @@ -2908,8 +2637,9 @@ IGNITION_HANDLER(JumpIfNotUndefined, InterpreterAssembler) { // JumpIfNotUndefinedConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool -// if the object referenced by the accumulator is not the undefined constant. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool if the object referenced by the accumulator is not the undefined +// constant. IGNITION_HANDLER(JumpIfNotUndefinedConstant, InterpreterAssembler) { Node* accumulator = GetAccumulator(); Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value()); @@ -2920,7 +2650,7 @@ IGNITION_HANDLER(JumpIfNotUndefinedConstant, InterpreterAssembler) { // JumpIfJSReceiver <imm> // -// Jump by number of bytes represented by an immediate operand if the object +// Jump by the number of bytes represented by an immediate operand if the object // referenced by the accumulator is a JSReceiver. IGNITION_HANDLER(JumpIfJSReceiver, InterpreterAssembler) { Node* accumulator = GetAccumulator(); @@ -2929,19 +2659,19 @@ IGNITION_HANDLER(JumpIfJSReceiver, InterpreterAssembler) { Label if_object(this), if_notobject(this, Label::kDeferred), if_notsmi(this); Branch(TaggedIsSmi(accumulator), &if_notobject, &if_notsmi); - Bind(&if_notsmi); + BIND(&if_notsmi); Branch(IsJSReceiver(accumulator), &if_object, &if_notobject); - Bind(&if_object); + BIND(&if_object); Jump(relative_jump); - Bind(&if_notobject); + BIND(&if_notobject); Dispatch(); } // JumpIfJSReceiverConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool if -// the object referenced by the accumulator is a JSReceiver. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool if the object referenced by the accumulator is a JSReceiver. IGNITION_HANDLER(JumpIfJSReceiverConstant, InterpreterAssembler) { Node* accumulator = GetAccumulator(); Node* index = BytecodeOperandIdx(0); @@ -2950,19 +2680,19 @@ IGNITION_HANDLER(JumpIfJSReceiverConstant, InterpreterAssembler) { Label if_object(this), if_notobject(this), if_notsmi(this); Branch(TaggedIsSmi(accumulator), &if_notobject, &if_notsmi); - Bind(&if_notsmi); + BIND(&if_notsmi); Branch(IsJSReceiver(accumulator), &if_object, &if_notobject); - Bind(&if_object); + BIND(&if_object); Jump(relative_jump); - Bind(&if_notobject); + BIND(&if_notobject); Dispatch(); } // JumpIfNotHole <imm> // -// Jump by number of bytes represented by an immediate operand if the object +// Jump by the number of bytes represented by an immediate operand if the object // referenced by the accumulator is the hole. IGNITION_HANDLER(JumpIfNotHole, InterpreterAssembler) { Node* accumulator = GetAccumulator(); @@ -2973,8 +2703,8 @@ IGNITION_HANDLER(JumpIfNotHole, InterpreterAssembler) { // JumpIfNotHoleConstant <idx> // -// Jump by number of bytes in the Smi in the |idx| entry in the constant pool -// if the object referenced by the accumulator is the hole constant. +// Jump by the number of bytes in the Smi in the |idx| entry in the constant +// pool if the object referenced by the accumulator is the hole constant. IGNITION_HANDLER(JumpIfNotHoleConstant, InterpreterAssembler) { Node* accumulator = GetAccumulator(); Node* the_hole_value = HeapConstant(isolate()->factory()->the_hole_value()); @@ -2985,7 +2715,7 @@ IGNITION_HANDLER(JumpIfNotHoleConstant, InterpreterAssembler) { // JumpLoop <imm> <loop_depth> // -// Jump by number of bytes represented by the immediate operand |imm|. Also +// Jump by the number of bytes represented by the immediate operand |imm|. Also // performs a loop nesting check and potentially triggers OSR in case the // current OSR level matches (or exceeds) the specified |loop_depth|. IGNITION_HANDLER(JumpLoop, InterpreterAssembler) { @@ -2999,10 +2729,10 @@ IGNITION_HANDLER(JumpLoop, InterpreterAssembler) { Node* condition = Int32GreaterThanOrEqual(loop_depth, osr_level); Branch(condition, &ok, &osr_armed); - Bind(&ok); + BIND(&ok); JumpBackward(relative_jump); - Bind(&osr_armed); + BIND(&osr_armed); { Callable callable = CodeFactory::InterpreterOnStackReplacement(isolate()); Node* target = HeapConstant(callable.code()); @@ -3012,6 +2742,37 @@ IGNITION_HANDLER(JumpLoop, InterpreterAssembler) { } } +// SwitchOnSmiNoFeedback <table_start> <table_length> <case_value_base> +// +// Jump by the number of bytes defined by a Smi in a table in the constant pool, +// where the table starts at |table_start| and has |table_length| entries. +// The table is indexed by the accumulator, minus |case_value_base|. If the +// case_value falls outside of the table |table_length|, fall-through to the +// next bytecode. +IGNITION_HANDLER(SwitchOnSmiNoFeedback, InterpreterAssembler) { + Node* acc = GetAccumulator(); + Node* table_start = BytecodeOperandIdx(0); + Node* table_length = BytecodeOperandUImmWord(1); + Node* case_value_base = BytecodeOperandImmIntPtr(2); + + Label fall_through(this); + + // The accumulator must be a Smi. + // TODO(leszeks): Add a bytecode with type feedback that allows other + // accumulator values. + CSA_ASSERT(this, TaggedIsSmi(acc)); + + Node* case_value = IntPtrSub(SmiUntag(acc), case_value_base); + GotoIf(IntPtrLessThan(case_value, IntPtrConstant(0)), &fall_through); + GotoIf(IntPtrGreaterThanOrEqual(case_value, table_length), &fall_through); + Node* entry = IntPtrAdd(table_start, case_value); + Node* relative_jump = LoadAndUntagConstantPoolEntry(entry); + Jump(relative_jump); + + BIND(&fall_through); + Dispatch(); +} + // CreateRegExpLiteral <pattern_idx> <literal_idx> <flags> // // Creates a regular expression literal for literal index <literal_idx> with @@ -3045,7 +2806,7 @@ IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) { IsSetWord32<CreateArrayLiteralFlags::FastShallowCloneBit>(bytecode_flags), &fast_shallow_clone, &call_runtime); - Bind(&fast_shallow_clone); + BIND(&fast_shallow_clone); { ConstructorBuiltinsAssembler constructor_assembler(state()); Node* result = constructor_assembler.EmitFastCloneShallowArray( @@ -3054,7 +2815,7 @@ IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) { Dispatch(); } - Bind(&call_runtime); + BIND(&call_runtime); { Node* flags_raw = DecodeWordFromWord32<CreateArrayLiteralFlags::FlagsBits>( bytecode_flags); @@ -3079,23 +2840,21 @@ IGNITION_HANDLER(CreateObjectLiteral, InterpreterAssembler) { // Check if we can do a fast clone or have to call the runtime. Label if_fast_clone(this), if_not_fast_clone(this, Label::kDeferred); - Node* fast_clone_properties_count = DecodeWordFromWord32< - CreateObjectLiteralFlags::FastClonePropertiesCountBits>(bytecode_flags); - Branch(WordNotEqual(fast_clone_properties_count, IntPtrConstant(0)), + Branch(IsSetWord32<CreateObjectLiteralFlags::FastCloneSupportedBit>( + bytecode_flags), &if_fast_clone, &if_not_fast_clone); - Bind(&if_fast_clone); + BIND(&if_fast_clone); { // If we can do a fast clone do the fast-path in FastCloneShallowObjectStub. ConstructorBuiltinsAssembler constructor_assembler(state()); Node* result = constructor_assembler.EmitFastCloneShallowObject( - &if_not_fast_clone, closure, literal_index, - fast_clone_properties_count); + &if_not_fast_clone, closure, literal_index); StoreRegister(result, BytecodeOperandReg(3)); Dispatch(); } - Bind(&if_not_fast_clone); + BIND(&if_not_fast_clone); { // If we can't do a fast clone, call into the runtime. Node* index = BytecodeOperandIdx(0); @@ -3135,7 +2894,7 @@ IGNITION_HANDLER(CreateClosure, InterpreterAssembler) { shared, feedback_vector, vector_index, context)); Dispatch(); - Bind(&call_runtime); + BIND(&call_runtime); { Node* tenured_raw = DecodeWordFromWord32<CreateClosureFlags::PretenuredBit>(flags); @@ -3249,7 +3008,7 @@ IGNITION_HANDLER(CreateMappedArguments, InterpreterAssembler) { Node* compare = Word32And(compiler_hints, duplicate_parameters_bit); Branch(compare, &if_duplicate_parameters, &if_not_duplicate_parameters); - Bind(&if_not_duplicate_parameters); + BIND(&if_not_duplicate_parameters); { ArgumentsBuiltinsAssembler constructor_assembler(state()); Node* result = @@ -3258,7 +3017,7 @@ IGNITION_HANDLER(CreateMappedArguments, InterpreterAssembler) { Dispatch(); } - Bind(&if_duplicate_parameters); + BIND(&if_duplicate_parameters); { Node* result = CallRuntime(Runtime::kNewSloppyArguments_Generic, context, closure); @@ -3301,10 +3060,10 @@ IGNITION_HANDLER(StackCheck, InterpreterAssembler) { Node* interrupt = StackCheckTriggeredInterrupt(); Branch(interrupt, &stack_check_interrupt, &ok); - Bind(&ok); + BIND(&ok); Dispatch(); - Bind(&stack_check_interrupt); + BIND(&stack_check_interrupt); { Node* context = GetContext(); CallRuntime(Runtime::kStackGuard, context); @@ -3427,7 +3186,7 @@ IGNITION_HANDLER(ForInPrepare, InterpreterForInPrepareAssembler) { cache_length); Dispatch(); - Bind(&call_runtime); + BIND(&call_runtime); { Node* result_triple = CallRuntime(Runtime::kForInPrepare, context, receiver); @@ -3438,7 +3197,7 @@ IGNITION_HANDLER(ForInPrepare, InterpreterForInPrepareAssembler) { cache_length); Dispatch(); } - Bind(¬hing_to_iterate); + BIND(¬hing_to_iterate); { // Receiver is null or undefined or descriptors are zero length. Node* zero = SmiConstant(0); @@ -3468,13 +3227,13 @@ IGNITION_HANDLER(ForInNext, InterpreterAssembler) { Label if_fast(this), if_slow(this, Label::kDeferred); Node* receiver_map = LoadMap(receiver); Branch(WordEqual(receiver_map, cache_type), &if_fast, &if_slow); - Bind(&if_fast); + BIND(&if_fast); { // Enum cache in use for {receiver}, the {key} is definitely valid. SetAccumulator(key); Dispatch(); } - Bind(&if_slow); + BIND(&if_slow); { // Record the fact that we hit the for-in slow path. Node* vector_index = BytecodeOperandIdx(3); @@ -3505,17 +3264,17 @@ IGNITION_HANDLER(ForInContinue, InterpreterAssembler) { // Check if {index} is at {cache_length} already. Label if_true(this), if_false(this), end(this); Branch(WordEqual(index, cache_length), &if_true, &if_false); - Bind(&if_true); + BIND(&if_true); { SetAccumulator(BooleanConstant(false)); Goto(&end); } - Bind(&if_false); + BIND(&if_false); { SetAccumulator(BooleanConstant(true)); Goto(&end); } - Bind(&end); + BIND(&end); Dispatch(); } @@ -3574,7 +3333,7 @@ IGNITION_HANDLER(SuspendGenerator, InterpreterAssembler) { STATIC_ASSERT(LastStepAction == StepIn); Node* step_next = Int32Constant(StepNext); Branch(Int32LessThanOrEqual(step_next, step_action), &if_stepping, &ok); - Bind(&ok); + BIND(&ok); Node* array = LoadObjectField(generator, JSGeneratorObject::kRegisterFileOffset); @@ -3598,7 +3357,7 @@ IGNITION_HANDLER(SuspendGenerator, InterpreterAssembler) { static_cast<int>(SuspendFlags::kAsyncGeneratorAwait))), &if_asyncgeneratorawait, &if_notasyncgeneratorawait); - Bind(&if_notasyncgeneratorawait); + BIND(&if_notasyncgeneratorawait); { // For ordinary yields (and for AwaitExpressions in Async Functions, which // are implemented as ordinary yields), it is safe to write over the @@ -3608,7 +3367,7 @@ IGNITION_HANDLER(SuspendGenerator, InterpreterAssembler) { Goto(&merge); } - Bind(&if_asyncgeneratorawait); + BIND(&if_asyncgeneratorawait); { // An AwaitExpression in an Async Generator requires writing to the // [await_input_or_debug_pos] field. @@ -3619,10 +3378,10 @@ IGNITION_HANDLER(SuspendGenerator, InterpreterAssembler) { Goto(&merge); } - Bind(&merge); + BIND(&merge); Dispatch(); - Bind(&if_stepping); + BIND(&if_stepping); { Node* context = GetContext(); CallRuntime(Runtime::kDebugRecordGenerator, context, generator); |