5 #include "src/interpreter/bytecode-array-builder.h" 7 #include "src/globals.h" 8 #include "src/interpreter/bytecode-array-writer.h" 9 #include "src/interpreter/bytecode-jump-table.h" 10 #include "src/interpreter/bytecode-label.h" 11 #include "src/interpreter/bytecode-node.h" 12 #include "src/interpreter/bytecode-register-optimizer.h" 13 #include "src/interpreter/bytecode-source-info.h" 14 #include "src/interpreter/interpreter-intrinsics.h" 15 #include "src/objects-inl.h" 16 #include "src/objects/smi.h" 20 namespace interpreter {
23 :
public NON_EXPORTED_BASE(BytecodeRegisterOptimizer::BytecodeWriter),
24 public NON_EXPORTED_BASE(ZoneObject) {
29 void EmitLdar(
Register input)
override { builder_->OutputLdarRaw(input); }
31 void EmitStar(
Register output)
override { builder_->OutputStarRaw(output); }
34 builder_->OutputMovRaw(input, output);
41 BytecodeArrayBuilder::BytecodeArrayBuilder(
42 Zone* zone,
int parameter_count,
int locals_count,
44 SourcePositionTableBuilder::RecordingMode source_position_mode)
46 feedback_vector_spec_(feedback_vector_spec),
47 bytecode_generated_(false),
48 constant_array_builder_(zone),
49 handler_table_builder_(zone),
50 return_seen_in_block_(false),
51 parameter_count_(parameter_count),
52 local_register_count_(locals_count),
53 register_allocator_(fixed_register_count()),
54 bytecode_array_writer_(zone, &constant_array_builder_,
55 source_position_mode),
56 register_optimizer_(nullptr) {
57 DCHECK_GE(parameter_count_, 0);
58 DCHECK_GE(local_register_count_, 0);
60 if (FLAG_ignition_reo) {
62 zone, ®ister_allocator_, fixed_register_count(), parameter_count,
67 Register BytecodeArrayBuilder::Parameter(
int parameter_index)
const {
68 DCHECK_GE(parameter_index, 0);
71 return Register::FromParameterIndex(parameter_index + 1, parameter_count());
74 Register BytecodeArrayBuilder::Receiver()
const {
75 return Register::FromParameterIndex(0, parameter_count());
78 Register BytecodeArrayBuilder::Local(
int index)
const {
80 CHECK_LT(index, locals_count());
81 return Register(index);
84 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
85 DCHECK(return_seen_in_block_);
86 DCHECK(!bytecode_generated_);
87 bytecode_generated_ =
true;
89 int register_count = total_register_count();
91 if (register_optimizer_) {
92 register_optimizer_->Flush();
93 register_count = register_optimizer_->maxiumum_register_index() + 1;
96 Handle<ByteArray> handler_table =
97 handler_table_builder()->ToHandlerTable(isolate);
98 return bytecode_array_writer_.ToBytecodeArray(
99 isolate, register_count, parameter_count(), handler_table);
102 BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
104 BytecodeSourceInfo source_position;
105 if (latest_source_info_.is_valid()) {
110 if (latest_source_info_.is_statement() ||
111 !FLAG_ignition_filter_expression_positions ||
112 !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
113 source_position = latest_source_info_;
114 latest_source_info_.set_invalid();
117 return source_position;
120 void BytecodeArrayBuilder::SetDeferredSourceInfo(
121 BytecodeSourceInfo source_info) {
122 if (!source_info.is_valid())
return;
123 deferred_source_info_ = source_info;
126 void BytecodeArrayBuilder::AttachOrEmitDeferredSourceInfo(BytecodeNode* node) {
127 if (!deferred_source_info_.is_valid())
return;
128 if (!node->source_info().is_valid()) {
129 node->set_source_info(deferred_source_info_);
130 }
else if (deferred_source_info_.is_statement() &&
131 node->source_info().is_expression()) {
132 BytecodeSourceInfo source_position = node->source_info();
133 source_position.MakeStatementPosition(source_position.source_position());
134 node->set_source_info(source_position);
136 deferred_source_info_.set_invalid();
139 void BytecodeArrayBuilder::Write(BytecodeNode* node) {
140 AttachOrEmitDeferredSourceInfo(node);
141 bytecode_array_writer_.Write(node);
144 void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
145 AttachOrEmitDeferredSourceInfo(node);
146 bytecode_array_writer_.WriteJump(node, label);
149 void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node,
150 BytecodeJumpTable* jump_table) {
151 AttachOrEmitDeferredSourceInfo(node);
152 bytecode_array_writer_.WriteSwitch(node, jump_table);
155 void BytecodeArrayBuilder::OutputLdarRaw(Register reg) {
157 BytecodeNode node(BytecodeNode::Ldar(BytecodeSourceInfo(), operand));
161 void BytecodeArrayBuilder::OutputStarRaw(Register reg) {
163 BytecodeNode node(BytecodeNode::Star(BytecodeSourceInfo(), operand));
167 void BytecodeArrayBuilder::OutputMovRaw(Register src, Register dest) {
171 BytecodeNode::Mov(BytecodeSourceInfo(), operand0, operand1));
177 template <OperandTypeInfo type_info>
178 class UnsignedOperandHelper {
180 V8_INLINE
static uint32_t Convert(BytecodeArrayBuilder* builder,
182 DCHECK(IsValid(value));
183 return static_cast<uint32_t>(value);
186 V8_INLINE
static uint32_t Convert(BytecodeArrayBuilder* builder,
int value) {
188 return Convert(builder, static_cast<size_t>(value));
192 static bool IsValid(
size_t value) {
194 case OperandTypeInfo::kFixedUnsignedByte:
195 return value <= kMaxUInt8;
196 case OperandTypeInfo::kFixedUnsignedShort:
197 return value <= kMaxUInt16;
198 case OperandTypeInfo::kScalableUnsignedByte:
199 return value <= kMaxUInt32;
206 template <OperandType>
207 class OperandHelper {};
209 #define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \ 211 class OperandHelper<OperandType::k##Name> \ 212 : public UnsignedOperandHelper<Type> {}; 213 UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
214 UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
215 #undef DEFINE_UNSIGNED_OPERAND_HELPER 218 class OperandHelper<OperandType::kImm> {
220 V8_INLINE
static uint32_t Convert(BytecodeArrayBuilder* builder,
int value) {
221 return static_cast<uint32_t>(value);
226 class OperandHelper<OperandType::kReg> {
228 V8_INLINE
static uint32_t Convert(BytecodeArrayBuilder* builder,
230 return builder->GetInputRegisterOperand(reg);
235 class OperandHelper<OperandType::kRegList> {
237 V8_INLINE
static uint32_t Convert(BytecodeArrayBuilder* builder,
238 RegisterList reg_list) {
239 return builder->GetInputRegisterListOperand(reg_list);
244 class OperandHelper<OperandType::kRegPair> {
246 V8_INLINE
static uint32_t Convert(BytecodeArrayBuilder* builder,
247 RegisterList reg_list) {
248 DCHECK_EQ(reg_list.register_count(), 2);
249 return builder->GetInputRegisterListOperand(reg_list);
254 class OperandHelper<OperandType::kRegOut> {
256 V8_INLINE
static uint32_t Convert(BytecodeArrayBuilder* builder,
258 return builder->GetOutputRegisterOperand(reg);
263 class OperandHelper<OperandType::kRegOutList> {
265 V8_INLINE
static uint32_t Convert(BytecodeArrayBuilder* builder,
266 RegisterList reg_list) {
267 return builder->GetOutputRegisterListOperand(reg_list);
272 class OperandHelper<OperandType::kRegOutPair> {
274 V8_INLINE
static uint32_t Convert(BytecodeArrayBuilder* builder,
275 RegisterList reg_list) {
276 DCHECK_EQ(2, reg_list.register_count());
277 return builder->GetOutputRegisterListOperand(reg_list);
282 class OperandHelper<OperandType::kRegOutTriple> {
284 V8_INLINE
static uint32_t Convert(BytecodeArrayBuilder* builder,
285 RegisterList reg_list) {
286 DCHECK_EQ(3, reg_list.register_count());
287 return builder->GetOutputRegisterListOperand(reg_list);
293 template <Bytecode bytecode, AccumulatorUse accumulator_use,
294 OperandType... operand_types>
297 template <
typename... Operands>
299 Operands... operands) {
300 static_assert(
sizeof...(Operands) <= Bytecodes::kMaxOperands,
301 "too many operands for bytecode");
302 builder->PrepareToOutputBytecode<bytecode, accumulator_use>();
310 return BytecodeNode::Create<bytecode, accumulator_use, operand_types...>(
311 builder->CurrentSourcePosition(bytecode),
312 OperandHelper<operand_types>::Convert(builder, operands)...);
316 #define DEFINE_BYTECODE_OUTPUT(name, ...) \ 317 template <typename... Operands> \ 318 BytecodeNode BytecodeArrayBuilder::Create##name##Node( \ 319 Operands... operands) { \ 320 return BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make( \ 321 this, operands...); \ 324 template <typename... Operands> \ 325 void BytecodeArrayBuilder::Output##name(Operands... operands) { \ 326 BytecodeNode node(Create##name##Node(operands...)); \ 330 template <typename... Operands> \ 331 void BytecodeArrayBuilder::Output##name(BytecodeLabel* label, \ 332 Operands... operands) { \ 333 DCHECK(Bytecodes::IsJump(Bytecode::k##name)); \ 334 BytecodeNode node(Create##name##Node(operands...)); \ 335 WriteJump(&node, label); \ 338 BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
339 #undef DEFINE_BYTECODE_OUTPUT 341 void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback(
344 jump_table->constant_pool_index(), jump_table->size(),
345 jump_table->case_value_base()));
346 WriteSwitch(&node, jump_table);
350 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
354 case Token::Value::ADD:
355 OutputAdd(reg, feedback_slot);
357 case Token::Value::SUB:
358 OutputSub(reg, feedback_slot);
360 case Token::Value::MUL:
361 OutputMul(reg, feedback_slot);
363 case Token::Value::DIV:
364 OutputDiv(reg, feedback_slot);
366 case Token::Value::MOD:
367 OutputMod(reg, feedback_slot);
369 case Token::Value::EXP:
370 OutputExp(reg, feedback_slot);
372 case Token::Value::BIT_OR:
373 OutputBitwiseOr(reg, feedback_slot);
375 case Token::Value::BIT_XOR:
376 OutputBitwiseXor(reg, feedback_slot);
378 case Token::Value::BIT_AND:
379 OutputBitwiseAnd(reg, feedback_slot);
381 case Token::Value::SHL:
382 OutputShiftLeft(reg, feedback_slot);
384 case Token::Value::SAR:
385 OutputShiftRight(reg, feedback_slot);
387 case Token::Value::SHR:
388 OutputShiftRightLogical(reg, feedback_slot);
396 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
397 Token::Value op, Smi literal,
int feedback_slot) {
399 case Token::Value::ADD:
400 OutputAddSmi(literal->value(), feedback_slot);
402 case Token::Value::SUB:
403 OutputSubSmi(literal->value(), feedback_slot);
405 case Token::Value::MUL:
406 OutputMulSmi(literal->value(), feedback_slot);
408 case Token::Value::DIV:
409 OutputDivSmi(literal->value(), feedback_slot);
411 case Token::Value::MOD:
412 OutputModSmi(literal->value(), feedback_slot);
414 case Token::Value::EXP:
415 OutputExpSmi(literal->value(), feedback_slot);
417 case Token::Value::BIT_OR:
418 OutputBitwiseOrSmi(literal->value(), feedback_slot);
420 case Token::Value::BIT_XOR:
421 OutputBitwiseXorSmi(literal->value(), feedback_slot);
423 case Token::Value::BIT_AND:
424 OutputBitwiseAndSmi(literal->value(), feedback_slot);
426 case Token::Value::SHL:
427 OutputShiftLeftSmi(literal->value(), feedback_slot);
429 case Token::Value::SAR:
430 OutputShiftRightSmi(literal->value(), feedback_slot);
432 case Token::Value::SHR:
433 OutputShiftRightLogicalSmi(literal->value(), feedback_slot);
441 BytecodeArrayBuilder& BytecodeArrayBuilder::UnaryOperation(Token::Value op,
444 case Token::Value::INC:
445 OutputInc(feedback_slot);
447 case Token::Value::DEC:
448 OutputDec(feedback_slot);
450 case Token::Value::ADD:
451 OutputToNumber(feedback_slot);
453 case Token::Value::SUB:
454 OutputNegate(feedback_slot);
456 case Token::Value::BIT_NOT:
457 OutputBitwiseNot(feedback_slot);
465 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
466 if (mode == ToBooleanMode::kAlreadyBoolean) {
469 DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
470 OutputToBooleanLogicalNot();
475 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
480 BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
481 OutputGetSuperConstructor(out);
485 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
486 Token::Value op, Register reg,
int feedback_slot) {
488 case Token::Value::EQ:
489 OutputTestEqual(reg, feedback_slot);
491 case Token::Value::EQ_STRICT:
492 OutputTestEqualStrict(reg, feedback_slot);
494 case Token::Value::LT:
495 OutputTestLessThan(reg, feedback_slot);
497 case Token::Value::GT:
498 OutputTestGreaterThan(reg, feedback_slot);
500 case Token::Value::LTE:
501 OutputTestLessThanOrEqual(reg, feedback_slot);
503 case Token::Value::GTE:
504 OutputTestGreaterThanOrEqual(reg, feedback_slot);
506 case Token::Value::INSTANCEOF:
507 OutputTestInstanceOf(reg, feedback_slot);
515 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
518 case Token::Value::IN:
527 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareReference(Register reg) {
528 OutputTestReferenceEqual(reg);
532 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndetectable() {
533 OutputTestUndetectable();
537 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndefined() {
538 OutputTestUndefined();
542 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNull() {
547 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNil(Token::Value op,
549 if (op == Token::EQ) {
550 return CompareUndetectable();
552 DCHECK_EQ(Token::EQ_STRICT, op);
553 if (nil == kUndefinedValue) {
554 return CompareUndefined();
556 DCHECK_EQ(kNullValue, nil);
557 return CompareNull();
562 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
563 TestTypeOfFlags::LiteralFlag literal_flag) {
564 DCHECK_NE(literal_flag, TestTypeOfFlags::LiteralFlag::kOther);
565 OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
569 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
571 OutputLdaConstant(entry);
575 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Smi smi) {
576 int32_t raw_smi = smi->value();
580 OutputLdaSmi(raw_smi);
585 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
double value) {
586 size_t entry = GetConstantPoolEntry(value);
587 OutputLdaConstant(entry);
591 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
592 const AstRawString* raw_string) {
593 size_t entry = GetConstantPoolEntry(raw_string);
594 OutputLdaConstant(entry);
598 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
const Scope* scope) {
599 size_t entry = GetConstantPoolEntry(scope);
600 OutputLdaConstant(entry);
604 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstBigInt bigint) {
605 size_t entry = GetConstantPoolEntry(bigint);
606 OutputLdaConstant(entry);
610 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstSymbol symbol) {
613 case AstSymbol::kHomeObjectSymbol:
614 entry = HomeObjectSymbolConstantPoolEntry();
618 OutputLdaConstant(entry);
622 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
623 OutputLdaUndefined();
627 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
632 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
637 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
642 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
647 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBoolean(
bool value) {
648 return value ? LoadTrue() : LoadFalse();
651 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
653 if (register_optimizer_) {
656 SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kLdar));
657 register_optimizer_->DoLdar(reg);
664 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
666 if (register_optimizer_) {
669 SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kStar));
670 register_optimizer_->DoStar(reg);
677 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
680 if (register_optimizer_) {
683 SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kMov));
684 register_optimizer_->DoMov(from, to);
691 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(
const AstRawString* name,
693 TypeofMode typeof_mode) {
694 size_t name_index = GetConstantPoolEntry(name);
696 DCHECK_EQ(GetTypeofModeFromSlotKind(feedback_vector_spec()->GetKind(
697 FeedbackVector::ToSlot(feedback_slot))),
699 if (typeof_mode == INSIDE_TYPEOF) {
700 OutputLdaGlobalInsideTypeof(name_index, feedback_slot);
702 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
703 OutputLdaGlobal(name_index, feedback_slot);
708 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
709 const AstRawString* name,
int feedback_slot) {
710 size_t name_index = GetConstantPoolEntry(name);
711 OutputStaGlobal(name_index, feedback_slot);
715 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
716 Register context,
int slot_index,
int depth,
717 ContextSlotMutability mutability) {
718 if (context.is_current_context() && depth == 0) {
719 if (mutability == kImmutableSlot) {
720 OutputLdaImmutableCurrentContextSlot(slot_index);
722 DCHECK_EQ(kMutableSlot, mutability);
723 OutputLdaCurrentContextSlot(slot_index);
725 }
else if (mutability == kImmutableSlot) {
726 OutputLdaImmutableContextSlot(context, slot_index, depth);
728 DCHECK_EQ(mutability, kMutableSlot);
729 OutputLdaContextSlot(context, slot_index, depth);
734 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
737 if (context.is_current_context() && depth == 0) {
738 OutputStaCurrentContextSlot(slot_index);
740 OutputStaContextSlot(context, slot_index, depth);
745 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
746 const AstRawString* name, TypeofMode typeof_mode) {
747 size_t name_index = GetConstantPoolEntry(name);
748 if (typeof_mode == INSIDE_TYPEOF) {
749 OutputLdaLookupSlotInsideTypeof(name_index);
751 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
752 OutputLdaLookupSlot(name_index);
757 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
758 const AstRawString* name, TypeofMode typeof_mode,
int slot_index,
760 size_t name_index = GetConstantPoolEntry(name);
761 if (typeof_mode == INSIDE_TYPEOF) {
762 OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
764 DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
765 OutputLdaLookupContextSlot(name_index, slot_index, depth);
770 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
771 const AstRawString* name, TypeofMode typeof_mode,
int feedback_slot,
773 size_t name_index = GetConstantPoolEntry(name);
774 if (typeof_mode == INSIDE_TYPEOF) {
775 OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth);
777 DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
778 OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth);
783 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
784 const AstRawString* name, LanguageMode language_mode,
785 LookupHoistingMode lookup_hoisting_mode) {
786 size_t name_index = GetConstantPoolEntry(name);
788 StoreLookupSlotFlags::Encode(language_mode, lookup_hoisting_mode);
789 OutputStaLookupSlot(name_index, flags);
793 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
794 Register
object,
const AstRawString* name,
int feedback_slot) {
795 size_t name_index = GetConstantPoolEntry(name);
796 OutputLdaNamedProperty(
object, name_index, feedback_slot);
800 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyNoFeedback(
801 Register
object,
const AstRawString* name) {
802 size_t name_index = GetConstantPoolEntry(name);
803 OutputLdaNamedPropertyNoFeedback(
object, name_index);
807 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
808 Register
object,
int feedback_slot) {
809 OutputLdaKeyedProperty(
object, feedback_slot);
813 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
814 Register
object,
int feedback_slot) {
815 size_t name_index = IteratorSymbolConstantPoolEntry();
816 OutputLdaNamedProperty(
object, name_index, feedback_slot);
820 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
821 Register
object,
int feedback_slot) {
822 size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
823 OutputLdaNamedProperty(
object, name_index, feedback_slot);
827 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
828 Register
object, Register name, DataPropertyInLiteralFlags flags,
830 OutputStaDataPropertyInLiteral(
object, name, flags, feedback_slot);
834 BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(
int position) {
835 OutputCollectTypeProfile(position);
839 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
840 Register
object,
size_t name_index,
int feedback_slot,
841 LanguageMode language_mode) {
843 DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
844 FeedbackVector::ToSlot(feedback_slot))),
846 OutputStaNamedProperty(
object, name_index, feedback_slot);
850 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
851 Register
object,
const AstRawString* name,
int feedback_slot,
852 LanguageMode language_mode) {
853 size_t name_index = GetConstantPoolEntry(name);
854 return StoreNamedProperty(
object, name_index, feedback_slot, language_mode);
857 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedPropertyNoFeedback(
858 Register
object,
const AstRawString* name, LanguageMode language_mode) {
859 size_t name_index = GetConstantPoolEntry(name);
860 OutputStaNamedPropertyNoFeedback(
object, name_index,
861 static_cast<uint8_t>(language_mode));
865 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedOwnProperty(
866 Register
object,
const AstRawString* name,
int feedback_slot) {
867 size_t name_index = GetConstantPoolEntry(name);
870 FeedbackSlotKind::kStoreOwnNamed,
871 feedback_vector_spec()->GetKind(FeedbackVector::ToSlot(feedback_slot)));
872 OutputStaNamedOwnProperty(
object, name_index, feedback_slot);
876 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
877 Register
object, Register key,
int feedback_slot,
878 LanguageMode language_mode) {
880 DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
881 FeedbackVector::ToSlot(feedback_slot))),
883 OutputStaKeyedProperty(
object, key, feedback_slot);
887 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreInArrayLiteral(
888 Register array, Register index,
int feedback_slot) {
889 OutputStaInArrayLiteral(array, index, feedback_slot);
893 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreHomeObjectProperty(
894 Register
object,
int feedback_slot, LanguageMode language_mode) {
895 size_t name_index = HomeObjectSymbolConstantPoolEntry();
896 return StoreNamedProperty(
object, name_index, feedback_slot, language_mode);
899 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreClassFieldsInitializer(
900 Register constructor,
int feedback_slot) {
901 size_t name_index = ClassFieldsSymbolConstantPoolEntry();
902 return StoreNamedProperty(constructor, name_index, feedback_slot,
903 LanguageMode::kStrict);
906 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadClassFieldsInitializer(
907 Register constructor,
int feedback_slot) {
908 size_t name_index = ClassFieldsSymbolConstantPoolEntry();
909 OutputLdaNamedProperty(constructor, name_index, feedback_slot);
913 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
914 size_t shared_function_info_entry,
int slot,
int flags) {
915 OutputCreateClosure(shared_function_info_entry, slot, flags);
919 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
920 const Scope* scope) {
921 size_t entry = GetConstantPoolEntry(scope);
922 OutputCreateBlockContext(entry);
926 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
927 Register exception,
const Scope* scope) {
928 size_t scope_index = GetConstantPoolEntry(scope);
929 OutputCreateCatchContext(exception, scope_index);
933 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(
934 const Scope* scope,
int slots) {
935 size_t scope_index = GetConstantPoolEntry(scope);
936 OutputCreateFunctionContext(scope_index, slots);
940 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(
941 const Scope* scope,
int slots) {
942 size_t scope_index = GetConstantPoolEntry(scope);
943 OutputCreateEvalContext(scope_index, slots);
947 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
948 Register
object,
const Scope* scope) {
949 size_t scope_index = GetConstantPoolEntry(scope);
950 OutputCreateWithContext(
object, scope_index);
954 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
955 CreateArgumentsType type) {
957 case CreateArgumentsType::kMappedArguments:
958 OutputCreateMappedArguments();
960 case CreateArgumentsType::kUnmappedArguments:
961 OutputCreateUnmappedArguments();
963 case CreateArgumentsType::kRestParameter:
964 OutputCreateRestParameter();
972 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
973 const AstRawString* pattern,
int literal_index,
int flags) {
974 size_t pattern_entry = GetConstantPoolEntry(pattern);
975 OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
979 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyArrayLiteral(
981 OutputCreateEmptyArrayLiteral(literal_index);
985 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
986 size_t constant_elements_entry,
int literal_index,
int flags) {
987 OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
991 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayFromIterable() {
992 OutputCreateArrayFromIterable();
996 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
997 size_t constant_properties_entry,
int literal_index,
int flags) {
998 OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags);
1002 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyObjectLiteral() {
1003 OutputCreateEmptyObjectLiteral();
1007 BytecodeArrayBuilder& BytecodeArrayBuilder::CloneObject(Register source,
1009 int feedback_slot) {
1010 OutputCloneObject(source, flags, feedback_slot);
1014 BytecodeArrayBuilder& BytecodeArrayBuilder::GetTemplateObject(
1015 size_t template_object_description_entry,
int feedback_slot) {
1016 OutputGetTemplateObject(template_object_description_entry, feedback_slot);
1020 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
1021 OutputPushContext(context);
1025 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
1026 OutputPopContext(context);
1030 BytecodeArrayBuilder& BytecodeArrayBuilder::ToObject(Register out) {
1031 OutputToObject(out);
1035 BytecodeArrayBuilder& BytecodeArrayBuilder::ToName(Register out) {
1040 BytecodeArrayBuilder& BytecodeArrayBuilder::ToString() {
1045 BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumber(
int feedback_slot) {
1046 OutputToNumber(feedback_slot);
1050 BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(
int feedback_slot) {
1051 OutputToNumeric(feedback_slot);
1055 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
1058 if (register_optimizer_) register_optimizer_->Flush();
1059 bytecode_array_writer_.BindLabel(label);
1064 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(
const BytecodeLabel& target,
1065 BytecodeLabel* label) {
1066 bytecode_array_writer_.BindLabel(target, label);
1071 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeJumpTable* jump_table,
1075 if (register_optimizer_) register_optimizer_->Flush();
1076 bytecode_array_writer_.BindJumpTableEntry(jump_table, case_value);
1081 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
1082 DCHECK(!label->is_bound());
1083 OutputJump(label, 0);
1087 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
1088 BytecodeLabel* label) {
1089 DCHECK(!label->is_bound());
1090 if (mode == ToBooleanMode::kAlreadyBoolean) {
1091 OutputJumpIfTrue(label, 0);
1093 DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1094 OutputJumpIfToBooleanTrue(label, 0);
1099 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
1100 BytecodeLabel* label) {
1101 DCHECK(!label->is_bound());
1102 if (mode == ToBooleanMode::kAlreadyBoolean) {
1103 OutputJumpIfFalse(label, 0);
1105 DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1106 OutputJumpIfToBooleanFalse(label, 0);
1111 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
1112 DCHECK(!label->is_bound());
1113 OutputJumpIfNull(label, 0);
1117 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
1118 BytecodeLabel* label) {
1119 DCHECK(!label->is_bound());
1120 OutputJumpIfNotNull(label, 0);
1124 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
1125 BytecodeLabel* label) {
1126 DCHECK(!label->is_bound());
1127 OutputJumpIfUndefined(label, 0);
1131 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotUndefined(
1132 BytecodeLabel* label) {
1133 DCHECK(!label->is_bound());
1134 OutputJumpIfNotUndefined(label, 0);
1138 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
1141 if (op == Token::EQ) {
1143 return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
1146 DCHECK_EQ(Token::EQ_STRICT, op);
1147 if (nil == kUndefinedValue) {
1148 return JumpIfUndefined(label);
1150 DCHECK_EQ(kNullValue, nil);
1151 return JumpIfNull(label);
1156 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
1159 if (op == Token::EQ) {
1161 return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
1164 DCHECK_EQ(Token::EQ_STRICT, op);
1165 if (nil == kUndefinedValue) {
1166 return JumpIfNotUndefined(label);
1168 DCHECK_EQ(kNullValue, nil);
1169 return JumpIfNotNull(label);
1174 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
1175 BytecodeLabel* label) {
1176 DCHECK(!label->is_bound());
1177 OutputJumpIfJSReceiver(label, 0);
1181 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
1183 DCHECK(label->is_bound());
1184 OutputJumpLoop(label, 0, loop_depth);
1188 BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnSmiNoFeedback(
1189 BytecodeJumpTable* jump_table) {
1190 OutputSwitchOnSmiNoFeedback(jump_table);
1194 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(
int position) {
1195 if (position != kNoSourcePosition) {
1206 latest_source_info_.ForceExpressionPosition(position);
1212 BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
1213 OutputSetPendingMessage();
1217 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
1222 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
1227 BytecodeArrayBuilder& BytecodeArrayBuilder::Abort(AbortReason reason) {
1228 DCHECK_LT(reason, AbortReason::kLastErrorMessage);
1229 DCHECK_GE(reason, AbortReason::kNoReason);
1230 OutputAbort(static_cast<int>(reason));
1234 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
1236 return_seen_in_block_ =
true;
1240 BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowReferenceErrorIfHole(
1241 const AstRawString* name) {
1242 size_t entry = GetConstantPoolEntry(name);
1243 OutputThrowReferenceErrorIfHole(entry);
1247 BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperNotCalledIfHole() {
1248 OutputThrowSuperNotCalledIfHole();
1252 BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperAlreadyCalledIfNotHole() {
1253 OutputThrowSuperAlreadyCalledIfNotHole();
1257 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
1262 BytecodeArrayBuilder& BytecodeArrayBuilder::IncBlockCounter(
1263 int coverage_array_slot) {
1264 OutputIncBlockCounter(coverage_array_slot);
1268 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInEnumerate(Register receiver) {
1269 OutputForInEnumerate(receiver);
1273 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
1274 RegisterList cache_info_triple,
int feedback_slot) {
1275 DCHECK_EQ(3, cache_info_triple.register_count());
1276 OutputForInPrepare(cache_info_triple, feedback_slot);
1280 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
1281 Register index, Register cache_length) {
1282 OutputForInContinue(index, cache_length);
1286 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
1287 Register receiver, Register index, RegisterList cache_type_array_pair,
1288 int feedback_slot) {
1289 DCHECK_EQ(2, cache_type_array_pair.register_count());
1290 OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
1294 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
1295 OutputForInStep(index);
1299 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(
int cell_index,
1301 OutputStaModuleVariable(cell_index, depth);
1305 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(
int cell_index,
1307 OutputLdaModuleVariable(cell_index, depth);
1311 BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
1312 Register generator, RegisterList registers,
int suspend_id) {
1313 OutputSuspendGenerator(generator, registers, registers.register_count(),
1318 BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnGeneratorState(
1319 Register generator, BytecodeJumpTable* jump_table) {
1320 DCHECK_EQ(jump_table->case_value_base(), 0);
1321 BytecodeNode node(CreateSwitchOnGeneratorStateNode(
1322 generator, jump_table->constant_pool_index(), jump_table->size()));
1323 WriteSwitch(&node, jump_table);
1328 BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
1329 Register generator, RegisterList registers) {
1330 OutputResumeGenerator(generator, registers, registers.register_count());
1334 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
1335 int handler_id, HandlerTable::CatchPrediction catch_prediction) {
1336 BytecodeLabel handler;
1338 handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
1339 handler_table_builder()->SetPrediction(handler_id, catch_prediction);
1343 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(
int handler_id,
1347 BytecodeLabel try_begin;
1349 handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
1350 handler_table_builder()->SetContextRegister(handler_id, context);
1354 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(
int handler_id) {
1355 BytecodeLabel try_end;
1357 handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
1361 BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable,
1363 int feedback_slot) {
1364 if (args.register_count() == 1) {
1365 OutputCallProperty0(callable, args[0], feedback_slot);
1366 }
else if (args.register_count() == 2) {
1367 OutputCallProperty1(callable, args[0], args[1], feedback_slot);
1368 }
else if (args.register_count() == 3) {
1369 OutputCallProperty2(callable, args[0], args[1], args[2], feedback_slot);
1371 OutputCallProperty(callable, args, args.register_count(), feedback_slot);
1376 BytecodeArrayBuilder& BytecodeArrayBuilder::CallUndefinedReceiver(
1377 Register callable, RegisterList args,
int feedback_slot) {
1378 if (args.register_count() == 0) {
1379 OutputCallUndefinedReceiver0(callable, feedback_slot);
1380 }
else if (args.register_count() == 1) {
1381 OutputCallUndefinedReceiver1(callable, args[0], feedback_slot);
1382 }
else if (args.register_count() == 2) {
1383 OutputCallUndefinedReceiver2(callable, args[0], args[1], feedback_slot);
1385 OutputCallUndefinedReceiver(callable, args, args.register_count(),
1391 BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
1393 int feedback_slot) {
1394 OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot);
1398 BytecodeArrayBuilder& BytecodeArrayBuilder::CallNoFeedback(Register callable,
1399 RegisterList args) {
1400 OutputCallNoFeedback(callable, args, args.register_count());
1404 BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
1406 int feedback_slot) {
1407 OutputCallWithSpread(callable, args, args.register_count(), feedback_slot);
1411 BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
1413 int feedback_slot_id) {
1414 OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
1418 BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
1419 Register constructor, RegisterList args,
int feedback_slot_id) {
1420 OutputConstructWithSpread(constructor, args, args.register_count(),
1425 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1426 Runtime::FunctionId function_id, RegisterList args) {
1427 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
1428 DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
1429 OperandSize::kShort);
1430 if (IntrinsicsHelper::IsSupported(function_id)) {
1431 IntrinsicsHelper::IntrinsicId intrinsic_id =
1432 IntrinsicsHelper::FromRuntimeId(function_id);
1433 OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
1434 args.register_count());
1436 OutputCallRuntime(static_cast<int>(function_id), args,
1437 args.register_count());
1442 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1443 Runtime::FunctionId function_id, Register arg) {
1444 return CallRuntime(function_id, RegisterList(arg));
1447 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1448 Runtime::FunctionId function_id) {
1449 return CallRuntime(function_id, RegisterList());
1452 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1453 Runtime::FunctionId function_id, RegisterList args,
1454 RegisterList return_pair) {
1455 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
1456 DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
1457 OperandSize::kShort);
1458 DCHECK_EQ(2, return_pair.register_count());
1459 OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
1460 args.register_count(), return_pair);
1464 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1465 Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
1466 return CallRuntimeForPair(function_id, RegisterList(arg), return_pair);
1469 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(
int context_index,
1470 RegisterList args) {
1471 OutputCallJSRuntime(context_index, args, args.register_count());
1475 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register
object,
1476 LanguageMode language_mode) {
1477 if (language_mode == LanguageMode::kSloppy) {
1478 OutputDeletePropertySloppy(
object);
1480 DCHECK_EQ(language_mode, LanguageMode::kStrict);
1481 OutputDeletePropertyStrict(
object);
1486 size_t BytecodeArrayBuilder::GetConstantPoolEntry(
1487 const AstRawString* raw_string) {
1488 return constant_array_builder()->Insert(raw_string);
1491 size_t BytecodeArrayBuilder::GetConstantPoolEntry(AstBigInt bigint) {
1492 return constant_array_builder()->Insert(bigint);
1495 size_t BytecodeArrayBuilder::GetConstantPoolEntry(
const Scope* scope) {
1496 return constant_array_builder()->Insert(scope);
1499 size_t BytecodeArrayBuilder::GetConstantPoolEntry(
double number) {
1500 return constant_array_builder()->Insert(number);
1503 #define ENTRY_GETTER(NAME, ...) \ 1504 size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \ 1505 return constant_array_builder()->Insert##NAME(); \ 1507 SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
1510 BytecodeJumpTable* BytecodeArrayBuilder::AllocateJumpTable(
1511 int size,
int case_value_base) {
1514 size_t constant_pool_index = constant_array_builder()->InsertJumpTable(size);
1517 BytecodeJumpTable(constant_pool_index, size, case_value_base, zone());
1520 size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
1521 return constant_array_builder()->InsertDeferred();
1524 void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(
size_t entry,
1525 Handle<Object>
object) {
1526 constant_array_builder()->SetDeferredAt(entry,
object);
1529 bool BytecodeArrayBuilder::RegisterIsValid(Register reg)
const {
1530 if (!reg.is_valid()) {
1534 if (reg.is_current_context() || reg.is_function_closure()) {
1536 }
else if (reg.is_parameter()) {
1537 int parameter_index = reg.ToParameterIndex(parameter_count());
1538 return parameter_index >= 0 && parameter_index < parameter_count();
1539 }
else if (reg.index() < fixed_register_count()) {
1542 return register_allocator()->RegisterIsLive(reg);
1546 bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list)
const {
1547 if (reg_list.register_count() == 0) {
1548 return reg_list.first_register() == Register(0);
1550 int first_reg_index = reg_list.first_register().index();
1551 for (
int i = 0;
i < reg_list.register_count();
i++) {
1552 if (!RegisterIsValid(Register(first_reg_index +
i))) {
1560 template <Bytecode bytecode, AccumulatorUse accumulator_use>
1561 void BytecodeArrayBuilder::PrepareToOutputBytecode() {
1562 if (register_optimizer_)
1563 register_optimizer_->PrepareForBytecode<bytecode, accumulator_use>();
1566 uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
1567 DCHECK(RegisterIsValid(reg));
1568 if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
1569 return static_cast<uint32_t>(reg.ToOperand());
1572 uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
1573 DCHECK(RegisterIsValid(reg));
1574 if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
1575 return static_cast<uint32_t>(reg.ToOperand());
1578 uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
1579 RegisterList reg_list) {
1580 DCHECK(RegisterListIsValid(reg_list));
1581 if (register_optimizer_)
1582 reg_list = register_optimizer_->GetInputRegisterList(reg_list);
1583 return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1586 uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
1587 RegisterList reg_list) {
1588 DCHECK(RegisterListIsValid(reg_list));
1589 if (register_optimizer_)
1590 register_optimizer_->PrepareOutputRegisterList(reg_list);
1591 return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1594 std::ostream& operator<<(std::ostream& os,
1595 const BytecodeArrayBuilder::ToBooleanMode& mode) {
1597 case BytecodeArrayBuilder::ToBooleanMode::kAlreadyBoolean:
1598 return os <<
"AlreadyBoolean";
1599 case BytecodeArrayBuilder::ToBooleanMode::kConvertToBoolean:
1600 return os <<
"ConvertToBoolean";