5 #include "src/interpreter/interpreter-generator.h" 10 #include "src/builtins/builtins-arguments-gen.h" 11 #include "src/builtins/builtins-constructor-gen.h" 12 #include "src/builtins/builtins-iterator-gen.h" 13 #include "src/code-events.h" 14 #include "src/code-factory.h" 15 #include "src/debug/debug.h" 16 #include "src/ic/accessor-assembler.h" 17 #include "src/ic/binary-op-assembler.h" 18 #include "src/interpreter/bytecode-flags.h" 19 #include "src/interpreter/bytecodes.h" 20 #include "src/interpreter/interpreter-assembler.h" 21 #include "src/interpreter/interpreter-intrinsics-generator.h" 22 #include "src/objects-inl.h" 23 #include "src/objects/js-generator.h" 24 #include "src/objects/module.h" 28 namespace interpreter {
33 typedef CodeStubAssembler::Label Label;
34 typedef CodeStubAssembler::Variable Variable;
36 #define IGNITION_HANDLER(Name, BaseAssembler) \ 37 class Name##Assembler : public BaseAssembler { \ 39 explicit Name##Assembler(compiler::CodeAssemblerState* state, \ 40 Bytecode bytecode, OperandScale scale) \ 41 : BaseAssembler(state, bytecode, scale) {} \ 42 static void Generate(compiler::CodeAssemblerState* state, \ 43 OperandScale scale); \ 46 void GenerateImpl(); \ 47 DISALLOW_COPY_AND_ASSIGN(Name##Assembler); \ 49 void Name##Assembler::Generate(compiler::CodeAssemblerState* state, \ 50 OperandScale scale) { \ 51 Name##Assembler assembler(state, Bytecode::k##Name, scale); \ 52 state->SetInitialDebugInformation(#Name, __FILE__, __LINE__); \ 53 assembler.GenerateImpl(); \ 55 void Name##Assembler::GenerateImpl() 60 IGNITION_HANDLER(LdaZero, InterpreterAssembler) {
61 Node* zero_value = NumberConstant(0.0);
62 SetAccumulator(zero_value);
69 IGNITION_HANDLER(LdaSmi, InterpreterAssembler) {
70 Node* smi_int = BytecodeOperandImmSmi(0);
71 SetAccumulator(smi_int);
78 IGNITION_HANDLER(LdaConstant, InterpreterAssembler) {
79 Node* constant = LoadConstantPoolEntryAtOperandIndex(0);
80 SetAccumulator(constant);
87 IGNITION_HANDLER(LdaUndefined, InterpreterAssembler) {
88 SetAccumulator(UndefinedConstant());
95 IGNITION_HANDLER(LdaNull, InterpreterAssembler) {
96 SetAccumulator(NullConstant());
103 IGNITION_HANDLER(LdaTheHole, InterpreterAssembler) {
104 SetAccumulator(TheHoleConstant());
111 IGNITION_HANDLER(LdaTrue, InterpreterAssembler) {
112 SetAccumulator(TrueConstant());
119 IGNITION_HANDLER(LdaFalse, InterpreterAssembler) {
120 SetAccumulator(FalseConstant());
127 IGNITION_HANDLER(Ldar, InterpreterAssembler) {
128 Node* value = LoadRegisterAtOperandIndex(0);
129 SetAccumulator(value);
136 IGNITION_HANDLER(Star, InterpreterAssembler) {
137 Node* accumulator = GetAccumulator();
138 StoreRegisterAtOperandIndex(accumulator, 0);
145 IGNITION_HANDLER(Mov, InterpreterAssembler) {
146 Node* src_value = LoadRegisterAtOperandIndex(0);
147 StoreRegisterAtOperandIndex(src_value, 1);
151 class InterpreterLoadGlobalAssembler :
public InterpreterAssembler {
153 InterpreterLoadGlobalAssembler(CodeAssemblerState* state, Bytecode bytecode,
154 OperandScale operand_scale)
155 : InterpreterAssembler(state, bytecode, operand_scale) {}
157 void LdaGlobal(
int slot_operand_index,
int name_operand_index,
158 TypeofMode typeof_mode) {
159 TNode<FeedbackVector> feedback_vector = LoadFeedbackVector();
160 Node* feedback_slot = BytecodeOperandIdx(slot_operand_index);
162 AccessorAssembler accessor_asm(state());
163 ExitPoint exit_point(
this, [=](Node* result) {
164 SetAccumulator(result);
168 LazyNode<Context> lazy_context = [=] {
return CAST(GetContext()); };
170 LazyNode<Name> lazy_name = [=] {
171 Node* name = LoadConstantPoolEntryAtOperandIndex(name_operand_index);
175 accessor_asm.LoadGlobalIC(feedback_vector, feedback_slot, lazy_context,
176 lazy_name, typeof_mode, &exit_point,
177 CodeStubAssembler::INTPTR_PARAMETERS);
185 IGNITION_HANDLER(LdaGlobal, InterpreterLoadGlobalAssembler) {
186 static const int kNameOperandIndex = 0;
187 static const int kSlotOperandIndex = 1;
189 LdaGlobal(kSlotOperandIndex, kNameOperandIndex, NOT_INSIDE_TYPEOF);
196 IGNITION_HANDLER(LdaGlobalInsideTypeof, InterpreterLoadGlobalAssembler) {
197 static const int kNameOperandIndex = 0;
198 static const int kSlotOperandIndex = 1;
200 LdaGlobal(kSlotOperandIndex, kNameOperandIndex, INSIDE_TYPEOF);
207 IGNITION_HANDLER(StaGlobal, InterpreterAssembler) {
208 Node* context = GetContext();
211 Node* name = LoadConstantPoolEntryAtOperandIndex(0);
212 Node* value = GetAccumulator();
213 Node* raw_slot = BytecodeOperandIdx(1);
214 Node* smi_slot = SmiTag(raw_slot);
215 Node* feedback_vector = LoadFeedbackVector();
216 CallBuiltin(Builtins::kStoreGlobalIC, context, name, value, smi_slot,
225 IGNITION_HANDLER(LdaContextSlot, InterpreterAssembler) {
226 Node* context = LoadRegisterAtOperandIndex(0);
227 Node* slot_index = BytecodeOperandIdx(1);
228 Node* depth = BytecodeOperandUImm(2);
229 Node* slot_context = GetContextAtDepth(context, depth);
230 Node* result = LoadContextElement(slot_context, slot_index);
231 SetAccumulator(result);
239 IGNITION_HANDLER(LdaImmutableContextSlot, InterpreterAssembler) {
240 Node* context = LoadRegisterAtOperandIndex(0);
241 Node* slot_index = BytecodeOperandIdx(1);
242 Node* depth = BytecodeOperandUImm(2);
243 Node* slot_context = GetContextAtDepth(context, depth);
244 Node* result = LoadContextElement(slot_context, slot_index);
245 SetAccumulator(result);
252 IGNITION_HANDLER(LdaCurrentContextSlot, InterpreterAssembler) {
253 Node* slot_index = BytecodeOperandIdx(0);
254 Node* slot_context = GetContext();
255 Node* result = LoadContextElement(slot_context, slot_index);
256 SetAccumulator(result);
263 IGNITION_HANDLER(LdaImmutableCurrentContextSlot, InterpreterAssembler) {
264 Node* slot_index = BytecodeOperandIdx(0);
265 Node* slot_context = GetContext();
266 Node* result = LoadContextElement(slot_context, slot_index);
267 SetAccumulator(result);
275 IGNITION_HANDLER(StaContextSlot, InterpreterAssembler) {
276 Node* value = GetAccumulator();
277 Node* context = LoadRegisterAtOperandIndex(0);
278 Node* slot_index = BytecodeOperandIdx(1);
279 Node* depth = BytecodeOperandUImm(2);
280 Node* slot_context = GetContextAtDepth(context, depth);
281 StoreContextElement(slot_context, slot_index, value);
289 IGNITION_HANDLER(StaCurrentContextSlot, InterpreterAssembler) {
290 Node* value = GetAccumulator();
291 Node* slot_index = BytecodeOperandIdx(0);
292 Node* slot_context = GetContext();
293 StoreContextElement(slot_context, slot_index, value);
301 IGNITION_HANDLER(LdaLookupSlot, InterpreterAssembler) {
302 Node* name = LoadConstantPoolEntryAtOperandIndex(0);
303 Node* context = GetContext();
304 Node* result = CallRuntime(Runtime::kLoadLookupSlot, context, name);
305 SetAccumulator(result);
313 IGNITION_HANDLER(LdaLookupSlotInsideTypeof, InterpreterAssembler) {
314 Node* name = LoadConstantPoolEntryAtOperandIndex(0);
315 Node* context = GetContext();
317 CallRuntime(Runtime::kLoadLookupSlotInsideTypeof, context, name);
318 SetAccumulator(result);
322 class InterpreterLookupContextSlotAssembler :
public InterpreterAssembler {
324 InterpreterLookupContextSlotAssembler(CodeAssemblerState* state,
326 OperandScale operand_scale)
327 : InterpreterAssembler(state, bytecode, operand_scale) {}
329 void LookupContextSlot(Runtime::FunctionId function_id) {
330 Node* context = GetContext();
331 Node* slot_index = BytecodeOperandIdx(1);
332 Node* depth = BytecodeOperandUImm(2);
334 Label slowpath(
this, Label::kDeferred);
337 GotoIfHasContextExtensionUpToDepth(context, depth, &slowpath);
341 Node* slot_context = GetContextAtDepth(context, depth);
342 Node* result = LoadContextElement(slot_context, slot_index);
343 SetAccumulator(result);
350 Node* name = LoadConstantPoolEntryAtOperandIndex(0);
351 Node* result = CallRuntime(function_id, context, name);
352 SetAccumulator(result);
362 IGNITION_HANDLER(LdaLookupContextSlot, InterpreterLookupContextSlotAssembler) {
363 LookupContextSlot(Runtime::kLoadLookupSlot);
370 IGNITION_HANDLER(LdaLookupContextSlotInsideTypeof,
371 InterpreterLookupContextSlotAssembler) {
372 LookupContextSlot(Runtime::kLoadLookupSlotInsideTypeof);
375 class InterpreterLookupGlobalAssembler :
public InterpreterLoadGlobalAssembler {
377 InterpreterLookupGlobalAssembler(CodeAssemblerState* state, Bytecode bytecode,
378 OperandScale operand_scale)
379 : InterpreterLoadGlobalAssembler(state, bytecode, operand_scale) {}
381 void LookupGlobalSlot(Runtime::FunctionId function_id) {
382 Node* context = GetContext();
383 Node* depth = BytecodeOperandUImm(2);
385 Label slowpath(
this, Label::kDeferred);
388 GotoIfHasContextExtensionUpToDepth(context, depth, &slowpath);
392 static const int kNameOperandIndex = 0;
393 static const int kSlotOperandIndex = 1;
395 TypeofMode typeof_mode =
396 function_id == Runtime::kLoadLookupSlotInsideTypeof
400 LdaGlobal(kSlotOperandIndex, kNameOperandIndex, typeof_mode);
406 Node* name = LoadConstantPoolEntryAtOperandIndex(0);
407 Node* result = CallRuntime(function_id, context, name);
408 SetAccumulator(result);
418 IGNITION_HANDLER(LdaLookupGlobalSlot, InterpreterLookupGlobalAssembler) {
419 LookupGlobalSlot(Runtime::kLoadLookupSlot);
426 IGNITION_HANDLER(LdaLookupGlobalSlotInsideTypeof,
427 InterpreterLookupGlobalAssembler) {
428 LookupGlobalSlot(Runtime::kLoadLookupSlotInsideTypeof);
435 IGNITION_HANDLER(StaLookupSlot, InterpreterAssembler) {
436 Node* value = GetAccumulator();
437 Node* name = LoadConstantPoolEntryAtOperandIndex(0);
438 Node* bytecode_flags = BytecodeOperandFlag(1);
439 Node* context = GetContext();
440 Variable var_result(
this, MachineRepresentation::kTagged);
442 Label sloppy(
this), strict(
this), end(
this);
443 DCHECK_EQ(0, LanguageMode::kSloppy);
444 DCHECK_EQ(1, LanguageMode::kStrict);
445 DCHECK_EQ(0, static_cast<int>(LookupHoistingMode::kNormal));
446 DCHECK_EQ(1, static_cast<int>(LookupHoistingMode::kLegacySloppy));
447 Branch(IsSetWord32<StoreLookupSlotFlags::LanguageModeBit>(bytecode_flags),
452 CSA_ASSERT(
this, IsClearWord32<StoreLookupSlotFlags::LookupHoistingModeBit>(
455 CallRuntime(Runtime::kStoreLookupSlot_Strict, context, name, value));
461 Label hoisting(
this), ordinary(
this);
462 Branch(IsSetWord32<StoreLookupSlotFlags::LookupHoistingModeBit>(
464 &hoisting, &ordinary);
468 var_result.Bind(CallRuntime(Runtime::kStoreLookupSlot_SloppyHoisting,
469 context, name, value));
476 CallRuntime(Runtime::kStoreLookupSlot_Sloppy, context, name, value));
483 SetAccumulator(var_result.value());
492 IGNITION_HANDLER(LdaNamedProperty, InterpreterAssembler) {
493 Node* feedback_vector = LoadFeedbackVector();
494 Node* feedback_slot = BytecodeOperandIdx(2);
495 Node* smi_slot = SmiTag(feedback_slot);
498 Node* recv = LoadRegisterAtOperandIndex(0);
502 Node* name = LoadConstantPoolEntryAtOperandIndex(1);
503 Node* context = GetContext();
506 Variable var_result(
this, MachineRepresentation::kTagged);
507 ExitPoint exit_point(
this, &done, &var_result);
509 AccessorAssembler::LoadICParameters params(context, recv, name, smi_slot,
511 AccessorAssembler accessor_asm(state());
512 accessor_asm.LoadIC_BytecodeHandler(¶ms, &exit_point);
516 SetAccumulator(var_result.value());
524 IGNITION_HANDLER(LdaNamedPropertyNoFeedback, InterpreterAssembler) {
525 Node*
object = LoadRegisterAtOperandIndex(0);
526 Node* name = LoadConstantPoolEntryAtOperandIndex(1);
527 Node* context = GetContext();
528 Node* result = CallBuiltin(Builtins::kGetProperty, context,
object, name);
529 SetAccumulator(result);
537 IGNITION_HANDLER(LdaKeyedProperty, InterpreterAssembler) {
538 Node*
object = LoadRegisterAtOperandIndex(0);
539 Node* name = GetAccumulator();
540 Node* raw_slot = BytecodeOperandIdx(1);
541 Node* smi_slot = SmiTag(raw_slot);
542 Node* feedback_vector = LoadFeedbackVector();
543 Node* context = GetContext();
544 Node* result = CallBuiltin(Builtins::kKeyedLoadIC, context,
object, name,
545 smi_slot, feedback_vector);
546 SetAccumulator(result);
550 class InterpreterStoreNamedPropertyAssembler :
public InterpreterAssembler {
552 InterpreterStoreNamedPropertyAssembler(CodeAssemblerState* state,
554 OperandScale operand_scale)
555 : InterpreterAssembler(state, bytecode, operand_scale) {}
557 void StaNamedProperty(Callable ic) {
558 Node* code_target = HeapConstant(ic.code());
559 Node*
object = LoadRegisterAtOperandIndex(0);
560 Node* name = LoadConstantPoolEntryAtOperandIndex(1);
561 Node* value = GetAccumulator();
562 Node* raw_slot = BytecodeOperandIdx(2);
563 Node* smi_slot = SmiTag(raw_slot);
564 Node* feedback_vector = LoadFeedbackVector();
565 Node* context = GetContext();
566 Node* result = CallStub(ic.descriptor(), code_target, context, object, name,
567 value, smi_slot, feedback_vector);
573 SetAccumulator(result);
583 IGNITION_HANDLER(StaNamedProperty, InterpreterStoreNamedPropertyAssembler) {
584 Callable ic = Builtins::CallableFor(isolate(), Builtins::kStoreIC);
585 StaNamedProperty(ic);
593 IGNITION_HANDLER(StaNamedOwnProperty, InterpreterStoreNamedPropertyAssembler) {
594 Callable ic = CodeFactory::StoreOwnICInOptimizedCode(isolate());
595 StaNamedProperty(ic);
602 IGNITION_HANDLER(StaNamedPropertyNoFeedback,
603 InterpreterStoreNamedPropertyAssembler) {
604 Node*
object = LoadRegisterAtOperandIndex(0);
605 Node* name = LoadConstantPoolEntryAtOperandIndex(1);
606 Node* value = GetAccumulator();
607 Node* language_mode = SmiFromInt32(BytecodeOperandFlag(2));
608 Node* context = GetContext();
610 Node* result = CallRuntime(Runtime::kSetNamedProperty, context,
object, name,
611 value, language_mode);
612 SetAccumulator(result);
620 IGNITION_HANDLER(StaKeyedProperty, InterpreterAssembler) {
621 Node*
object = LoadRegisterAtOperandIndex(0);
622 Node* name = LoadRegisterAtOperandIndex(1);
623 Node* value = GetAccumulator();
624 Node* raw_slot = BytecodeOperandIdx(2);
625 Node* smi_slot = SmiTag(raw_slot);
626 Node* feedback_vector = LoadFeedbackVector();
627 Node* context = GetContext();
628 Node* result = CallBuiltin(Builtins::kKeyedStoreIC, context,
object, name,
629 value, smi_slot, feedback_vector);
635 SetAccumulator(result);
643 IGNITION_HANDLER(StaInArrayLiteral, InterpreterAssembler) {
644 Node* array = LoadRegisterAtOperandIndex(0);
645 Node* index = LoadRegisterAtOperandIndex(1);
646 Node* value = GetAccumulator();
647 Node* raw_slot = BytecodeOperandIdx(2);
648 Node* smi_slot = SmiTag(raw_slot);
649 Node* feedback_vector = LoadFeedbackVector();
650 Node* context = GetContext();
651 Node* result = CallBuiltin(Builtins::kStoreInArrayLiteralIC, context, array,
652 index, value, smi_slot, feedback_vector);
658 SetAccumulator(result);
670 IGNITION_HANDLER(StaDataPropertyInLiteral, InterpreterAssembler) {
671 Node*
object = LoadRegisterAtOperandIndex(0);
672 Node* name = LoadRegisterAtOperandIndex(1);
673 Node* value = GetAccumulator();
674 Node* flags = SmiFromInt32(BytecodeOperandFlag(2));
675 Node* vector_index = SmiTag(BytecodeOperandIdx(3));
677 Node* feedback_vector = LoadFeedbackVector();
678 Node* context = GetContext();
680 CallRuntime(Runtime::kDefineDataPropertyInLiteral, context,
object, name,
681 value, flags, feedback_vector, vector_index);
685 IGNITION_HANDLER(CollectTypeProfile, InterpreterAssembler) {
686 Node* position = BytecodeOperandImmSmi(0);
687 Node* value = GetAccumulator();
689 Node* feedback_vector = LoadFeedbackVector();
690 Node* context = GetContext();
692 CallRuntime(Runtime::kCollectTypeProfile, context, position, value,
702 IGNITION_HANDLER(LdaModuleVariable, InterpreterAssembler) {
703 Node* cell_index = BytecodeOperandImmIntPtr(0);
704 Node* depth = BytecodeOperandUImm(1);
706 Node* module_context = GetContextAtDepth(GetContext(), depth);
707 Node* module = LoadContextElement(module_context, Context::EXTENSION_INDEX);
709 Label if_export(
this), if_import(
this), end(
this);
710 Branch(IntPtrGreaterThan(cell_index, IntPtrConstant(0)), &if_export,
715 TNode<FixedArray> regular_exports =
716 CAST(LoadObjectField(module, Module::kRegularExportsOffset));
718 Node* export_index = IntPtrSub(cell_index, IntPtrConstant(1));
719 Node* cell = LoadFixedArrayElement(regular_exports, export_index);
720 SetAccumulator(LoadObjectField(cell, Cell::kValueOffset));
726 TNode<FixedArray> regular_imports =
727 CAST(LoadObjectField(module, Module::kRegularImportsOffset));
729 Node* import_index = IntPtrSub(IntPtrConstant(-1), cell_index);
730 Node* cell = LoadFixedArrayElement(regular_imports, import_index);
731 SetAccumulator(LoadObjectField(cell, Cell::kValueOffset));
743 IGNITION_HANDLER(StaModuleVariable, InterpreterAssembler) {
744 Node* value = GetAccumulator();
745 Node* cell_index = BytecodeOperandImmIntPtr(0);
746 Node* depth = BytecodeOperandUImm(1);
748 Node* module_context = GetContextAtDepth(GetContext(), depth);
749 Node* module = LoadContextElement(module_context, Context::EXTENSION_INDEX);
751 Label if_export(
this), if_import(
this), end(
this);
752 Branch(IntPtrGreaterThan(cell_index, IntPtrConstant(0)), &if_export,
757 TNode<FixedArray> regular_exports =
758 CAST(LoadObjectField(module, Module::kRegularExportsOffset));
760 Node* export_index = IntPtrSub(cell_index, IntPtrConstant(1));
761 Node* cell = LoadFixedArrayElement(regular_exports, export_index);
762 StoreObjectField(cell, Cell::kValueOffset, value);
769 Abort(AbortReason::kUnsupportedModuleOperation);
781 IGNITION_HANDLER(PushContext, InterpreterAssembler) {
782 Node* new_context = GetAccumulator();
783 Node* old_context = GetContext();
784 StoreRegisterAtOperandIndex(old_context, 0);
785 SetContext(new_context);
792 IGNITION_HANDLER(PopContext, InterpreterAssembler) {
793 Node* context = LoadRegisterAtOperandIndex(0);
798 class InterpreterBinaryOpAssembler :
public InterpreterAssembler {
800 InterpreterBinaryOpAssembler(CodeAssemblerState* state, Bytecode bytecode,
801 OperandScale operand_scale)
802 : InterpreterAssembler(state, bytecode, operand_scale) {}
804 typedef Node* (BinaryOpAssembler::*BinaryOpGenerator)(Node* context,
805 Node* left, Node* right,
810 void BinaryOpWithFeedback(BinaryOpGenerator generator) {
811 Node* lhs = LoadRegisterAtOperandIndex(0);
812 Node* rhs = GetAccumulator();
813 Node* context = GetContext();
814 Node* slot_index = BytecodeOperandIdx(1);
815 Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
817 BinaryOpAssembler binop_asm(state());
818 Node* result = (binop_asm.*generator)(context, lhs, rhs, slot_index,
819 maybe_feedback_vector,
false);
820 SetAccumulator(result);
824 void BinaryOpSmiWithFeedback(BinaryOpGenerator generator) {
825 Node* lhs = GetAccumulator();
826 Node* rhs = BytecodeOperandImmSmi(0);
827 Node* context = GetContext();
828 Node* slot_index = BytecodeOperandIdx(1);
829 Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
831 BinaryOpAssembler binop_asm(state());
832 Node* result = (binop_asm.*generator)(context, lhs, rhs, slot_index,
833 maybe_feedback_vector,
true);
834 SetAccumulator(result);
842 IGNITION_HANDLER(Add, InterpreterBinaryOpAssembler) {
843 BinaryOpWithFeedback(&BinaryOpAssembler::Generate_AddWithFeedback);
849 IGNITION_HANDLER(Sub, InterpreterBinaryOpAssembler) {
850 BinaryOpWithFeedback(&BinaryOpAssembler::Generate_SubtractWithFeedback);
856 IGNITION_HANDLER(Mul, InterpreterBinaryOpAssembler) {
857 BinaryOpWithFeedback(&BinaryOpAssembler::Generate_MultiplyWithFeedback);
863 IGNITION_HANDLER(Div, InterpreterBinaryOpAssembler) {
864 BinaryOpWithFeedback(&BinaryOpAssembler::Generate_DivideWithFeedback);
870 IGNITION_HANDLER(Mod, InterpreterBinaryOpAssembler) {
871 BinaryOpWithFeedback(&BinaryOpAssembler::Generate_ModulusWithFeedback);
877 IGNITION_HANDLER(Exp, InterpreterBinaryOpAssembler) {
878 BinaryOpWithFeedback(&BinaryOpAssembler::Generate_ExponentiateWithFeedback);
884 IGNITION_HANDLER(AddSmi, InterpreterBinaryOpAssembler) {
885 BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_AddWithFeedback);
891 IGNITION_HANDLER(SubSmi, InterpreterBinaryOpAssembler) {
892 BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_SubtractWithFeedback);
898 IGNITION_HANDLER(MulSmi, InterpreterBinaryOpAssembler) {
899 BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_MultiplyWithFeedback);
905 IGNITION_HANDLER(DivSmi, InterpreterBinaryOpAssembler) {
906 BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_DivideWithFeedback);
912 IGNITION_HANDLER(ModSmi, InterpreterBinaryOpAssembler) {
913 BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_ModulusWithFeedback);
919 IGNITION_HANDLER(ExpSmi, InterpreterBinaryOpAssembler) {
920 BinaryOpSmiWithFeedback(
921 &BinaryOpAssembler::Generate_ExponentiateWithFeedback);
924 class InterpreterBitwiseBinaryOpAssembler :
public InterpreterAssembler {
926 InterpreterBitwiseBinaryOpAssembler(CodeAssemblerState* state,
928 OperandScale operand_scale)
929 : InterpreterAssembler(state, bytecode, operand_scale) {}
931 void BitwiseBinaryOpWithFeedback(Operation bitwise_op) {
932 Node* left = LoadRegisterAtOperandIndex(0);
933 Node* right = GetAccumulator();
934 Node* context = GetContext();
935 Node* slot_index = BytecodeOperandIdx(1);
936 Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
938 TVARIABLE(Smi, var_left_feedback);
939 TVARIABLE(Smi, var_right_feedback);
940 VARIABLE(var_left_word32, MachineRepresentation::kWord32);
941 VARIABLE(var_right_word32, MachineRepresentation::kWord32);
942 VARIABLE(var_left_bigint, MachineRepresentation::kTagged, left);
943 VARIABLE(var_right_bigint, MachineRepresentation::kTagged);
944 Label if_left_number(
this), do_number_op(
this);
945 Label if_left_bigint(
this), do_bigint_op(
this);
947 TaggedToWord32OrBigIntWithFeedback(context, left, &if_left_number,
948 &var_left_word32, &if_left_bigint,
949 &var_left_bigint, &var_left_feedback);
950 BIND(&if_left_number);
951 TaggedToWord32OrBigIntWithFeedback(context, right, &do_number_op,
952 &var_right_word32, &do_bigint_op,
953 &var_right_bigint, &var_right_feedback);
955 TNode<Number> result = BitwiseOp(var_left_word32.value(),
956 var_right_word32.value(), bitwise_op);
957 TNode<Smi> result_type = SelectSmiConstant(
958 TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
959 BinaryOperationFeedback::kNumber);
960 TNode<Smi> input_feedback =
961 SmiOr(var_left_feedback.value(), var_right_feedback.value());
962 UpdateFeedback(SmiOr(result_type, input_feedback), maybe_feedback_vector,
964 SetAccumulator(result);
968 BIND(&if_left_bigint);
969 TaggedToNumericWithFeedback(context, right, &do_bigint_op,
970 &var_right_bigint, &var_right_feedback);
974 CallRuntime(Runtime::kBigIntBinaryOp, context, var_left_bigint.value(),
975 var_right_bigint.value(), SmiConstant(bitwise_op)));
976 UpdateFeedback(SmiOr(var_left_feedback.value(), var_right_feedback.value()),
977 maybe_feedback_vector, slot_index);
981 void BitwiseBinaryOpWithSmi(Operation bitwise_op) {
982 Node* left = GetAccumulator();
983 Node* right = BytecodeOperandImmSmi(0);
984 Node* slot_index = BytecodeOperandIdx(1);
985 Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
986 Node* context = GetContext();
988 TVARIABLE(Smi, var_left_feedback);
989 VARIABLE(var_left_word32, MachineRepresentation::kWord32);
990 VARIABLE(var_left_bigint, MachineRepresentation::kTagged);
991 Label do_smi_op(
this), if_bigint_mix(
this);
993 TaggedToWord32OrBigIntWithFeedback(context, left, &do_smi_op,
994 &var_left_word32, &if_bigint_mix,
995 &var_left_bigint, &var_left_feedback);
997 TNode<Number> result =
998 BitwiseOp(var_left_word32.value(), SmiToInt32(right), bitwise_op);
999 TNode<Smi> result_type = SelectSmiConstant(
1000 TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
1001 BinaryOperationFeedback::kNumber);
1002 UpdateFeedback(SmiOr(result_type, var_left_feedback.value()),
1003 maybe_feedback_vector, slot_index);
1004 SetAccumulator(result);
1007 BIND(&if_bigint_mix);
1008 UpdateFeedback(var_left_feedback.value(), maybe_feedback_vector,
1010 ThrowTypeError(context, MessageTemplate::kBigIntMixedTypes);
1017 IGNITION_HANDLER(BitwiseOr, InterpreterBitwiseBinaryOpAssembler) {
1018 BitwiseBinaryOpWithFeedback(Operation::kBitwiseOr);
1024 IGNITION_HANDLER(BitwiseXor, InterpreterBitwiseBinaryOpAssembler) {
1025 BitwiseBinaryOpWithFeedback(Operation::kBitwiseXor);
1031 IGNITION_HANDLER(BitwiseAnd, InterpreterBitwiseBinaryOpAssembler) {
1032 BitwiseBinaryOpWithFeedback(Operation::kBitwiseAnd);
1041 IGNITION_HANDLER(ShiftLeft, InterpreterBitwiseBinaryOpAssembler) {
1042 BitwiseBinaryOpWithFeedback(Operation::kShiftLeft);
1051 IGNITION_HANDLER(ShiftRight, InterpreterBitwiseBinaryOpAssembler) {
1052 BitwiseBinaryOpWithFeedback(Operation::kShiftRight);
1061 IGNITION_HANDLER(ShiftRightLogical, InterpreterBitwiseBinaryOpAssembler) {
1062 BitwiseBinaryOpWithFeedback(Operation::kShiftRightLogical);
1068 IGNITION_HANDLER(BitwiseOrSmi, InterpreterBitwiseBinaryOpAssembler) {
1069 BitwiseBinaryOpWithSmi(Operation::kBitwiseOr);
1075 IGNITION_HANDLER(BitwiseXorSmi, InterpreterBitwiseBinaryOpAssembler) {
1076 BitwiseBinaryOpWithSmi(Operation::kBitwiseXor);
1082 IGNITION_HANDLER(BitwiseAndSmi, InterpreterBitwiseBinaryOpAssembler) {
1083 BitwiseBinaryOpWithSmi(Operation::kBitwiseAnd);
1089 IGNITION_HANDLER(BitwiseNot, InterpreterAssembler) {
1090 Node* operand = GetAccumulator();
1091 Node* slot_index = BytecodeOperandIdx(0);
1092 Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
1093 Node* context = GetContext();
1095 VARIABLE(var_word32, MachineRepresentation::kWord32);
1096 TVARIABLE(Smi, var_feedback);
1097 VARIABLE(var_bigint, MachineRepresentation::kTagged);
1098 Label if_number(
this), if_bigint(
this);
1099 TaggedToWord32OrBigIntWithFeedback(context, operand, &if_number, &var_word32,
1100 &if_bigint, &var_bigint, &var_feedback);
1104 TNode<Number> result =
1105 ChangeInt32ToTagged(Signed(Word32BitwiseNot(var_word32.value())));
1106 TNode<Smi> result_type = SelectSmiConstant(
1107 TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
1108 BinaryOperationFeedback::kNumber);
1109 UpdateFeedback(SmiOr(result_type, var_feedback.value()),
1110 maybe_feedback_vector, slot_index);
1111 SetAccumulator(result);
1116 UpdateFeedback(SmiConstant(BinaryOperationFeedback::kBigInt),
1117 maybe_feedback_vector, slot_index);
1118 SetAccumulator(CallRuntime(Runtime::kBigIntUnaryOp, context,
1120 SmiConstant(Operation::kBitwiseNot)));
1129 IGNITION_HANDLER(ShiftLeftSmi, InterpreterBitwiseBinaryOpAssembler) {
1130 BitwiseBinaryOpWithSmi(Operation::kShiftLeft);
1138 IGNITION_HANDLER(ShiftRightSmi, InterpreterBitwiseBinaryOpAssembler) {
1139 BitwiseBinaryOpWithSmi(Operation::kShiftRight);
1147 IGNITION_HANDLER(ShiftRightLogicalSmi, InterpreterBitwiseBinaryOpAssembler) {
1148 BitwiseBinaryOpWithSmi(Operation::kShiftRightLogical);
1151 class UnaryNumericOpAssembler :
public InterpreterAssembler {
1153 UnaryNumericOpAssembler(CodeAssemblerState* state, Bytecode bytecode,
1154 OperandScale operand_scale)
1155 : InterpreterAssembler(state, bytecode, operand_scale) {}
1157 virtual ~UnaryNumericOpAssembler() =
default;
1160 virtual TNode<Number> SmiOp(TNode<Smi> smi_value, Variable* var_feedback,
1161 Label* do_float_op, Variable* var_float) = 0;
1163 virtual Node* FloatOp(Node* float_value) = 0;
1165 virtual Node* BigIntOp(Node* bigint_value) = 0;
1167 void UnaryOpWithFeedback() {
1168 VARIABLE(var_value, MachineRepresentation::kTagged, GetAccumulator());
1169 Node* slot_index = BytecodeOperandIdx(0);
1170 Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
1172 VARIABLE(var_result, MachineRepresentation::kTagged);
1173 VARIABLE(var_float_value, MachineRepresentation::kFloat64);
1174 TVARIABLE(Smi, var_feedback, SmiConstant(BinaryOperationFeedback::kNone));
1175 Variable* loop_vars[] = {&var_value, &var_feedback};
1176 Label start(
this, arraysize(loop_vars), loop_vars), end(
this);
1177 Label do_float_op(
this, &var_float_value);
1182 Label if_smi(
this), if_heapnumber(
this), if_bigint(
this);
1183 Label if_oddball(
this), if_other(
this);
1184 Node* value = var_value.value();
1185 GotoIf(TaggedIsSmi(value), &if_smi);
1186 Node* map = LoadMap(value);
1187 GotoIf(IsHeapNumberMap(map), &if_heapnumber);
1188 Node* instance_type = LoadMapInstanceType(map);
1189 GotoIf(IsBigIntInstanceType(instance_type), &if_bigint);
1190 Branch(InstanceTypeEqual(instance_type, ODDBALL_TYPE), &if_oddball,
1196 SmiOp(CAST(value), &var_feedback, &do_float_op, &var_float_value));
1200 BIND(&if_heapnumber);
1202 var_float_value.Bind(LoadHeapNumberValue(value));
1208 var_result.Bind(BigIntOp(value));
1209 CombineFeedback(&var_feedback, BinaryOperationFeedback::kBigInt);
1218 CSA_ASSERT(
this, SmiEqual(var_feedback.value(),
1219 SmiConstant(BinaryOperationFeedback::kNone)));
1220 OverwriteFeedback(&var_feedback,
1221 BinaryOperationFeedback::kNumberOrOddball);
1222 var_value.Bind(LoadObjectField(value, Oddball::kToNumberOffset));
1231 CSA_ASSERT(
this, SmiEqual(var_feedback.value(),
1232 SmiConstant(BinaryOperationFeedback::kNone)));
1233 OverwriteFeedback(&var_feedback, BinaryOperationFeedback::kAny);
1235 CallBuiltin(Builtins::kNonNumberToNumeric, GetContext(), value));
1242 CombineFeedback(&var_feedback, BinaryOperationFeedback::kNumber);
1244 AllocateHeapNumberWithValue(FloatOp(var_float_value.value())));
1249 UpdateFeedback(var_feedback.value(), maybe_feedback_vector, slot_index);
1250 SetAccumulator(var_result.value());
1255 class NegateAssemblerImpl :
public UnaryNumericOpAssembler {
1257 explicit NegateAssemblerImpl(CodeAssemblerState* state, Bytecode bytecode,
1258 OperandScale operand_scale)
1259 : UnaryNumericOpAssembler(state, bytecode, operand_scale) {}
1261 TNode<Number> SmiOp(TNode<Smi> smi_value, Variable* var_feedback,
1262 Label* do_float_op, Variable* var_float)
override {
1263 TVARIABLE(Number, var_result);
1264 Label if_zero(
this), if_min_smi(
this), end(
this);
1266 GotoIf(SmiEqual(smi_value, SmiConstant(0)), &if_zero);
1269 GotoIf(SmiEqual(smi_value, SmiConstant(Smi::kMinValue)), &if_min_smi);
1272 CombineFeedback(var_feedback, BinaryOperationFeedback::kSignedSmall);
1273 var_result = SmiSub(SmiConstant(0), smi_value);
1277 CombineFeedback(var_feedback, BinaryOperationFeedback::kNumber);
1278 var_result = MinusZeroConstant();
1282 var_float->Bind(SmiToFloat64(smi_value));
1286 return var_result.value();
1289 Node* FloatOp(Node* float_value)
override {
return Float64Neg(float_value); }
1291 Node* BigIntOp(Node* bigint_value)
override {
1292 return CallRuntime(Runtime::kBigIntUnaryOp, GetContext(), bigint_value,
1293 SmiConstant(Operation::kNegate));
1300 IGNITION_HANDLER(Negate, NegateAssemblerImpl) { UnaryOpWithFeedback(); }
1305 IGNITION_HANDLER(ToName, InterpreterAssembler) {
1306 Node*
object = GetAccumulator();
1307 Node* context = GetContext();
1308 Node* result = CallBuiltin(Builtins::kToName, context,
object);
1309 StoreRegisterAtOperandIndex(result, 0);
1316 IGNITION_HANDLER(ToNumber, InterpreterAssembler) {
1317 ToNumberOrNumeric(Object::Conversion::kToNumber);
1323 IGNITION_HANDLER(ToNumeric, InterpreterAssembler) {
1324 ToNumberOrNumeric(Object::Conversion::kToNumeric);
1330 IGNITION_HANDLER(ToObject, InterpreterAssembler) {
1331 Node* accumulator = GetAccumulator();
1332 Node* context = GetContext();
1333 Node* result = CallBuiltin(Builtins::kToObject, context, accumulator);
1334 StoreRegisterAtOperandIndex(result, 0);
1341 IGNITION_HANDLER(ToString, InterpreterAssembler) {
1342 SetAccumulator(ToString_Inline(GetContext(), GetAccumulator()));
1346 class IncDecAssembler :
public UnaryNumericOpAssembler {
1348 explicit IncDecAssembler(CodeAssemblerState* state, Bytecode bytecode,
1349 OperandScale operand_scale)
1350 : UnaryNumericOpAssembler(state, bytecode, operand_scale) {}
1353 DCHECK(op_ == Operation::kIncrement || op_ == Operation::kDecrement);
1357 TNode<Number> SmiOp(TNode<Smi> value, Variable* var_feedback,
1358 Label* do_float_op, Variable* var_float)
override {
1359 TNode<Smi> one = SmiConstant(1);
1360 Label if_overflow(
this), if_notoverflow(
this);
1361 TNode<Smi> result = op() == Operation::kIncrement
1362 ? TrySmiAdd(value, one, &if_overflow)
1363 : TrySmiSub(value, one, &if_overflow);
1364 Goto(&if_notoverflow);
1368 var_float->Bind(SmiToFloat64(value));
1372 BIND(&if_notoverflow);
1373 CombineFeedback(var_feedback, BinaryOperationFeedback::kSignedSmall);
1377 Node* FloatOp(Node* float_value)
override {
1378 return op() == Operation::kIncrement
1379 ? Float64Add(float_value, Float64Constant(1.0))
1380 : Float64Sub(float_value, Float64Constant(1.0));
1383 Node* BigIntOp(Node* bigint_value)
override {
1384 return CallRuntime(Runtime::kBigIntUnaryOp, GetContext(), bigint_value,
1388 void IncWithFeedback() {
1389 op_ = Operation::kIncrement;
1390 UnaryOpWithFeedback();
1393 void DecWithFeedback() {
1394 op_ = Operation::kDecrement;
1395 UnaryOpWithFeedback();
1399 Operation op_ = Operation::kEqual;
1405 IGNITION_HANDLER(Inc, IncDecAssembler) { IncWithFeedback(); }
1410 IGNITION_HANDLER(Dec, IncDecAssembler) { DecWithFeedback(); }
1417 IGNITION_HANDLER(ToBooleanLogicalNot, InterpreterAssembler) {
1418 Node* value = GetAccumulator();
1419 Variable result(
this, MachineRepresentation::kTagged);
1420 Label if_true(
this), if_false(
this), end(
this);
1421 BranchIfToBooleanIsTrue(value, &if_true, &if_false);
1424 result.Bind(FalseConstant());
1429 result.Bind(TrueConstant());
1433 SetAccumulator(result.value());
1441 IGNITION_HANDLER(LogicalNot, InterpreterAssembler) {
1442 Node* value = GetAccumulator();
1443 Variable result(
this, MachineRepresentation::kTagged);
1444 Label if_true(
this), if_false(
this), end(
this);
1445 Node* true_value = TrueConstant();
1446 Node* false_value = FalseConstant();
1447 Branch(WordEqual(value, true_value), &if_true, &if_false);
1450 result.Bind(false_value);
1455 CSA_ASSERT(
this, WordEqual(value, false_value));
1456 result.Bind(true_value);
1460 SetAccumulator(result.value());
1468 IGNITION_HANDLER(TypeOf, InterpreterAssembler) {
1469 Node* value = GetAccumulator();
1470 Node* result = Typeof(value);
1471 SetAccumulator(result);
1479 IGNITION_HANDLER(DeletePropertyStrict, InterpreterAssembler) {
1480 Node*
object = LoadRegisterAtOperandIndex(0);
1481 Node* key = GetAccumulator();
1482 Node* context = GetContext();
1483 Node* result = CallBuiltin(Builtins::kDeleteProperty, context,
object, key,
1484 SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
1485 SetAccumulator(result);
1493 IGNITION_HANDLER(DeletePropertySloppy, InterpreterAssembler) {
1494 Node*
object = LoadRegisterAtOperandIndex(0);
1495 Node* key = GetAccumulator();
1496 Node* context = GetContext();
1497 Node* result = CallBuiltin(Builtins::kDeleteProperty, context,
object, key,
1498 SmiConstant(Smi::FromEnum(LanguageMode::kSloppy)));
1499 SetAccumulator(result);
1507 IGNITION_HANDLER(GetSuperConstructor, InterpreterAssembler) {
1508 Node* active_function = GetAccumulator();
1509 Node* context = GetContext();
1510 Node* result = GetSuperConstructor(context, active_function);
1511 StoreRegisterAtOperandIndex(result, 0);
1515 class InterpreterJSCallAssembler :
public InterpreterAssembler {
1517 InterpreterJSCallAssembler(CodeAssemblerState* state, Bytecode bytecode,
1518 OperandScale operand_scale)
1519 : InterpreterAssembler(state, bytecode, operand_scale) {}
1522 void JSCall(ConvertReceiverMode receiver_mode) {
1523 Node*
function = LoadRegisterAtOperandIndex(0);
1524 RegListNodePair args = GetRegisterListAtOperandIndex(1);
1525 Node* slot_id = BytecodeOperandIdx(3);
1526 Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
1527 Node* context = GetContext();
1530 CollectCallFeedback(
function, context, maybe_feedback_vector, slot_id);
1533 CallJSAndDispatch(
function, context, args, receiver_mode);
1537 void JSCallNoFeedback(ConvertReceiverMode receiver_mode) {
1538 Node*
function = LoadRegisterAtOperandIndex(0);
1539 RegListNodePair args = GetRegisterListAtOperandIndex(1);
1540 Node* context = GetContext();
1543 CallJSAndDispatch(
function, context, args, receiver_mode);
1548 void JSCallN(
int arg_count, ConvertReceiverMode receiver_mode) {
1550 const int kFirstArgumentOperandIndex = 1;
1551 const int kReceiverOperandCount =
1552 (receiver_mode == ConvertReceiverMode::kNullOrUndefined) ? 0 : 1;
1553 const int kRecieverAndArgOperandCount = kReceiverOperandCount + arg_count;
1554 const int kSlotOperandIndex =
1555 kFirstArgumentOperandIndex + kRecieverAndArgOperandCount;
1557 Node*
function = LoadRegisterAtOperandIndex(0);
1558 Node* slot_id = BytecodeOperandIdx(kSlotOperandIndex);
1559 Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
1560 Node* context = GetContext();
1563 CollectCallFeedback(
function, context, maybe_feedback_vector, slot_id);
1565 switch (kRecieverAndArgOperandCount) {
1567 CallJSAndDispatch(
function, context, Int32Constant(arg_count),
1572 function, context, Int32Constant(arg_count), receiver_mode,
1573 LoadRegisterAtOperandIndex(kFirstArgumentOperandIndex));
1577 function, context, Int32Constant(arg_count), receiver_mode,
1578 LoadRegisterAtOperandIndex(kFirstArgumentOperandIndex),
1579 LoadRegisterAtOperandIndex(kFirstArgumentOperandIndex + 1));
1583 function, context, Int32Constant(arg_count), receiver_mode,
1584 LoadRegisterAtOperandIndex(kFirstArgumentOperandIndex),
1585 LoadRegisterAtOperandIndex(kFirstArgumentOperandIndex + 1),
1586 LoadRegisterAtOperandIndex(kFirstArgumentOperandIndex + 2));
1599 IGNITION_HANDLER(CallAnyReceiver, InterpreterJSCallAssembler) {
1600 JSCall(ConvertReceiverMode::kAny);
1603 IGNITION_HANDLER(CallProperty, InterpreterJSCallAssembler) {
1604 JSCall(ConvertReceiverMode::kNotNullOrUndefined);
1607 IGNITION_HANDLER(CallProperty0, InterpreterJSCallAssembler) {
1608 JSCallN(0, ConvertReceiverMode::kNotNullOrUndefined);
1611 IGNITION_HANDLER(CallProperty1, InterpreterJSCallAssembler) {
1612 JSCallN(1, ConvertReceiverMode::kNotNullOrUndefined);
1615 IGNITION_HANDLER(CallProperty2, InterpreterJSCallAssembler) {
1616 JSCallN(2, ConvertReceiverMode::kNotNullOrUndefined);
1619 IGNITION_HANDLER(CallUndefinedReceiver, InterpreterJSCallAssembler) {
1620 JSCall(ConvertReceiverMode::kNullOrUndefined);
1623 IGNITION_HANDLER(CallUndefinedReceiver0, InterpreterJSCallAssembler) {
1624 JSCallN(0, ConvertReceiverMode::kNullOrUndefined);
1627 IGNITION_HANDLER(CallUndefinedReceiver1, InterpreterJSCallAssembler) {
1628 JSCallN(1, ConvertReceiverMode::kNullOrUndefined);
1631 IGNITION_HANDLER(CallUndefinedReceiver2, InterpreterJSCallAssembler) {
1632 JSCallN(2, ConvertReceiverMode::kNullOrUndefined);
1635 IGNITION_HANDLER(CallNoFeedback, InterpreterJSCallAssembler) {
1636 JSCallNoFeedback(ConvertReceiverMode::kAny);
1644 IGNITION_HANDLER(CallRuntime, InterpreterAssembler) {
1645 Node* function_id = BytecodeOperandRuntimeId(0);
1646 RegListNodePair args = GetRegisterListAtOperandIndex(1);
1647 Node* context = GetContext();
1648 Node* result = CallRuntimeN(function_id, context, args);
1649 SetAccumulator(result);
1658 IGNITION_HANDLER(InvokeIntrinsic, InterpreterAssembler) {
1659 Node* function_id = BytecodeOperandIntrinsicId(0);
1660 RegListNodePair args = GetRegisterListAtOperandIndex(1);
1661 Node* context = GetContext();
1662 Node* result = GenerateInvokeIntrinsic(
this, function_id, context, args);
1663 SetAccumulator(result);
1673 IGNITION_HANDLER(CallRuntimeForPair, InterpreterAssembler) {
1675 Node* function_id = BytecodeOperandRuntimeId(0);
1676 RegListNodePair args = GetRegisterListAtOperandIndex(1);
1677 Node* context = GetContext();
1678 Node* result_pair = CallRuntimeN(function_id, context, args, 2);
1680 Node* result0 = Projection(0, result_pair);
1681 Node* result1 = Projection(1, result_pair);
1682 StoreRegisterPairAtOperandIndex(result0, result1, 3);
1690 IGNITION_HANDLER(CallJSRuntime, InterpreterAssembler) {
1691 Node* context_index = BytecodeOperandNativeContextIndex(0);
1692 RegListNodePair args = GetRegisterListAtOperandIndex(1);
1695 Node* context = GetContext();
1696 Node* native_context = LoadNativeContext(context);
1697 Node*
function = LoadContextElement(native_context, context_index);
1700 CallJSAndDispatch(
function, context, args,
1701 ConvertReceiverMode::kNullOrUndefined);
1710 IGNITION_HANDLER(CallWithSpread, InterpreterAssembler) {
1711 Node* callable = LoadRegisterAtOperandIndex(0);
1712 RegListNodePair args = GetRegisterListAtOperandIndex(1);
1713 Node* slot_id = BytecodeOperandIdx(3);
1714 Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
1715 Node* context = GetContext();
1718 CallJSWithSpreadAndDispatch(callable, context, args, slot_id,
1719 maybe_feedback_vector);
1728 IGNITION_HANDLER(ConstructWithSpread, InterpreterAssembler) {
1729 Node* new_target = GetAccumulator();
1730 Node* constructor = LoadRegisterAtOperandIndex(0);
1731 RegListNodePair args = GetRegisterListAtOperandIndex(1);
1732 Node* slot_id = BytecodeOperandIdx(3);
1733 Node* feedback_vector = LoadFeedbackVector();
1734 Node* context = GetContext();
1735 Node* result = ConstructWithSpread(constructor, context, new_target, args,
1736 slot_id, feedback_vector);
1737 SetAccumulator(result);
1747 IGNITION_HANDLER(Construct, InterpreterAssembler) {
1748 Node* new_target = GetAccumulator();
1749 Node* constructor = LoadRegisterAtOperandIndex(0);
1750 RegListNodePair args = GetRegisterListAtOperandIndex(1);
1751 Node* slot_id = BytecodeOperandIdx(3);
1752 Node* feedback_vector = LoadFeedbackVector();
1753 Node* context = GetContext();
1754 Node* result = Construct(constructor, context, new_target, args, slot_id,
1756 SetAccumulator(result);
1760 class InterpreterCompareOpAssembler :
public InterpreterAssembler {
1762 InterpreterCompareOpAssembler(CodeAssemblerState* state, Bytecode bytecode,
1763 OperandScale operand_scale)
1764 : InterpreterAssembler(state, bytecode, operand_scale) {}
1766 void CompareOpWithFeedback(Operation compare_op) {
1767 Node* lhs = LoadRegisterAtOperandIndex(0);
1768 Node* rhs = GetAccumulator();
1769 Node* context = GetContext();
1771 Variable var_type_feedback(
this, MachineRepresentation::kTagged);
1773 switch (compare_op) {
1774 case Operation::kEqual:
1775 result = Equal(lhs, rhs, context, &var_type_feedback);
1777 case Operation::kStrictEqual:
1778 result = StrictEqual(lhs, rhs, &var_type_feedback);
1780 case Operation::kLessThan:
1781 case Operation::kGreaterThan:
1782 case Operation::kLessThanOrEqual:
1783 case Operation::kGreaterThanOrEqual:
1784 result = RelationalComparison(compare_op, lhs, rhs, context,
1785 &var_type_feedback);
1791 Node* slot_index = BytecodeOperandIdx(1);
1792 Node* maybe_feedback_vector = LoadFeedbackVectorUnchecked();
1793 UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector,
1795 SetAccumulator(result);
1803 IGNITION_HANDLER(TestEqual, InterpreterCompareOpAssembler) {
1804 CompareOpWithFeedback(Operation::kEqual);
1810 IGNITION_HANDLER(TestEqualStrict, InterpreterCompareOpAssembler) {
1811 CompareOpWithFeedback(Operation::kStrictEqual);
1817 IGNITION_HANDLER(TestLessThan, InterpreterCompareOpAssembler) {
1818 CompareOpWithFeedback(Operation::kLessThan);
1824 IGNITION_HANDLER(TestGreaterThan, InterpreterCompareOpAssembler) {
1825 CompareOpWithFeedback(Operation::kGreaterThan);
1832 IGNITION_HANDLER(TestLessThanOrEqual, InterpreterCompareOpAssembler) {
1833 CompareOpWithFeedback(Operation::kLessThanOrEqual);
1840 IGNITION_HANDLER(TestGreaterThanOrEqual, InterpreterCompareOpAssembler) {
1841 CompareOpWithFeedback(Operation::kGreaterThanOrEqual);
1848 IGNITION_HANDLER(TestReferenceEqual, InterpreterAssembler) {
1849 Node* lhs = LoadRegisterAtOperandIndex(0);
1850 Node* rhs = GetAccumulator();
1851 Node* result = SelectBooleanConstant(WordEqual(lhs, rhs));
1852 SetAccumulator(result);
1860 IGNITION_HANDLER(TestIn, InterpreterAssembler) {
1861 Node*
property = LoadRegisterAtOperandIndex(0);
1862 Node*
object = GetAccumulator();
1863 Node* context = GetContext();
1865 SetAccumulator(HasProperty(context,
object, property, kHasProperty));
1873 IGNITION_HANDLER(TestInstanceOf, InterpreterAssembler) {
1874 Node*
object = LoadRegisterAtOperandIndex(0);
1875 Node* callable = GetAccumulator();
1876 Node* slot_id = BytecodeOperandIdx(1);
1877 Node* feedback_vector = LoadFeedbackVectorUnchecked();
1878 Node* context = GetContext();
1880 Label feedback_done(
this);
1881 GotoIf(IsUndefined(feedback_vector), &feedback_done);
1884 CollectCallableFeedback(callable, context, feedback_vector, slot_id);
1885 Goto(&feedback_done);
1887 BIND(&feedback_done);
1889 SetAccumulator(InstanceOf(
object, callable, context));
1897 IGNITION_HANDLER(TestUndetectable, InterpreterAssembler) {
1898 Label return_false(
this), end(
this);
1899 Node*
object = GetAccumulator();
1902 SetAccumulator(FalseConstant());
1903 GotoIf(TaggedIsSmi(
object), &end);
1906 Node* result = SelectBooleanConstant(IsUndetectableMap(LoadMap(
object)));
1907 SetAccumulator(result);
1917 IGNITION_HANDLER(TestNull, InterpreterAssembler) {
1918 Node*
object = GetAccumulator();
1919 Node* result = SelectBooleanConstant(WordEqual(
object, NullConstant()));
1920 SetAccumulator(result);
1927 IGNITION_HANDLER(TestUndefined, InterpreterAssembler) {
1928 Node*
object = GetAccumulator();
1929 Node* result = SelectBooleanConstant(WordEqual(
object, UndefinedConstant()));
1930 SetAccumulator(result);
1938 IGNITION_HANDLER(TestTypeOf, InterpreterAssembler) {
1939 Node*
object = GetAccumulator();
1940 Node* literal_flag = BytecodeOperandFlag(0);
1942 #define MAKE_LABEL(name, lower_case) Label if_##lower_case(this); 1943 TYPEOF_LITERAL_LIST(MAKE_LABEL)
1946 #define LABEL_POINTER(name, lower_case) &if_##lower_case, 1947 Label* labels[] = {TYPEOF_LITERAL_LIST(LABEL_POINTER)};
1948 #undef LABEL_POINTER 1950 #define CASE(name, lower_case) \ 1951 static_cast<int32_t>(TestTypeOfFlags::LiteralFlag::k##name), 1952 int32_t cases[] = {TYPEOF_LITERAL_LIST(CASE)};
1955 Label if_true(
this), if_false(
this), end(
this);
1960 unsigned const num_cases = arraysize(cases);
1961 CSA_ASSERT(
this, Uint32LessThan(literal_flag, Int32Constant(num_cases)));
1962 Switch(literal_flag, labels[num_cases - 1], cases, labels, num_cases - 1);
1966 Comment(
"IfNumber");
1967 GotoIfNumber(
object, &if_true);
1972 Comment(
"IfString");
1973 GotoIf(TaggedIsSmi(
object), &if_false);
1974 Branch(IsString(
object), &if_true, &if_false);
1978 Comment(
"IfSymbol");
1979 GotoIf(TaggedIsSmi(
object), &if_false);
1980 Branch(IsSymbol(
object), &if_true, &if_false);
1984 Comment(
"IfBoolean");
1985 GotoIf(WordEqual(
object, TrueConstant()), &if_true);
1986 Branch(WordEqual(
object, FalseConstant()), &if_true, &if_false);
1990 Comment(
"IfBigInt");
1991 GotoIf(TaggedIsSmi(
object), &if_false);
1992 Branch(IsBigInt(
object), &if_true, &if_false);
1994 BIND(&if_undefined);
1996 Comment(
"IfUndefined");
1997 GotoIf(TaggedIsSmi(
object), &if_false);
1999 GotoIf(IsNull(
object), &if_false);
2000 Branch(IsUndetectableMap(LoadMap(
object)), &if_true, &if_false);
2004 Comment(
"IfFunction");
2005 GotoIf(TaggedIsSmi(
object), &if_false);
2007 Node* map_bitfield = LoadMapBitField(LoadMap(
object));
2008 Node* callable_undetectable =
2009 Word32And(map_bitfield, Int32Constant(Map::IsUndetectableBit::kMask |
2010 Map::IsCallableBit::kMask));
2011 Branch(Word32Equal(callable_undetectable,
2012 Int32Constant(Map::IsCallableBit::kMask)),
2013 &if_true, &if_false);
2017 Comment(
"IfObject");
2018 GotoIf(TaggedIsSmi(
object), &if_false);
2021 GotoIf(IsNull(
object), &if_true);
2024 Node* map = LoadMap(
object);
2025 GotoIfNot(IsJSReceiverMap(map), &if_false);
2026 Node* map_bitfield = LoadMapBitField(map);
2027 Node* callable_undetectable =
2028 Word32And(map_bitfield, Int32Constant(Map::IsUndetectableBit::kMask |
2029 Map::IsCallableBit::kMask));
2030 Branch(Word32Equal(callable_undetectable, Int32Constant(0)), &if_true,
2041 SetAccumulator(FalseConstant());
2046 SetAccumulator(TrueConstant());
2056 IGNITION_HANDLER(Jump, InterpreterAssembler) {
2057 Node* relative_jump = BytecodeOperandUImmWord(0);
2058 Jump(relative_jump);
2065 IGNITION_HANDLER(JumpConstant, InterpreterAssembler) {
2066 Node* relative_jump = LoadAndUntagConstantPoolEntryAtOperandIndex(0);
2067 Jump(relative_jump);
2075 IGNITION_HANDLER(JumpIfTrue, InterpreterAssembler) {
2076 Node* accumulator = GetAccumulator();
2077 Node* relative_jump = BytecodeOperandUImmWord(0);
2078 CSA_ASSERT(
this, TaggedIsNotSmi(accumulator));
2079 CSA_ASSERT(
this, IsBoolean(accumulator));
2080 JumpIfWordEqual(accumulator, TrueConstant(), relative_jump);
2088 IGNITION_HANDLER(JumpIfTrueConstant, InterpreterAssembler) {
2089 Node* accumulator = GetAccumulator();
2090 Node* relative_jump = LoadAndUntagConstantPoolEntryAtOperandIndex(0);
2091 CSA_ASSERT(
this, TaggedIsNotSmi(accumulator));
2092 CSA_ASSERT(
this, IsBoolean(accumulator));
2093 JumpIfWordEqual(accumulator, TrueConstant(), relative_jump);
2101 IGNITION_HANDLER(JumpIfFalse, InterpreterAssembler) {
2102 Node* accumulator = GetAccumulator();
2103 Node* relative_jump = BytecodeOperandUImmWord(0);
2104 CSA_ASSERT(
this, TaggedIsNotSmi(accumulator));
2105 CSA_ASSERT(
this, IsBoolean(accumulator));
2106 JumpIfWordEqual(accumulator, FalseConstant(), relative_jump);
2114 IGNITION_HANDLER(JumpIfFalseConstant, InterpreterAssembler) {
2115 Node* accumulator = GetAccumulator();
2116 Node* relative_jump = LoadAndUntagConstantPoolEntryAtOperandIndex(0);
2117 CSA_ASSERT(
this, TaggedIsNotSmi(accumulator));
2118 CSA_ASSERT(
this, IsBoolean(accumulator));
2119 JumpIfWordEqual(accumulator, FalseConstant(), relative_jump);
2126 IGNITION_HANDLER(JumpIfToBooleanTrue, InterpreterAssembler) {
2127 Node* value = GetAccumulator();
2128 Node* relative_jump = BytecodeOperandUImmWord(0);
2129 Label if_true(
this), if_false(
this);
2130 BranchIfToBooleanIsTrue(value, &if_true, &if_false);
2132 Jump(relative_jump);
2142 IGNITION_HANDLER(JumpIfToBooleanTrueConstant, InterpreterAssembler) {
2143 Node* value = GetAccumulator();
2144 Node* relative_jump = LoadAndUntagConstantPoolEntryAtOperandIndex(0);
2145 Label if_true(
this), if_false(
this);
2146 BranchIfToBooleanIsTrue(value, &if_true, &if_false);
2148 Jump(relative_jump);
2157 IGNITION_HANDLER(JumpIfToBooleanFalse, InterpreterAssembler) {
2158 Node* value = GetAccumulator();
2159 Node* relative_jump = BytecodeOperandUImmWord(0);
2160 Label if_true(
this), if_false(
this);
2161 BranchIfToBooleanIsTrue(value, &if_true, &if_false);
2165 Jump(relative_jump);
2173 IGNITION_HANDLER(JumpIfToBooleanFalseConstant, InterpreterAssembler) {
2174 Node* value = GetAccumulator();
2175 Node* relative_jump = LoadAndUntagConstantPoolEntryAtOperandIndex(0);
2176 Label if_true(
this), if_false(
this);
2177 BranchIfToBooleanIsTrue(value, &if_true, &if_false);
2181 Jump(relative_jump);
2188 IGNITION_HANDLER(JumpIfNull, InterpreterAssembler) {
2189 Node* accumulator = GetAccumulator();
2190 Node* relative_jump = BytecodeOperandUImmWord(0);
2191 JumpIfWordEqual(accumulator, NullConstant(), relative_jump);
2198 IGNITION_HANDLER(JumpIfNullConstant, InterpreterAssembler) {
2199 Node* accumulator = GetAccumulator();
2200 Node* relative_jump = LoadAndUntagConstantPoolEntryAtOperandIndex(0);
2201 JumpIfWordEqual(accumulator, NullConstant(), relative_jump);
2208 IGNITION_HANDLER(JumpIfNotNull, InterpreterAssembler) {
2209 Node* accumulator = GetAccumulator();
2210 Node* relative_jump = BytecodeOperandUImmWord(0);
2211 JumpIfWordNotEqual(accumulator, NullConstant(), relative_jump);
2218 IGNITION_HANDLER(JumpIfNotNullConstant, InterpreterAssembler) {
2219 Node* accumulator = GetAccumulator();
2220 Node* relative_jump = LoadAndUntagConstantPoolEntryAtOperandIndex(0);
2221 JumpIfWordNotEqual(accumulator, NullConstant(), relative_jump);
2228 IGNITION_HANDLER(JumpIfUndefined, InterpreterAssembler) {
2229 Node* accumulator = GetAccumulator();
2230 Node* relative_jump = BytecodeOperandUImmWord(0);
2231 JumpIfWordEqual(accumulator, UndefinedConstant(), relative_jump);
2238 IGNITION_HANDLER(JumpIfUndefinedConstant, InterpreterAssembler) {
2239 Node* accumulator = GetAccumulator();
2240 Node* relative_jump = LoadAndUntagConstantPoolEntryAtOperandIndex(0);
2241 JumpIfWordEqual(accumulator, UndefinedConstant(), relative_jump);
2248 IGNITION_HANDLER(JumpIfNotUndefined, InterpreterAssembler) {
2249 Node* accumulator = GetAccumulator();
2250 Node* relative_jump = BytecodeOperandUImmWord(0);
2251 JumpIfWordNotEqual(accumulator, UndefinedConstant(), relative_jump);
2259 IGNITION_HANDLER(JumpIfNotUndefinedConstant, InterpreterAssembler) {
2260 Node* accumulator = GetAccumulator();
2261 Node* relative_jump = LoadAndUntagConstantPoolEntryAtOperandIndex(0);
2262 JumpIfWordNotEqual(accumulator, UndefinedConstant(), relative_jump);
2269 IGNITION_HANDLER(JumpIfJSReceiver, InterpreterAssembler) {
2270 Node* accumulator = GetAccumulator();
2271 Node* relative_jump = BytecodeOperandUImmWord(0);
2273 Label if_object(
this), if_notobject(
this, Label::kDeferred), if_notsmi(
this);
2274 Branch(TaggedIsSmi(accumulator), &if_notobject, &if_notsmi);
2277 Branch(IsJSReceiver(accumulator), &if_object, &if_notobject);
2279 Jump(relative_jump);
2281 BIND(&if_notobject);
2289 IGNITION_HANDLER(JumpIfJSReceiverConstant, InterpreterAssembler) {
2290 Node* accumulator = GetAccumulator();
2291 Node* relative_jump = LoadAndUntagConstantPoolEntryAtOperandIndex(0);
2293 Label if_object(
this), if_notobject(
this), if_notsmi(
this);
2294 Branch(TaggedIsSmi(accumulator), &if_notobject, &if_notsmi);
2297 Branch(IsJSReceiver(accumulator), &if_object, &if_notobject);
2300 Jump(relative_jump);
2302 BIND(&if_notobject);
2311 IGNITION_HANDLER(JumpLoop, InterpreterAssembler) {
2312 Node* relative_jump = BytecodeOperandUImmWord(0);
2313 Node* loop_depth = BytecodeOperandImm(1);
2314 Node* osr_level = LoadOSRNestingLevel();
2318 Label ok(
this), osr_armed(
this, Label::kDeferred);
2319 Node* condition = Int32GreaterThanOrEqual(loop_depth, osr_level);
2320 Branch(condition, &ok, &osr_armed);
2323 JumpBackward(relative_jump);
2327 Callable callable = CodeFactory::InterpreterOnStackReplacement(isolate());
2328 Node* target = HeapConstant(callable.code());
2329 Node* context = GetContext();
2330 CallStub(callable.descriptor(), target, context);
2331 JumpBackward(relative_jump);
2342 IGNITION_HANDLER(SwitchOnSmiNoFeedback, InterpreterAssembler) {
2343 Node* acc = GetAccumulator();
2344 Node* table_start = BytecodeOperandIdx(0);
2345 Node* table_length = BytecodeOperandUImmWord(1);
2346 Node* case_value_base = BytecodeOperandImmIntPtr(2);
2348 Label fall_through(
this);
2353 CSA_ASSERT(
this, TaggedIsSmi(acc));
2355 Node* case_value = IntPtrSub(SmiUntag(acc), case_value_base);
2356 GotoIf(IntPtrLessThan(case_value, IntPtrConstant(0)), &fall_through);
2357 GotoIf(IntPtrGreaterThanOrEqual(case_value, table_length), &fall_through);
2358 Node* entry = IntPtrAdd(table_start, case_value);
2359 Node* relative_jump = LoadAndUntagConstantPoolEntry(entry);
2360 Jump(relative_jump);
2362 BIND(&fall_through);
2370 IGNITION_HANDLER(CreateRegExpLiteral, InterpreterAssembler) {
2371 Node* pattern = LoadConstantPoolEntryAtOperandIndex(0);
2372 Node* feedback_vector = LoadFeedbackVector();
2373 Node* slot_id = BytecodeOperandIdx(1);
2374 Node* flags = SmiFromInt32(BytecodeOperandFlag(2));
2375 Node* context = GetContext();
2376 ConstructorBuiltinsAssembler constructor_assembler(state());
2377 Node* result = constructor_assembler.EmitCreateRegExpLiteral(
2378 feedback_vector, slot_id, pattern, flags, context);
2379 SetAccumulator(result);
2387 IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) {
2388 Node* feedback_vector = LoadFeedbackVector();
2389 Node* slot_id = BytecodeOperandIdx(1);
2390 Node* context = GetContext();
2391 Node* bytecode_flags = BytecodeOperandFlag(2);
2393 Label fast_shallow_clone(
this), call_runtime(
this, Label::kDeferred);
2394 Branch(IsSetWord32<CreateArrayLiteralFlags::FastCloneSupportedBit>(
2396 &fast_shallow_clone, &call_runtime);
2398 BIND(&fast_shallow_clone);
2400 ConstructorBuiltinsAssembler constructor_assembler(state());
2401 Node* result = constructor_assembler.EmitCreateShallowArrayLiteral(
2402 feedback_vector, slot_id, context, &call_runtime,
2403 TRACK_ALLOCATION_SITE);
2404 SetAccumulator(result);
2408 BIND(&call_runtime);
2410 Node* flags_raw = DecodeWordFromWord32<CreateArrayLiteralFlags::FlagsBits>(
2412 Node* flags = SmiTag(flags_raw);
2413 Node* constant_elements = LoadConstantPoolEntryAtOperandIndex(0);
2415 CallRuntime(Runtime::kCreateArrayLiteral, context, feedback_vector,
2416 SmiTag(slot_id), constant_elements, flags);
2417 SetAccumulator(result);
2425 IGNITION_HANDLER(CreateEmptyArrayLiteral, InterpreterAssembler) {
2426 Node* feedback_vector = LoadFeedbackVector();
2427 Node* slot_id = BytecodeOperandIdx(0);
2428 Node* context = GetContext();
2429 ConstructorBuiltinsAssembler constructor_assembler(state());
2430 Node* result = constructor_assembler.EmitCreateEmptyArrayLiteral(
2431 feedback_vector, slot_id, context);
2432 SetAccumulator(result);
2439 IGNITION_HANDLER(CreateArrayFromIterable, InterpreterAssembler) {
2440 Node* iterable = GetAccumulator();
2441 Node* context = GetContext();
2443 CallBuiltin(Builtins::kIterableToListWithSymbolLookup, context, iterable);
2444 SetAccumulator(result);
2452 IGNITION_HANDLER(CreateObjectLiteral, InterpreterAssembler) {
2453 Node* feedback_vector = LoadFeedbackVector();
2454 Node* slot_id = BytecodeOperandIdx(1);
2455 Node* bytecode_flags = BytecodeOperandFlag(2);
2458 Label if_fast_clone(
this), if_not_fast_clone(
this, Label::kDeferred);
2459 Branch(IsSetWord32<CreateObjectLiteralFlags::FastCloneSupportedBit>(
2461 &if_fast_clone, &if_not_fast_clone);
2463 BIND(&if_fast_clone);
2466 ConstructorBuiltinsAssembler constructor_assembler(state());
2467 Node* result = constructor_assembler.EmitCreateShallowObjectLiteral(
2468 feedback_vector, slot_id, &if_not_fast_clone);
2469 SetAccumulator(result);
2473 BIND(&if_not_fast_clone);
2476 Node* object_boilerplate_description =
2477 LoadConstantPoolEntryAtOperandIndex(0);
2478 Node* context = GetContext();
2480 Node* flags_raw = DecodeWordFromWord32<CreateObjectLiteralFlags::FlagsBits>(
2482 Node* flags = SmiTag(flags_raw);
2485 CallRuntime(Runtime::kCreateObjectLiteral, context, feedback_vector,
2486 SmiTag(slot_id), object_boilerplate_description, flags);
2487 SetAccumulator(result);
2496 IGNITION_HANDLER(CreateEmptyObjectLiteral, InterpreterAssembler) {
2497 Node* context = GetContext();
2498 ConstructorBuiltinsAssembler constructor_assembler(state());
2499 Node* result = constructor_assembler.EmitCreateEmptyObjectLiteral(context);
2500 SetAccumulator(result);
2508 IGNITION_HANDLER(CloneObject, InterpreterAssembler) {
2509 Node* source = LoadRegisterAtOperandIndex(0);
2510 Node* bytecode_flags = BytecodeOperandFlag(1);
2512 DecodeWordFromWord32<CreateObjectLiteralFlags::FlagsBits>(bytecode_flags);
2513 Node* smi_flags = SmiTag(raw_flags);
2514 Node* raw_slot = BytecodeOperandIdx(2);
2515 Node* smi_slot = SmiTag(raw_slot);
2516 Node* feedback_vector = LoadFeedbackVector();
2517 Node* context = GetContext();
2518 Node* result = CallBuiltin(Builtins::kCloneObjectIC, context, source,
2519 smi_flags, smi_slot, feedback_vector);
2520 SetAccumulator(result);
2529 IGNITION_HANDLER(GetTemplateObject, InterpreterAssembler) {
2530 Node* feedback_vector = LoadFeedbackVector();
2531 Node* slot = BytecodeOperandIdx(1);
2532 TNode<Object> cached_value =
2533 CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
2535 Label call_runtime(
this, Label::kDeferred);
2536 GotoIf(WordEqual(cached_value, SmiConstant(0)), &call_runtime);
2538 SetAccumulator(cached_value);
2541 BIND(&call_runtime);
2543 Node* description = LoadConstantPoolEntryAtOperandIndex(0);
2544 Node* context = GetContext();
2546 CallRuntime(Runtime::kCreateTemplateObject, context, description);
2547 StoreFeedbackVectorSlot(feedback_vector, slot, result);
2548 SetAccumulator(result);
2557 IGNITION_HANDLER(CreateClosure, InterpreterAssembler) {
2558 Node* shared = LoadConstantPoolEntryAtOperandIndex(0);
2559 Node* flags = BytecodeOperandFlag(2);
2560 Node* context = GetContext();
2561 Node* slot = BytecodeOperandIdx(1);
2563 Label if_undefined(
this), load_feedback_done(
this);
2564 Variable feedback_cell(
this, MachineRepresentation::kTagged);
2565 Node* feedback_vector = LoadFeedbackVectorUnchecked();
2567 GotoIf(IsUndefined(feedback_vector), &if_undefined);
2568 feedback_cell.Bind(LoadFeedbackVectorSlot(feedback_vector, slot));
2569 Goto(&load_feedback_done);
2571 BIND(&if_undefined);
2573 feedback_cell.Bind(LoadRoot(RootIndex::kNoFeedbackCell));
2574 Goto(&load_feedback_done);
2577 BIND(&load_feedback_done);
2578 Label if_fast(
this), if_slow(
this, Label::kDeferred);
2579 Branch(IsSetWord32<CreateClosureFlags::FastNewClosureBit>(flags), &if_fast,
2584 Node* result = CallBuiltin(Builtins::kFastNewClosure, context, shared,
2585 feedback_cell.value());
2586 SetAccumulator(result);
2592 Label if_newspace(
this), if_oldspace(
this);
2593 Branch(IsSetWord32<CreateClosureFlags::PretenuredBit>(flags), &if_oldspace,
2598 Node* result = CallRuntime(Runtime::kNewClosure, context, shared,
2599 feedback_cell.value());
2600 SetAccumulator(result);
2606 Node* result = CallRuntime(Runtime::kNewClosure_Tenured, context, shared,
2607 feedback_cell.value());
2608 SetAccumulator(result);
2617 IGNITION_HANDLER(CreateBlockContext, InterpreterAssembler) {
2618 Node* scope_info = LoadConstantPoolEntryAtOperandIndex(0);
2619 Node* context = GetContext();
2620 SetAccumulator(CallRuntime(Runtime::kPushBlockContext, context, scope_info));
2628 IGNITION_HANDLER(CreateCatchContext, InterpreterAssembler) {
2629 Node* exception = LoadRegisterAtOperandIndex(0);
2630 Node* scope_info = LoadConstantPoolEntryAtOperandIndex(1);
2631 Node* context = GetContext();
2633 CallRuntime(Runtime::kPushCatchContext, context, exception, scope_info));
2640 IGNITION_HANDLER(CreateFunctionContext, InterpreterAssembler) {
2641 Node* scope_info_idx = BytecodeOperandIdx(0);
2642 Node* scope_info = LoadConstantPoolEntry(scope_info_idx);
2643 Node* slots = BytecodeOperandUImm(1);
2644 Node* context = GetContext();
2645 ConstructorBuiltinsAssembler constructor_assembler(state());
2646 SetAccumulator(constructor_assembler.EmitFastNewFunctionContext(
2647 scope_info, slots, context, FUNCTION_SCOPE));
2654 IGNITION_HANDLER(CreateEvalContext, InterpreterAssembler) {
2655 Node* scope_info_idx = BytecodeOperandIdx(0);
2656 Node* scope_info = LoadConstantPoolEntry(scope_info_idx);
2657 Node* slots = BytecodeOperandUImm(1);
2658 Node* context = GetContext();
2659 ConstructorBuiltinsAssembler constructor_assembler(state());
2660 SetAccumulator(constructor_assembler.EmitFastNewFunctionContext(
2661 scope_info, slots, context, EVAL_SCOPE));
2669 IGNITION_HANDLER(CreateWithContext, InterpreterAssembler) {
2670 Node*
object = LoadRegisterAtOperandIndex(0);
2671 Node* scope_info = LoadConstantPoolEntryAtOperandIndex(1);
2672 Node* context = GetContext();
2674 CallRuntime(Runtime::kPushWithContext, context,
object, scope_info));
2681 IGNITION_HANDLER(CreateMappedArguments, InterpreterAssembler) {
2682 Node* closure = LoadRegister(Register::function_closure());
2683 Node* context = GetContext();
2685 Label if_duplicate_parameters(
this, Label::kDeferred);
2686 Label if_not_duplicate_parameters(
this);
2692 LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
2693 Node* flags = LoadObjectField(shared_info, SharedFunctionInfo::kFlagsOffset,
2694 MachineType::Uint32());
2695 Node* has_duplicate_parameters =
2696 IsSetWord32<SharedFunctionInfo::HasDuplicateParametersBit>(flags);
2697 Branch(has_duplicate_parameters, &if_duplicate_parameters,
2698 &if_not_duplicate_parameters);
2700 BIND(&if_not_duplicate_parameters);
2702 ArgumentsBuiltinsAssembler constructor_assembler(state());
2704 constructor_assembler.EmitFastNewSloppyArguments(context, closure);
2705 SetAccumulator(result);
2709 BIND(&if_duplicate_parameters);
2712 CallRuntime(Runtime::kNewSloppyArguments_Generic, context, closure);
2713 SetAccumulator(result);
2721 IGNITION_HANDLER(CreateUnmappedArguments, InterpreterAssembler) {
2722 Node* context = GetContext();
2723 Node* closure = LoadRegister(Register::function_closure());
2724 ArgumentsBuiltinsAssembler builtins_assembler(state());
2726 builtins_assembler.EmitFastNewStrictArguments(context, closure);
2727 SetAccumulator(result);
2734 IGNITION_HANDLER(CreateRestParameter, InterpreterAssembler) {
2735 Node* closure = LoadRegister(Register::function_closure());
2736 Node* context = GetContext();
2737 ArgumentsBuiltinsAssembler builtins_assembler(state());
2738 Node* result = builtins_assembler.EmitFastNewRestParameter(context, closure);
2739 SetAccumulator(result);
2746 IGNITION_HANDLER(StackCheck, InterpreterAssembler) {
2747 TNode<Context> context = CAST(GetContext());
2748 PerformStackCheck(context);
2756 IGNITION_HANDLER(SetPendingMessage, InterpreterAssembler) {
2757 Node* pending_message = ExternalConstant(
2758 ExternalReference::address_of_pending_message_obj(isolate()));
2759 Node* previous_message = Load(MachineType::TaggedPointer(), pending_message);
2760 Node* new_message = GetAccumulator();
2761 StoreNoWriteBarrier(MachineRepresentation::kTaggedPointer, pending_message,
2763 SetAccumulator(previous_message);
2770 IGNITION_HANDLER(Throw, InterpreterAssembler) {
2771 Node* exception = GetAccumulator();
2772 Node* context = GetContext();
2773 CallRuntime(Runtime::kThrow, context, exception);
2775 Abort(AbortReason::kUnexpectedReturnFromThrow);
2782 IGNITION_HANDLER(ReThrow, InterpreterAssembler) {
2783 Node* exception = GetAccumulator();
2784 Node* context = GetContext();
2785 CallRuntime(Runtime::kReThrow, context, exception);
2787 Abort(AbortReason::kUnexpectedReturnFromThrow);
2794 IGNITION_HANDLER(Abort, InterpreterAssembler) {
2795 Node* reason = BytecodeOperandIdx(0);
2796 CallRuntime(Runtime::kAbort, NoContextConstant(), SmiTag(reason));
2803 IGNITION_HANDLER(Return, InterpreterAssembler) {
2804 UpdateInterruptBudgetOnReturn();
2805 Node* accumulator = GetAccumulator();
2806 Return(accumulator);
2812 IGNITION_HANDLER(ThrowReferenceErrorIfHole, InterpreterAssembler) {
2813 Node* value = GetAccumulator();
2815 Label throw_error(
this, Label::kDeferred);
2816 GotoIf(WordEqual(value, TheHoleConstant()), &throw_error);
2821 Node* name = LoadConstantPoolEntryAtOperandIndex(0);
2822 CallRuntime(Runtime::kThrowReferenceError, GetContext(), name);
2824 Abort(AbortReason::kUnexpectedReturnFromThrow);
2832 IGNITION_HANDLER(ThrowSuperNotCalledIfHole, InterpreterAssembler) {
2833 Node* value = GetAccumulator();
2835 Label throw_error(
this, Label::kDeferred);
2836 GotoIf(WordEqual(value, TheHoleConstant()), &throw_error);
2841 CallRuntime(Runtime::kThrowSuperNotCalled, GetContext());
2843 Abort(AbortReason::kUnexpectedReturnFromThrow);
2852 IGNITION_HANDLER(ThrowSuperAlreadyCalledIfNotHole, InterpreterAssembler) {
2853 Node* value = GetAccumulator();
2855 Label throw_error(
this, Label::kDeferred);
2856 GotoIf(WordNotEqual(value, TheHoleConstant()), &throw_error);
2861 CallRuntime(Runtime::kThrowSuperAlreadyCalledError, GetContext());
2863 Abort(AbortReason::kUnexpectedReturnFromThrow);
2871 IGNITION_HANDLER(Debugger, InterpreterAssembler) {
2872 Node* context = GetContext();
2873 CallStub(CodeFactory::HandleDebuggerStatement(isolate()), context);
2880 #define DEBUG_BREAK(Name, ...) \ 2881 IGNITION_HANDLER(Name, InterpreterAssembler) { \ 2882 Node* context = GetContext(); \ 2883 Node* accumulator = GetAccumulator(); \ 2884 Node* result_pair = \ 2885 CallRuntime(Runtime::kDebugBreakOnBytecode, context, accumulator); \ 2886 Node* return_value = Projection(0, result_pair); \ 2887 Node* original_bytecode = SmiUntag(Projection(1, result_pair)); \ 2888 MaybeDropFrames(context); \ 2889 SetAccumulator(return_value); \ 2890 DispatchToBytecode(original_bytecode, BytecodeOffset()); \ 2892 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
2899 IGNITION_HANDLER(IncBlockCounter, InterpreterAssembler) {
2900 Node* closure = LoadRegister(Register::function_closure());
2901 Node* coverage_array_slot = BytecodeOperandIdxSmi(0);
2902 Node* context = GetContext();
2904 CallRuntime(Runtime::kIncBlockCounter, context, closure, coverage_array_slot);
2914 IGNITION_HANDLER(ForInEnumerate, InterpreterAssembler) {
2915 Node* receiver = LoadRegisterAtOperandIndex(0);
2916 Node* context = GetContext();
2918 Label if_empty(
this), if_runtime(
this, Label::kDeferred);
2919 Node* receiver_map = CheckEnumCache(receiver, &if_empty, &if_runtime);
2920 SetAccumulator(receiver_map);
2925 Node* result = EmptyFixedArrayConstant();
2926 SetAccumulator(result);
2932 Node* result = CallRuntime(Runtime::kForInEnumerate, context, receiver);
2933 SetAccumulator(result);
2946 IGNITION_HANDLER(ForInPrepare, InterpreterAssembler) {
2947 Node* enumerator = GetAccumulator();
2948 Node* vector_index = BytecodeOperandIdx(1);
2949 Node* feedback_vector = LoadFeedbackVector();
2952 CSA_ASSERT(
this, TaggedIsNotSmi(enumerator));
2955 Label if_fast(
this), if_slow(
this);
2956 Branch(IsMap(enumerator), &if_fast, &if_slow);
2961 Node* enum_length = LoadMapEnumLength(enumerator);
2962 CSA_ASSERT(
this, WordNotEqual(enum_length,
2963 IntPtrConstant(kInvalidEnumCacheSentinel)));
2964 Node* descriptors = LoadMapDescriptors(enumerator);
2966 LoadObjectField(descriptors, DescriptorArray::kEnumCacheOffset);
2967 Node* enum_keys = LoadObjectField(enum_cache, EnumCache::kKeysOffset);
2970 Node* enum_indices = LoadObjectField(enum_cache, EnumCache::kIndicesOffset);
2971 Node* enum_indices_length = LoadAndUntagFixedArrayBaseLength(enum_indices);
2972 Node* feedback = SelectSmiConstant(
2973 IntPtrLessThanOrEqual(enum_length, enum_indices_length),
2974 ForInFeedback::kEnumCacheKeysAndIndices, ForInFeedback::kEnumCacheKeys);
2975 UpdateFeedback(feedback, feedback_vector, vector_index);
2978 Node* cache_type = enumerator;
2979 Node* cache_array = enum_keys;
2980 Node* cache_length = SmiTag(enum_length);
2981 StoreRegisterTripleAtOperandIndex(cache_type, cache_array, cache_length, 0);
2988 CSA_ASSERT(
this, IsFixedArray(enumerator));
2991 UpdateFeedback(SmiConstant(ForInFeedback::kAny), feedback_vector,
2995 Node* cache_type = enumerator;
2996 Node* cache_array = enumerator;
2997 Node* cache_length = LoadFixedArrayBaseLength(enumerator);
2998 StoreRegisterTripleAtOperandIndex(cache_type, cache_array, cache_length, 0);
3006 IGNITION_HANDLER(ForInNext, InterpreterAssembler) {
3007 Node* receiver = LoadRegisterAtOperandIndex(0);
3008 Node* index = LoadRegisterAtOperandIndex(1);
3011 std::tie(cache_type, cache_array) = LoadRegisterPairAtOperandIndex(2);
3012 Node* vector_index = BytecodeOperandIdx(3);
3013 Node* feedback_vector = LoadFeedbackVector();
3016 Node* key = LoadFixedArrayElement(CAST(cache_array), index, 0,
3017 CodeStubAssembler::SMI_PARAMETERS);
3020 Label if_fast(
this), if_slow(
this, Label::kDeferred);
3021 Node* receiver_map = LoadMap(receiver);
3022 Branch(WordEqual(receiver_map, cache_type), &if_fast, &if_slow);
3026 SetAccumulator(key);
3032 UpdateFeedback(SmiConstant(ForInFeedback::kAny), feedback_vector,
3036 Node* context = GetContext();
3037 Node* result = CallBuiltin(Builtins::kForInFilter, context, key, receiver);
3038 SetAccumulator(result);
3046 IGNITION_HANDLER(ForInContinue, InterpreterAssembler) {
3047 Node* index = LoadRegisterAtOperandIndex(0);
3048 Node* cache_length = LoadRegisterAtOperandIndex(1);
3051 Label if_true(
this), if_false(
this), end(
this);
3052 Branch(WordEqual(index, cache_length), &if_true, &if_false);
3055 SetAccumulator(FalseConstant());
3060 SetAccumulator(TrueConstant());
3071 IGNITION_HANDLER(ForInStep, InterpreterAssembler) {
3072 TNode<Smi> index = CAST(LoadRegisterAtOperandIndex(0));
3073 TNode<Smi> one = SmiConstant(1);
3074 TNode<Smi> result = SmiAdd(index, one);
3075 SetAccumulator(result);
3082 IGNITION_HANDLER(Wide, InterpreterAssembler) {
3083 DispatchWide(OperandScale::kDouble);
3089 IGNITION_HANDLER(ExtraWide, InterpreterAssembler) {
3090 DispatchWide(OperandScale::kQuadruple);
3096 IGNITION_HANDLER(Illegal, InterpreterAssembler) {
3097 Abort(AbortReason::kInvalidBytecode);
3108 IGNITION_HANDLER(SuspendGenerator, InterpreterAssembler) {
3109 Node* generator = LoadRegisterAtOperandIndex(0);
3110 TNode<FixedArray> array = CAST(LoadObjectField(
3111 generator, JSGeneratorObject::kParametersAndRegistersOffset));
3112 Node* closure = LoadRegister(Register::function_closure());
3113 Node* context = GetContext();
3114 RegListNodePair registers = GetRegisterListAtOperandIndex(1);
3115 Node* suspend_id = BytecodeOperandUImmSmi(3);
3118 LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
3119 TNode<Int32T> formal_parameter_count = UncheckedCast<Int32T>(
3120 LoadObjectField(shared, SharedFunctionInfo::kFormalParameterCountOffset,
3121 MachineType::Uint16()));
3123 ExportParametersAndRegisterFile(array, registers, formal_parameter_count);
3124 StoreObjectField(generator, JSGeneratorObject::kContextOffset, context);
3125 StoreObjectField(generator, JSGeneratorObject::kContinuationOffset,
3130 Node* offset = SmiTag(BytecodeOffset());
3131 StoreObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset,
3134 UpdateInterruptBudgetOnReturn();
3135 Return(GetAccumulator());
3145 IGNITION_HANDLER(SwitchOnGeneratorState, InterpreterAssembler) {
3146 Node* generator = LoadRegisterAtOperandIndex(0);
3148 Label fallthrough(
this);
3149 GotoIf(WordEqual(generator, UndefinedConstant()), &fallthrough);
3152 LoadObjectField(generator, JSGeneratorObject::kContinuationOffset);
3153 Node* new_state = SmiConstant(JSGeneratorObject::kGeneratorExecuting);
3154 StoreObjectField(generator, JSGeneratorObject::kContinuationOffset,
3157 Node* context = LoadObjectField(generator, JSGeneratorObject::kContextOffset);
3158 SetContext(context);
3160 Node* table_start = BytecodeOperandIdx(1);
3163 Node* table_length = BytecodeOperandUImmWord(2);
3166 CSA_ASSERT(
this, TaggedIsSmi(state));
3168 Node* case_value = SmiUntag(state);
3170 CSA_ASSERT(
this, IntPtrGreaterThanOrEqual(case_value, IntPtrConstant(0)));
3171 CSA_ASSERT(
this, IntPtrLessThan(case_value, table_length));
3174 Node* entry = IntPtrAdd(table_start, case_value);
3175 Node* relative_jump = LoadAndUntagConstantPoolEntry(entry);
3176 Jump(relative_jump);
3186 IGNITION_HANDLER(ResumeGenerator, InterpreterAssembler) {
3187 Node* generator = LoadRegisterAtOperandIndex(0);
3188 Node* closure = LoadRegister(Register::function_closure());
3189 RegListNodePair registers = GetRegisterListAtOperandIndex(1);
3192 LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
3193 TNode<Int32T> formal_parameter_count = UncheckedCast<Int32T>(
3194 LoadObjectField(shared, SharedFunctionInfo::kFormalParameterCountOffset,
3195 MachineType::Uint16()));
3198 CAST(LoadObjectField(generator,
3199 JSGeneratorObject::kParametersAndRegistersOffset)),
3200 registers, formal_parameter_count);
3204 LoadObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset));
3211 Handle<Code> GenerateBytecodeHandler(Isolate* isolate, Bytecode bytecode,
3212 OperandScale operand_scale,
3214 const AssemblerOptions& options) {
3215 Zone zone(isolate->allocator(), ZONE_NAME);
3216 compiler::CodeAssemblerState state(
3217 isolate, &zone, InterpreterDispatchDescriptor{}, Code::BYTECODE_HANDLER,
3218 Bytecodes::ToString(bytecode),
3219 FLAG_untrusted_code_mitigations
3220 ? PoisoningMitigationLevel::kPoisonCriticalOnly
3221 : PoisoningMitigationLevel::kDontPoison,
3225 #define CALL_GENERATOR(Name, ...) \ 3226 case Bytecode::k##Name: \ 3227 Name##Assembler::Generate(&state, operand_scale); \ 3229 BYTECODE_LIST(CALL_GENERATOR);
3230 #undef CALL_GENERATOR 3233 Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state, options);
3234 PROFILE(isolate, CodeCreateEvent(
3235 CodeEventListener::BYTECODE_HANDLER_TAG,
3236 AbstractCode::cast(*code),
3237 Bytecodes::ToString(bytecode, operand_scale).c_str()));
3238 #ifdef ENABLE_DISASSEMBLER 3239 if (FLAG_trace_ignition_codegen) {
3241 code->Disassemble(Bytecodes::ToString(bytecode), os);
3244 #endif // ENABLE_DISASSEMBLER