1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/interpreter/bytecode-array-builder.h"
6
7 #include "src/common/assert-scope.h"
8 #include "src/common/globals.h"
9 #include "src/interpreter/bytecode-array-writer.h"
10 #include "src/interpreter/bytecode-jump-table.h"
11 #include "src/interpreter/bytecode-label.h"
12 #include "src/interpreter/bytecode-node.h"
13 #include "src/interpreter/bytecode-register-optimizer.h"
14 #include "src/interpreter/bytecode-source-info.h"
15 #include "src/interpreter/interpreter-intrinsics.h"
16 #include "src/objects/feedback-vector-inl.h"
17 #include "src/objects/smi.h"
18
19 namespace v8 {
20 namespace internal {
21 namespace interpreter {
22
23 class RegisterTransferWriter final
24 : public NON_EXPORTED_BASE(BytecodeRegisterOptimizer::BytecodeWriter),
25 public NON_EXPORTED_BASE(ZoneObject) {
26 public:
RegisterTransferWriter(BytecodeArrayBuilder * builder)27 explicit RegisterTransferWriter(BytecodeArrayBuilder* builder)
28 : builder_(builder) {}
29 ~RegisterTransferWriter() override = default;
30
EmitLdar(Register input)31 void EmitLdar(Register input) override { builder_->OutputLdarRaw(input); }
32
EmitStar(Register output)33 void EmitStar(Register output) override { builder_->OutputStarRaw(output); }
34
EmitMov(Register input,Register output)35 void EmitMov(Register input, Register output) override {
36 builder_->OutputMovRaw(input, output);
37 }
38
39 private:
40 BytecodeArrayBuilder* builder_;
41 };
42
BytecodeArrayBuilder(Zone * zone,int parameter_count,int locals_count,FeedbackVectorSpec * feedback_vector_spec,SourcePositionTableBuilder::RecordingMode source_position_mode)43 BytecodeArrayBuilder::BytecodeArrayBuilder(
44 Zone* zone, int parameter_count, int locals_count,
45 FeedbackVectorSpec* feedback_vector_spec,
46 SourcePositionTableBuilder::RecordingMode source_position_mode)
47 : zone_(zone),
48 feedback_vector_spec_(feedback_vector_spec),
49 bytecode_generated_(false),
50 constant_array_builder_(zone),
51 handler_table_builder_(zone),
52 parameter_count_(parameter_count),
53 local_register_count_(locals_count),
54 register_allocator_(fixed_register_count()),
55 bytecode_array_writer_(zone, &constant_array_builder_,
56 source_position_mode),
57 register_optimizer_(nullptr) {
58 DCHECK_GE(parameter_count_, 0);
59 DCHECK_GE(local_register_count_, 0);
60
61 if (FLAG_ignition_reo) {
62 register_optimizer_ = zone->New<BytecodeRegisterOptimizer>(
63 zone, ®ister_allocator_, fixed_register_count(), parameter_count,
64 zone->New<RegisterTransferWriter>(this));
65 }
66 }
67
Parameter(int parameter_index) const68 Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
69 DCHECK_GE(parameter_index, 0);
70 // The parameter indices are shifted by 1 (receiver is the
71 // first entry).
72 return Register::FromParameterIndex(parameter_index + 1);
73 }
74
Receiver() const75 Register BytecodeArrayBuilder::Receiver() const {
76 return Register::FromParameterIndex(0);
77 }
78
Local(int index) const79 Register BytecodeArrayBuilder::Local(int index) const {
80 DCHECK_LT(index, locals_count());
81 return Register(index);
82 }
83
84 template <typename IsolateT>
ToBytecodeArray(IsolateT * isolate)85 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(IsolateT* isolate) {
86 DCHECK(RemainderOfBlockIsDead());
87 DCHECK(!bytecode_generated_);
88 bytecode_generated_ = true;
89
90 int register_count = total_register_count();
91
92 if (register_optimizer_) {
93 register_optimizer_->Flush();
94 register_count = register_optimizer_->maxiumum_register_index() + 1;
95 }
96
97 Handle<ByteArray> handler_table =
98 handler_table_builder()->ToHandlerTable(isolate);
99 return bytecode_array_writer_.ToBytecodeArray(
100 isolate, register_count, parameter_count(), handler_table);
101 }
102
103 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
104 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(
105 Isolate* isolate);
106 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
107 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(
108 LocalIsolate* isolate);
109
110 #ifdef DEBUG
CheckBytecodeMatches(BytecodeArray bytecode)111 int BytecodeArrayBuilder::CheckBytecodeMatches(BytecodeArray bytecode) {
112 DisallowGarbageCollection no_gc;
113 return bytecode_array_writer_.CheckBytecodeMatches(bytecode);
114 }
115 #endif
116
117 template <typename IsolateT>
ToSourcePositionTable(IsolateT * isolate)118 Handle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
119 IsolateT* isolate) {
120 DCHECK(RemainderOfBlockIsDead());
121
122 return bytecode_array_writer_.ToSourcePositionTable(isolate);
123 }
124
125 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
126 Handle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
127 Isolate* isolate);
128 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
129 Handle<ByteArray> BytecodeArrayBuilder::ToSourcePositionTable(
130 LocalIsolate* isolate);
131
CurrentSourcePosition(Bytecode bytecode)132 BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
133 Bytecode bytecode) {
134 BytecodeSourceInfo source_position;
135 if (latest_source_info_.is_valid()) {
136 // Statement positions need to be emitted immediately. Expression
137 // positions can be pushed back until a bytecode is found that can
138 // throw (if expression position filtering is turned on). We only
139 // invalidate the existing source position information if it is used.
140 if (latest_source_info_.is_statement() ||
141 !FLAG_ignition_filter_expression_positions ||
142 !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
143 source_position = latest_source_info_;
144 latest_source_info_.set_invalid();
145 }
146 }
147 return source_position;
148 }
149
SetDeferredSourceInfo(BytecodeSourceInfo source_info)150 void BytecodeArrayBuilder::SetDeferredSourceInfo(
151 BytecodeSourceInfo source_info) {
152 if (!source_info.is_valid()) return;
153 deferred_source_info_ = source_info;
154 }
155
AttachOrEmitDeferredSourceInfo(BytecodeNode * node)156 void BytecodeArrayBuilder::AttachOrEmitDeferredSourceInfo(BytecodeNode* node) {
157 if (!deferred_source_info_.is_valid()) return;
158 if (!node->source_info().is_valid()) {
159 node->set_source_info(deferred_source_info_);
160 } else if (deferred_source_info_.is_statement() &&
161 node->source_info().is_expression()) {
162 BytecodeSourceInfo source_position = node->source_info();
163 source_position.MakeStatementPosition(source_position.source_position());
164 node->set_source_info(source_position);
165 }
166 deferred_source_info_.set_invalid();
167 }
168
Write(BytecodeNode * node)169 void BytecodeArrayBuilder::Write(BytecodeNode* node) {
170 AttachOrEmitDeferredSourceInfo(node);
171 bytecode_array_writer_.Write(node);
172 }
173
WriteJump(BytecodeNode * node,BytecodeLabel * label)174 void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
175 AttachOrEmitDeferredSourceInfo(node);
176 bytecode_array_writer_.WriteJump(node, label);
177 }
178
WriteJumpLoop(BytecodeNode * node,BytecodeLoopHeader * loop_header)179 void BytecodeArrayBuilder::WriteJumpLoop(BytecodeNode* node,
180 BytecodeLoopHeader* loop_header) {
181 AttachOrEmitDeferredSourceInfo(node);
182 bytecode_array_writer_.WriteJumpLoop(node, loop_header);
183 }
184
WriteSwitch(BytecodeNode * node,BytecodeJumpTable * jump_table)185 void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node,
186 BytecodeJumpTable* jump_table) {
187 AttachOrEmitDeferredSourceInfo(node);
188 bytecode_array_writer_.WriteSwitch(node, jump_table);
189 }
190
OutputLdarRaw(Register reg)191 void BytecodeArrayBuilder::OutputLdarRaw(Register reg) {
192 uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
193 BytecodeNode node(BytecodeNode::Ldar(BytecodeSourceInfo(), operand));
194 Write(&node);
195 }
196
OutputStarRaw(Register reg)197 void BytecodeArrayBuilder::OutputStarRaw(Register reg) {
198 uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
199 base::Optional<Bytecode> short_code = reg.TryToShortStar();
200 BytecodeNode node = short_code
201 ? BytecodeNode(*short_code)
202 : BytecodeNode::Star(BytecodeSourceInfo(), operand);
203 Write(&node);
204 }
205
OutputMovRaw(Register src,Register dest)206 void BytecodeArrayBuilder::OutputMovRaw(Register src, Register dest) {
207 uint32_t operand0 = static_cast<uint32_t>(src.ToOperand());
208 uint32_t operand1 = static_cast<uint32_t>(dest.ToOperand());
209 BytecodeNode node(
210 BytecodeNode::Mov(BytecodeSourceInfo(), operand0, operand1));
211 Write(&node);
212 }
213
214 namespace {
215
216 template <OperandTypeInfo type_info>
217 class UnsignedOperandHelper {
218 public:
Convert(BytecodeArrayBuilder * builder,size_t value)219 V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
220 size_t value) {
221 DCHECK(IsValid(value));
222 return static_cast<uint32_t>(value);
223 }
224
Convert(BytecodeArrayBuilder * builder,int value)225 V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
226 DCHECK_GE(value, 0);
227 return Convert(builder, static_cast<size_t>(value));
228 }
229
230 private:
IsValid(size_t value)231 static bool IsValid(size_t value) {
232 switch (type_info) {
233 case OperandTypeInfo::kFixedUnsignedByte:
234 return value <= kMaxUInt8;
235 case OperandTypeInfo::kFixedUnsignedShort:
236 return value <= kMaxUInt16;
237 case OperandTypeInfo::kScalableUnsignedByte:
238 return value <= kMaxUInt32;
239 default:
240 UNREACHABLE();
241 }
242 }
243 };
244
245 template <OperandType>
246 class OperandHelper {};
247
248 #define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \
249 template <> \
250 class OperandHelper<OperandType::k##Name> \
251 : public UnsignedOperandHelper<Type> {};
252 UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
253 UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
254 #undef DEFINE_UNSIGNED_OPERAND_HELPER
255
256 template <>
257 class OperandHelper<OperandType::kImm> {
258 public:
Convert(BytecodeArrayBuilder * builder,int value)259 V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
260 return static_cast<uint32_t>(value);
261 }
262 };
263
264 template <>
265 class OperandHelper<OperandType::kReg> {
266 public:
Convert(BytecodeArrayBuilder * builder,Register reg)267 V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
268 Register reg) {
269 return builder->GetInputRegisterOperand(reg);
270 }
271 };
272
273 template <>
274 class OperandHelper<OperandType::kRegList> {
275 public:
Convert(BytecodeArrayBuilder * builder,RegisterList reg_list)276 V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
277 RegisterList reg_list) {
278 return builder->GetInputRegisterListOperand(reg_list);
279 }
280 };
281
282 template <>
283 class OperandHelper<OperandType::kRegPair> {
284 public:
Convert(BytecodeArrayBuilder * builder,RegisterList reg_list)285 V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
286 RegisterList reg_list) {
287 DCHECK_EQ(reg_list.register_count(), 2);
288 return builder->GetInputRegisterListOperand(reg_list);
289 }
290 };
291
292 template <>
293 class OperandHelper<OperandType::kRegOut> {
294 public:
Convert(BytecodeArrayBuilder * builder,Register reg)295 V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
296 Register reg) {
297 return builder->GetOutputRegisterOperand(reg);
298 }
299 };
300
301 template <>
302 class OperandHelper<OperandType::kRegOutList> {
303 public:
Convert(BytecodeArrayBuilder * builder,RegisterList reg_list)304 V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
305 RegisterList reg_list) {
306 return builder->GetOutputRegisterListOperand(reg_list);
307 }
308 };
309
310 template <>
311 class OperandHelper<OperandType::kRegOutPair> {
312 public:
Convert(BytecodeArrayBuilder * builder,RegisterList reg_list)313 V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
314 RegisterList reg_list) {
315 DCHECK_EQ(2, reg_list.register_count());
316 return builder->GetOutputRegisterListOperand(reg_list);
317 }
318 };
319
320 template <>
321 class OperandHelper<OperandType::kRegOutTriple> {
322 public:
Convert(BytecodeArrayBuilder * builder,RegisterList reg_list)323 V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
324 RegisterList reg_list) {
325 DCHECK_EQ(3, reg_list.register_count());
326 return builder->GetOutputRegisterListOperand(reg_list);
327 }
328 };
329
330 } // namespace
331
332 template <Bytecode bytecode, ImplicitRegisterUse implicit_register_use,
333 OperandType... operand_types>
334 class BytecodeNodeBuilder {
335 public:
336 template <typename... Operands>
Make(BytecodeArrayBuilder * builder,Operands...operands)337 V8_INLINE static BytecodeNode Make(BytecodeArrayBuilder* builder,
338 Operands... operands) {
339 static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands,
340 "too many operands for bytecode");
341 builder->PrepareToOutputBytecode<bytecode, implicit_register_use>();
342 // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
343 // expand both the OperandType... and Operands... parameter packs e.g. for:
344 // BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
345 // Register, int>(..., Register reg, int immediate)
346 // the code will expand into:
347 // OperandHelper<OperandType::kReg>::Convert(builder, reg),
348 // OperandHelper<OperandType::kImm>::Convert(builder, immediate),
349 return BytecodeNode::Create<bytecode, implicit_register_use,
350 operand_types...>(
351 builder->CurrentSourcePosition(bytecode),
352 OperandHelper<operand_types>::Convert(builder, operands)...);
353 }
354 };
355
356 #define DEFINE_BYTECODE_OUTPUT(name, ...) \
357 template <typename... Operands> \
358 BytecodeNode BytecodeArrayBuilder::Create##name##Node( \
359 Operands... operands) { \
360 return BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make( \
361 this, operands...); \
362 } \
363 \
364 template <typename... Operands> \
365 void BytecodeArrayBuilder::Output##name(Operands... operands) { \
366 BytecodeNode node(Create##name##Node(operands...)); \
367 Write(&node); \
368 } \
369 \
370 template <typename... Operands> \
371 void BytecodeArrayBuilder::Output##name(BytecodeLabel* label, \
372 Operands... operands) { \
373 DCHECK(Bytecodes::IsForwardJump(Bytecode::k##name)); \
374 BytecodeNode node(Create##name##Node(operands...)); \
375 WriteJump(&node, label); \
376 }
BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)377 BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
378 #undef DEFINE_BYTECODE_OUTPUT
379
380 void BytecodeArrayBuilder::OutputJumpLoop(BytecodeLoopHeader* loop_header,
381 int loop_depth) {
382 BytecodeNode node(CreateJumpLoopNode(0, loop_depth));
383 WriteJumpLoop(&node, loop_header);
384 }
385
OutputSwitchOnSmiNoFeedback(BytecodeJumpTable * jump_table)386 void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback(
387 BytecodeJumpTable* jump_table) {
388 BytecodeNode node(CreateSwitchOnSmiNoFeedbackNode(
389 jump_table->constant_pool_index(), jump_table->size(),
390 jump_table->case_value_base()));
391 WriteSwitch(&node, jump_table);
392 }
393
BinaryOperation(Token::Value op,Register reg,int feedback_slot)394 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
395 Register reg,
396 int feedback_slot) {
397 switch (op) {
398 case Token::Value::ADD:
399 OutputAdd(reg, feedback_slot);
400 break;
401 case Token::Value::SUB:
402 OutputSub(reg, feedback_slot);
403 break;
404 case Token::Value::MUL:
405 OutputMul(reg, feedback_slot);
406 break;
407 case Token::Value::DIV:
408 OutputDiv(reg, feedback_slot);
409 break;
410 case Token::Value::MOD:
411 OutputMod(reg, feedback_slot);
412 break;
413 case Token::Value::EXP:
414 OutputExp(reg, feedback_slot);
415 break;
416 case Token::Value::BIT_OR:
417 OutputBitwiseOr(reg, feedback_slot);
418 break;
419 case Token::Value::BIT_XOR:
420 OutputBitwiseXor(reg, feedback_slot);
421 break;
422 case Token::Value::BIT_AND:
423 OutputBitwiseAnd(reg, feedback_slot);
424 break;
425 case Token::Value::SHL:
426 OutputShiftLeft(reg, feedback_slot);
427 break;
428 case Token::Value::SAR:
429 OutputShiftRight(reg, feedback_slot);
430 break;
431 case Token::Value::SHR:
432 OutputShiftRightLogical(reg, feedback_slot);
433 break;
434 default:
435 UNREACHABLE();
436 }
437 return *this;
438 }
439
BinaryOperationSmiLiteral(Token::Value op,Smi literal,int feedback_slot)440 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
441 Token::Value op, Smi literal, int feedback_slot) {
442 switch (op) {
443 case Token::Value::ADD:
444 OutputAddSmi(literal.value(), feedback_slot);
445 break;
446 case Token::Value::SUB:
447 OutputSubSmi(literal.value(), feedback_slot);
448 break;
449 case Token::Value::MUL:
450 OutputMulSmi(literal.value(), feedback_slot);
451 break;
452 case Token::Value::DIV:
453 OutputDivSmi(literal.value(), feedback_slot);
454 break;
455 case Token::Value::MOD:
456 OutputModSmi(literal.value(), feedback_slot);
457 break;
458 case Token::Value::EXP:
459 OutputExpSmi(literal.value(), feedback_slot);
460 break;
461 case Token::Value::BIT_OR:
462 OutputBitwiseOrSmi(literal.value(), feedback_slot);
463 break;
464 case Token::Value::BIT_XOR:
465 OutputBitwiseXorSmi(literal.value(), feedback_slot);
466 break;
467 case Token::Value::BIT_AND:
468 OutputBitwiseAndSmi(literal.value(), feedback_slot);
469 break;
470 case Token::Value::SHL:
471 OutputShiftLeftSmi(literal.value(), feedback_slot);
472 break;
473 case Token::Value::SAR:
474 OutputShiftRightSmi(literal.value(), feedback_slot);
475 break;
476 case Token::Value::SHR:
477 OutputShiftRightLogicalSmi(literal.value(), feedback_slot);
478 break;
479 default:
480 UNREACHABLE();
481 }
482 return *this;
483 }
484
UnaryOperation(Token::Value op,int feedback_slot)485 BytecodeArrayBuilder& BytecodeArrayBuilder::UnaryOperation(Token::Value op,
486 int feedback_slot) {
487 switch (op) {
488 case Token::Value::INC:
489 OutputInc(feedback_slot);
490 break;
491 case Token::Value::DEC:
492 OutputDec(feedback_slot);
493 break;
494 case Token::Value::ADD:
495 OutputToNumber(feedback_slot);
496 break;
497 case Token::Value::SUB:
498 OutputNegate(feedback_slot);
499 break;
500 case Token::Value::BIT_NOT:
501 OutputBitwiseNot(feedback_slot);
502 break;
503 default:
504 UNREACHABLE();
505 }
506 return *this;
507 }
508
LogicalNot(ToBooleanMode mode)509 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
510 if (mode == ToBooleanMode::kAlreadyBoolean) {
511 OutputLogicalNot();
512 } else {
513 DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
514 OutputToBooleanLogicalNot();
515 }
516 return *this;
517 }
518
TypeOf()519 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
520 OutputTypeOf();
521 return *this;
522 }
523
GetSuperConstructor(Register out)524 BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
525 OutputGetSuperConstructor(out);
526 return *this;
527 }
528
CompareOperation(Token::Value op,Register reg,int feedback_slot)529 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
530 Token::Value op, Register reg, int feedback_slot) {
531 switch (op) {
532 case Token::Value::EQ:
533 OutputTestEqual(reg, feedback_slot);
534 break;
535 case Token::Value::EQ_STRICT:
536 OutputTestEqualStrict(reg, feedback_slot);
537 break;
538 case Token::Value::LT:
539 OutputTestLessThan(reg, feedback_slot);
540 break;
541 case Token::Value::GT:
542 OutputTestGreaterThan(reg, feedback_slot);
543 break;
544 case Token::Value::LTE:
545 OutputTestLessThanOrEqual(reg, feedback_slot);
546 break;
547 case Token::Value::GTE:
548 OutputTestGreaterThanOrEqual(reg, feedback_slot);
549 break;
550 case Token::Value::INSTANCEOF:
551 OutputTestInstanceOf(reg, feedback_slot);
552 break;
553 case Token::Value::IN:
554 OutputTestIn(reg, feedback_slot);
555 break;
556 default:
557 UNREACHABLE();
558 }
559 return *this;
560 }
561
CompareReference(Register reg)562 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareReference(Register reg) {
563 OutputTestReferenceEqual(reg);
564 return *this;
565 }
566
CompareUndetectable()567 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndetectable() {
568 OutputTestUndetectable();
569 return *this;
570 }
571
CompareUndefined()572 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndefined() {
573 OutputTestUndefined();
574 return *this;
575 }
576
CompareNull()577 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNull() {
578 OutputTestNull();
579 return *this;
580 }
581
CompareNil(Token::Value op,NilValue nil)582 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNil(Token::Value op,
583 NilValue nil) {
584 if (op == Token::EQ) {
585 return CompareUndetectable();
586 } else {
587 DCHECK_EQ(Token::EQ_STRICT, op);
588 if (nil == kUndefinedValue) {
589 return CompareUndefined();
590 } else {
591 DCHECK_EQ(kNullValue, nil);
592 return CompareNull();
593 }
594 }
595 }
596
CompareTypeOf(TestTypeOfFlags::LiteralFlag literal_flag)597 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
598 TestTypeOfFlags::LiteralFlag literal_flag) {
599 DCHECK_NE(literal_flag, TestTypeOfFlags::LiteralFlag::kOther);
600 OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
601 return *this;
602 }
603
LoadConstantPoolEntry(size_t entry)604 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
605 size_t entry) {
606 OutputLdaConstant(entry);
607 return *this;
608 }
609
LoadLiteral(Smi smi)610 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Smi smi) {
611 int32_t raw_smi = smi.value();
612 if (raw_smi == 0) {
613 OutputLdaZero();
614 } else {
615 OutputLdaSmi(raw_smi);
616 }
617 return *this;
618 }
619
LoadLiteral(double value)620 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(double value) {
621 // If we can encode the value as a Smi, we should.
622 int smi;
623 if (DoubleToSmiInteger(value, &smi)) {
624 LoadLiteral(Smi::FromInt(smi));
625 } else {
626 size_t entry = GetConstantPoolEntry(value);
627 OutputLdaConstant(entry);
628 }
629 return *this;
630 }
631
LoadLiteral(const AstRawString * raw_string)632 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
633 const AstRawString* raw_string) {
634 size_t entry = GetConstantPoolEntry(raw_string);
635 OutputLdaConstant(entry);
636 return *this;
637 }
638
LoadLiteral(const Scope * scope)639 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(const Scope* scope) {
640 size_t entry = GetConstantPoolEntry(scope);
641 OutputLdaConstant(entry);
642 return *this;
643 }
644
LoadLiteral(AstBigInt bigint)645 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstBigInt bigint) {
646 size_t entry = GetConstantPoolEntry(bigint);
647 OutputLdaConstant(entry);
648 return *this;
649 }
650
LoadUndefined()651 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
652 OutputLdaUndefined();
653 return *this;
654 }
655
LoadNull()656 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
657 OutputLdaNull();
658 return *this;
659 }
660
LoadTheHole()661 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
662 OutputLdaTheHole();
663 return *this;
664 }
665
LoadTrue()666 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
667 OutputLdaTrue();
668 return *this;
669 }
670
LoadFalse()671 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
672 OutputLdaFalse();
673 return *this;
674 }
675
LoadBoolean(bool value)676 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBoolean(bool value) {
677 return value ? LoadTrue() : LoadFalse();
678 }
679
LoadAccumulatorWithRegister(Register reg)680 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
681 Register reg) {
682 if (register_optimizer_) {
683 // Defer source info so that if we elide the bytecode transfer, we attach
684 // the source info to a subsequent bytecode if it exists.
685 SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kLdar));
686 register_optimizer_->DoLdar(reg);
687 } else {
688 OutputLdar(reg);
689 }
690 return *this;
691 }
692
StoreAccumulatorInRegister(Register reg)693 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
694 Register reg) {
695 if (register_optimizer_) {
696 // Defer source info so that if we elide the bytecode transfer, we attach
697 // the source info to a subsequent bytecode if it exists.
698 SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kStar));
699 register_optimizer_->DoStar(reg);
700 } else {
701 OutputStarRaw(reg);
702 }
703 return *this;
704 }
705
MoveRegister(Register from,Register to)706 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
707 Register to) {
708 DCHECK(from != to);
709 if (register_optimizer_) {
710 // Defer source info so that if we elide the bytecode transfer, we attach
711 // the source info to a subsequent bytecode if it exists.
712 SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kMov));
713 register_optimizer_->DoMov(from, to);
714 } else {
715 OutputMov(from, to);
716 }
717 return *this;
718 }
719
LoadGlobal(const AstRawString * name,int feedback_slot,TypeofMode typeof_mode)720 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(const AstRawString* name,
721 int feedback_slot,
722 TypeofMode typeof_mode) {
723 size_t name_index = GetConstantPoolEntry(name);
724 // Ensure that typeof mode is in sync with the IC slot kind.
725 DCHECK_EQ(GetTypeofModeFromSlotKind(feedback_vector_spec()->GetKind(
726 FeedbackVector::ToSlot(feedback_slot))),
727 typeof_mode);
728 switch (typeof_mode) {
729 case TypeofMode::kInside:
730 OutputLdaGlobalInsideTypeof(name_index, feedback_slot);
731 break;
732 case TypeofMode::kNotInside:
733 OutputLdaGlobal(name_index, feedback_slot);
734 break;
735 }
736 return *this;
737 }
738
StoreGlobal(const AstRawString * name,int feedback_slot)739 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
740 const AstRawString* name, int feedback_slot) {
741 size_t name_index = GetConstantPoolEntry(name);
742 OutputStaGlobal(name_index, feedback_slot);
743 return *this;
744 }
745
LoadContextSlot(Register context,int slot_index,int depth,ContextSlotMutability mutability)746 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
747 Register context, int slot_index, int depth,
748 ContextSlotMutability mutability) {
749 if (context.is_current_context() && depth == 0) {
750 if (mutability == kImmutableSlot) {
751 OutputLdaImmutableCurrentContextSlot(slot_index);
752 } else {
753 DCHECK_EQ(kMutableSlot, mutability);
754 OutputLdaCurrentContextSlot(slot_index);
755 }
756 } else if (mutability == kImmutableSlot) {
757 OutputLdaImmutableContextSlot(context, slot_index, depth);
758 } else {
759 DCHECK_EQ(mutability, kMutableSlot);
760 OutputLdaContextSlot(context, slot_index, depth);
761 }
762 return *this;
763 }
764
StoreContextSlot(Register context,int slot_index,int depth)765 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
766 int slot_index,
767 int depth) {
768 if (context.is_current_context() && depth == 0) {
769 OutputStaCurrentContextSlot(slot_index);
770 } else {
771 OutputStaContextSlot(context, slot_index, depth);
772 }
773 return *this;
774 }
775
LoadLookupSlot(const AstRawString * name,TypeofMode typeof_mode)776 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
777 const AstRawString* name, TypeofMode typeof_mode) {
778 size_t name_index = GetConstantPoolEntry(name);
779 switch (typeof_mode) {
780 case TypeofMode::kInside:
781 OutputLdaLookupSlotInsideTypeof(name_index);
782 break;
783 case TypeofMode::kNotInside:
784 OutputLdaLookupSlot(name_index);
785 break;
786 }
787 return *this;
788 }
789
LoadLookupContextSlot(const AstRawString * name,TypeofMode typeof_mode,int slot_index,int depth)790 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
791 const AstRawString* name, TypeofMode typeof_mode, int slot_index,
792 int depth) {
793 size_t name_index = GetConstantPoolEntry(name);
794 switch (typeof_mode) {
795 case TypeofMode::kInside:
796 OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
797 break;
798 case TypeofMode::kNotInside:
799 OutputLdaLookupContextSlot(name_index, slot_index, depth);
800 break;
801 }
802 return *this;
803 }
804
LoadLookupGlobalSlot(const AstRawString * name,TypeofMode typeof_mode,int feedback_slot,int depth)805 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
806 const AstRawString* name, TypeofMode typeof_mode, int feedback_slot,
807 int depth) {
808 size_t name_index = GetConstantPoolEntry(name);
809 switch (typeof_mode) {
810 case TypeofMode::kInside:
811 OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth);
812 break;
813 case TypeofMode::kNotInside:
814 OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth);
815 break;
816 }
817 return *this;
818 }
819
StoreLookupSlot(const AstRawString * name,LanguageMode language_mode,LookupHoistingMode lookup_hoisting_mode)820 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
821 const AstRawString* name, LanguageMode language_mode,
822 LookupHoistingMode lookup_hoisting_mode) {
823 size_t name_index = GetConstantPoolEntry(name);
824 uint8_t flags =
825 StoreLookupSlotFlags::Encode(language_mode, lookup_hoisting_mode);
826 OutputStaLookupSlot(name_index, flags);
827 return *this;
828 }
829
LoadNamedProperty(Register object,const AstRawString * name,int feedback_slot)830 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
831 Register object, const AstRawString* name, int feedback_slot) {
832 size_t name_index = GetConstantPoolEntry(name);
833 OutputGetNamedProperty(object, name_index, feedback_slot);
834 return *this;
835 }
836
LoadNamedPropertyFromSuper(Register object,const AstRawString * name,int feedback_slot)837 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyFromSuper(
838 Register object, const AstRawString* name, int feedback_slot) {
839 size_t name_index = GetConstantPoolEntry(name);
840 OutputGetNamedPropertyFromSuper(object, name_index, feedback_slot);
841 return *this;
842 }
843
LoadKeyedProperty(Register object,int feedback_slot)844 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
845 Register object, int feedback_slot) {
846 OutputGetKeyedProperty(object, feedback_slot);
847 return *this;
848 }
849
LoadIteratorProperty(Register object,int feedback_slot)850 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
851 Register object, int feedback_slot) {
852 size_t name_index = IteratorSymbolConstantPoolEntry();
853 OutputGetNamedProperty(object, name_index, feedback_slot);
854 return *this;
855 }
856
GetIterator(Register object,int load_feedback_slot,int call_feedback_slot)857 BytecodeArrayBuilder& BytecodeArrayBuilder::GetIterator(
858 Register object, int load_feedback_slot, int call_feedback_slot) {
859 OutputGetIterator(object, load_feedback_slot, call_feedback_slot);
860 return *this;
861 }
862
LoadAsyncIteratorProperty(Register object,int feedback_slot)863 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
864 Register object, int feedback_slot) {
865 size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
866 OutputGetNamedProperty(object, name_index, feedback_slot);
867 return *this;
868 }
869
DefineKeyedOwnPropertyInLiteral(Register object,Register name,DefineKeyedOwnPropertyInLiteralFlags flags,int feedback_slot)870 BytecodeArrayBuilder& BytecodeArrayBuilder::DefineKeyedOwnPropertyInLiteral(
871 Register object, Register name, DefineKeyedOwnPropertyInLiteralFlags flags,
872 int feedback_slot) {
873 OutputDefineKeyedOwnPropertyInLiteral(object, name, flags, feedback_slot);
874 return *this;
875 }
876
CollectTypeProfile(int position)877 BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
878 OutputCollectTypeProfile(position);
879 return *this;
880 }
881
SetNamedProperty(Register object,size_t name_index,int feedback_slot,LanguageMode language_mode)882 BytecodeArrayBuilder& BytecodeArrayBuilder::SetNamedProperty(
883 Register object, size_t name_index, int feedback_slot,
884 LanguageMode language_mode) {
885 // Ensure that language mode is in sync with the IC slot kind.
886 DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
887 FeedbackVector::ToSlot(feedback_slot))),
888 language_mode);
889 OutputSetNamedProperty(object, name_index, feedback_slot);
890 return *this;
891 }
892
SetNamedProperty(Register object,const AstRawString * name,int feedback_slot,LanguageMode language_mode)893 BytecodeArrayBuilder& BytecodeArrayBuilder::SetNamedProperty(
894 Register object, const AstRawString* name, int feedback_slot,
895 LanguageMode language_mode) {
896 size_t name_index = GetConstantPoolEntry(name);
897 return SetNamedProperty(object, name_index, feedback_slot, language_mode);
898 }
899
DefineNamedOwnProperty(Register object,const AstRawString * name,int feedback_slot)900 BytecodeArrayBuilder& BytecodeArrayBuilder::DefineNamedOwnProperty(
901 Register object, const AstRawString* name, int feedback_slot) {
902 size_t name_index = GetConstantPoolEntry(name);
903 // Ensure that the store operation is in sync with the IC slot kind.
904 DCHECK_EQ(
905 FeedbackSlotKind::kDefineNamedOwn,
906 feedback_vector_spec()->GetKind(FeedbackVector::ToSlot(feedback_slot)));
907 OutputDefineNamedOwnProperty(object, name_index, feedback_slot);
908 return *this;
909 }
910
SetKeyedProperty(Register object,Register key,int feedback_slot,LanguageMode language_mode)911 BytecodeArrayBuilder& BytecodeArrayBuilder::SetKeyedProperty(
912 Register object, Register key, int feedback_slot,
913 LanguageMode language_mode) {
914 // Ensure that language mode is in sync with the IC slot kind.
915 DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
916 FeedbackVector::ToSlot(feedback_slot))),
917 language_mode);
918 OutputSetKeyedProperty(object, key, feedback_slot);
919 return *this;
920 }
921
DefineKeyedOwnProperty(Register object,Register key,int feedback_slot)922 BytecodeArrayBuilder& BytecodeArrayBuilder::DefineKeyedOwnProperty(
923 Register object, Register key, int feedback_slot) {
924 // Ensure that the IC uses a strict language mode, as this is the only
925 // supported mode for this use case.
926 DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
927 FeedbackVector::ToSlot(feedback_slot))),
928 LanguageMode::kStrict);
929 OutputDefineKeyedOwnProperty(object, key, feedback_slot);
930 return *this;
931 }
932
StoreInArrayLiteral(Register array,Register index,int feedback_slot)933 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreInArrayLiteral(
934 Register array, Register index, int feedback_slot) {
935 OutputStaInArrayLiteral(array, index, feedback_slot);
936 return *this;
937 }
938
StoreClassFieldsInitializer(Register constructor,int feedback_slot)939 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreClassFieldsInitializer(
940 Register constructor, int feedback_slot) {
941 size_t name_index = ClassFieldsSymbolConstantPoolEntry();
942 return SetNamedProperty(constructor, name_index, feedback_slot,
943 LanguageMode::kStrict);
944 }
945
LoadClassFieldsInitializer(Register constructor,int feedback_slot)946 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadClassFieldsInitializer(
947 Register constructor, int feedback_slot) {
948 size_t name_index = ClassFieldsSymbolConstantPoolEntry();
949 OutputGetNamedProperty(constructor, name_index, feedback_slot);
950 return *this;
951 }
952
CreateClosure(size_t shared_function_info_entry,int slot,int flags)953 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
954 size_t shared_function_info_entry, int slot, int flags) {
955 OutputCreateClosure(shared_function_info_entry, slot, flags);
956 return *this;
957 }
958
CreateBlockContext(const Scope * scope)959 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
960 const Scope* scope) {
961 size_t entry = GetConstantPoolEntry(scope);
962 OutputCreateBlockContext(entry);
963 return *this;
964 }
965
CreateCatchContext(Register exception,const Scope * scope)966 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
967 Register exception, const Scope* scope) {
968 size_t scope_index = GetConstantPoolEntry(scope);
969 OutputCreateCatchContext(exception, scope_index);
970 return *this;
971 }
972
CreateFunctionContext(const Scope * scope,int slots)973 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(
974 const Scope* scope, int slots) {
975 size_t scope_index = GetConstantPoolEntry(scope);
976 OutputCreateFunctionContext(scope_index, slots);
977 return *this;
978 }
979
CreateEvalContext(const Scope * scope,int slots)980 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(
981 const Scope* scope, int slots) {
982 size_t scope_index = GetConstantPoolEntry(scope);
983 OutputCreateEvalContext(scope_index, slots);
984 return *this;
985 }
986
CreateWithContext(Register object,const Scope * scope)987 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
988 Register object, const Scope* scope) {
989 size_t scope_index = GetConstantPoolEntry(scope);
990 OutputCreateWithContext(object, scope_index);
991 return *this;
992 }
993
CreateArguments(CreateArgumentsType type)994 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
995 CreateArgumentsType type) {
996 switch (type) {
997 case CreateArgumentsType::kMappedArguments:
998 OutputCreateMappedArguments();
999 break;
1000 case CreateArgumentsType::kUnmappedArguments:
1001 OutputCreateUnmappedArguments();
1002 break;
1003 case CreateArgumentsType::kRestParameter:
1004 OutputCreateRestParameter();
1005 break;
1006 default:
1007 UNREACHABLE();
1008 }
1009 return *this;
1010 }
1011
CreateRegExpLiteral(const AstRawString * pattern,int literal_index,int flags)1012 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
1013 const AstRawString* pattern, int literal_index, int flags) {
1014 size_t pattern_entry = GetConstantPoolEntry(pattern);
1015 OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
1016 return *this;
1017 }
1018
CreateEmptyArrayLiteral(int literal_index)1019 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyArrayLiteral(
1020 int literal_index) {
1021 OutputCreateEmptyArrayLiteral(literal_index);
1022 return *this;
1023 }
1024
CreateArrayLiteral(size_t constant_elements_entry,int literal_index,int flags)1025 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
1026 size_t constant_elements_entry, int literal_index, int flags) {
1027 OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
1028 return *this;
1029 }
1030
CreateArrayFromIterable()1031 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayFromIterable() {
1032 OutputCreateArrayFromIterable();
1033 return *this;
1034 }
1035
CreateObjectLiteral(size_t constant_properties_entry,int literal_index,int flags)1036 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
1037 size_t constant_properties_entry, int literal_index, int flags) {
1038 OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags);
1039 return *this;
1040 }
1041
CreateEmptyObjectLiteral()1042 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyObjectLiteral() {
1043 OutputCreateEmptyObjectLiteral();
1044 return *this;
1045 }
1046
CloneObject(Register source,int flags,int feedback_slot)1047 BytecodeArrayBuilder& BytecodeArrayBuilder::CloneObject(Register source,
1048 int flags,
1049 int feedback_slot) {
1050 OutputCloneObject(source, flags, feedback_slot);
1051 return *this;
1052 }
1053
GetTemplateObject(size_t template_object_description_entry,int feedback_slot)1054 BytecodeArrayBuilder& BytecodeArrayBuilder::GetTemplateObject(
1055 size_t template_object_description_entry, int feedback_slot) {
1056 OutputGetTemplateObject(template_object_description_entry, feedback_slot);
1057 return *this;
1058 }
1059
PushContext(Register context)1060 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
1061 OutputPushContext(context);
1062 return *this;
1063 }
1064
PopContext(Register context)1065 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
1066 OutputPopContext(context);
1067 return *this;
1068 }
1069
ToObject(Register out)1070 BytecodeArrayBuilder& BytecodeArrayBuilder::ToObject(Register out) {
1071 OutputToObject(out);
1072 return *this;
1073 }
1074
ToName(Register out)1075 BytecodeArrayBuilder& BytecodeArrayBuilder::ToName(Register out) {
1076 OutputToName(out);
1077 return *this;
1078 }
1079
ToString()1080 BytecodeArrayBuilder& BytecodeArrayBuilder::ToString() {
1081 OutputToString();
1082 return *this;
1083 }
1084
ToNumber(int feedback_slot)1085 BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumber(int feedback_slot) {
1086 OutputToNumber(feedback_slot);
1087 return *this;
1088 }
1089
ToNumeric(int feedback_slot)1090 BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(int feedback_slot) {
1091 OutputToNumeric(feedback_slot);
1092 return *this;
1093 }
1094
Bind(BytecodeLabel * label)1095 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
1096 // Don't generate code for a label which hasn't had a corresponding forward
1097 // jump generated already. For backwards jumps, use BindLoopHeader.
1098 if (!label->has_referrer_jump()) return *this;
1099
1100 // Flush the register optimizer when binding a label to ensure all
1101 // expected registers are valid when jumping to this label.
1102 if (register_optimizer_) register_optimizer_->Flush();
1103 bytecode_array_writer_.BindLabel(label);
1104 return *this;
1105 }
1106
Bind(BytecodeLoopHeader * loop_header)1107 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(
1108 BytecodeLoopHeader* loop_header) {
1109 // Flush the register optimizer when starting a loop to ensure all expected
1110 // registers are valid when jumping to the loop header.
1111 if (register_optimizer_) register_optimizer_->Flush();
1112 bytecode_array_writer_.BindLoopHeader(loop_header);
1113 return *this;
1114 }
1115
Bind(BytecodeJumpTable * jump_table,int case_value)1116 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeJumpTable* jump_table,
1117 int case_value) {
1118 // Flush the register optimizer when binding a jump table entry to ensure
1119 // all expected registers are valid when jumping to this location.
1120 if (register_optimizer_) register_optimizer_->Flush();
1121 bytecode_array_writer_.BindJumpTableEntry(jump_table, case_value);
1122 return *this;
1123 }
1124
MarkHandler(int handler_id,HandlerTable::CatchPrediction catch_prediction)1125 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
1126 int handler_id, HandlerTable::CatchPrediction catch_prediction) {
1127 // The handler starts a new basic block, and any reasonable try block won't
1128 // let control fall through into it.
1129 DCHECK_IMPLIES(register_optimizer_,
1130 register_optimizer_->EnsureAllRegistersAreFlushed());
1131 bytecode_array_writer_.BindHandlerTarget(handler_table_builder(), handler_id);
1132 handler_table_builder()->SetPrediction(handler_id, catch_prediction);
1133 return *this;
1134 }
1135
MarkTryBegin(int handler_id,Register context)1136 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
1137 Register context) {
1138 // Flush registers to make sure everything visible to the handler is
1139 // materialized.
1140 if (register_optimizer_) register_optimizer_->Flush();
1141 bytecode_array_writer_.BindTryRegionStart(handler_table_builder(),
1142 handler_id);
1143 handler_table_builder()->SetContextRegister(handler_id, context);
1144 return *this;
1145 }
1146
MarkTryEnd(int handler_id)1147 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
1148 bytecode_array_writer_.BindTryRegionEnd(handler_table_builder(), handler_id);
1149 return *this;
1150 }
1151
Jump(BytecodeLabel * label)1152 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
1153 DCHECK(!label->is_bound());
1154 OutputJump(label, 0);
1155 return *this;
1156 }
1157
JumpIfTrue(ToBooleanMode mode,BytecodeLabel * label)1158 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
1159 BytecodeLabel* label) {
1160 DCHECK(!label->is_bound());
1161 if (mode == ToBooleanMode::kAlreadyBoolean) {
1162 OutputJumpIfTrue(label, 0);
1163 } else {
1164 DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1165 OutputJumpIfToBooleanTrue(label, 0);
1166 }
1167 return *this;
1168 }
1169
JumpIfFalse(ToBooleanMode mode,BytecodeLabel * label)1170 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
1171 BytecodeLabel* label) {
1172 DCHECK(!label->is_bound());
1173 if (mode == ToBooleanMode::kAlreadyBoolean) {
1174 OutputJumpIfFalse(label, 0);
1175 } else {
1176 DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1177 OutputJumpIfToBooleanFalse(label, 0);
1178 }
1179 return *this;
1180 }
1181
JumpIfNull(BytecodeLabel * label)1182 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
1183 DCHECK(!label->is_bound());
1184 OutputJumpIfNull(label, 0);
1185 return *this;
1186 }
1187
JumpIfNotNull(BytecodeLabel * label)1188 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
1189 BytecodeLabel* label) {
1190 DCHECK(!label->is_bound());
1191 OutputJumpIfNotNull(label, 0);
1192 return *this;
1193 }
1194
JumpIfUndefined(BytecodeLabel * label)1195 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
1196 BytecodeLabel* label) {
1197 DCHECK(!label->is_bound());
1198 OutputJumpIfUndefined(label, 0);
1199 return *this;
1200 }
1201
JumpIfUndefinedOrNull(BytecodeLabel * label)1202 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefinedOrNull(
1203 BytecodeLabel* label) {
1204 DCHECK(!label->is_bound());
1205 OutputJumpIfUndefinedOrNull(label, 0);
1206 return *this;
1207 }
1208
JumpIfNotUndefined(BytecodeLabel * label)1209 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotUndefined(
1210 BytecodeLabel* label) {
1211 DCHECK(!label->is_bound());
1212 OutputJumpIfNotUndefined(label, 0);
1213 return *this;
1214 }
1215
JumpIfNil(BytecodeLabel * label,Token::Value op,NilValue nil)1216 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
1217 Token::Value op,
1218 NilValue nil) {
1219 if (op == Token::EQ) {
1220 // TODO(rmcilroy): Implement JumpIfUndetectable.
1221 return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
1222 label);
1223 } else {
1224 DCHECK_EQ(Token::EQ_STRICT, op);
1225 if (nil == kUndefinedValue) {
1226 return JumpIfUndefined(label);
1227 } else {
1228 DCHECK_EQ(kNullValue, nil);
1229 return JumpIfNull(label);
1230 }
1231 }
1232 }
1233
JumpIfNotNil(BytecodeLabel * label,Token::Value op,NilValue nil)1234 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
1235 Token::Value op,
1236 NilValue nil) {
1237 if (op == Token::EQ) {
1238 // TODO(rmcilroy): Implement JumpIfUndetectable.
1239 return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
1240 label);
1241 } else {
1242 DCHECK_EQ(Token::EQ_STRICT, op);
1243 if (nil == kUndefinedValue) {
1244 return JumpIfNotUndefined(label);
1245 } else {
1246 DCHECK_EQ(kNullValue, nil);
1247 return JumpIfNotNull(label);
1248 }
1249 }
1250 }
1251
JumpIfJSReceiver(BytecodeLabel * label)1252 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
1253 BytecodeLabel* label) {
1254 DCHECK(!label->is_bound());
1255 OutputJumpIfJSReceiver(label, 0);
1256 return *this;
1257 }
1258
JumpLoop(BytecodeLoopHeader * loop_header,int loop_depth,int position)1259 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(
1260 BytecodeLoopHeader* loop_header, int loop_depth, int position) {
1261 if (position != kNoSourcePosition) {
1262 // We need to attach a non-breakable source position to JumpLoop for its
1263 // implicit stack check, so we simply add it as expression position. There
1264 // can be a prior statement position from constructs like:
1265 //
1266 // do var x; while (false);
1267 //
1268 // A Nop could be inserted for empty statements, but since no code
1269 // is associated with these positions, instead we force the jump loop's
1270 // expression position which eliminates the empty statement's position.
1271 latest_source_info_.ForceExpressionPosition(position);
1272 }
1273 OutputJumpLoop(loop_header, loop_depth);
1274 return *this;
1275 }
1276
SwitchOnSmiNoFeedback(BytecodeJumpTable * jump_table)1277 BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnSmiNoFeedback(
1278 BytecodeJumpTable* jump_table) {
1279 OutputSwitchOnSmiNoFeedback(jump_table);
1280 return *this;
1281 }
1282
SetPendingMessage()1283 BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
1284 OutputSetPendingMessage();
1285 return *this;
1286 }
1287
Throw()1288 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
1289 OutputThrow();
1290 return *this;
1291 }
1292
ReThrow()1293 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
1294 OutputReThrow();
1295 return *this;
1296 }
1297
Abort(AbortReason reason)1298 BytecodeArrayBuilder& BytecodeArrayBuilder::Abort(AbortReason reason) {
1299 DCHECK_LT(reason, AbortReason::kLastErrorMessage);
1300 DCHECK_GE(reason, AbortReason::kNoReason);
1301 OutputAbort(static_cast<int>(reason));
1302 return *this;
1303 }
1304
Return()1305 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
1306 OutputReturn();
1307 return *this;
1308 }
1309
ThrowReferenceErrorIfHole(const AstRawString * name)1310 BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowReferenceErrorIfHole(
1311 const AstRawString* name) {
1312 size_t entry = GetConstantPoolEntry(name);
1313 OutputThrowReferenceErrorIfHole(entry);
1314 return *this;
1315 }
1316
ThrowSuperNotCalledIfHole()1317 BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperNotCalledIfHole() {
1318 OutputThrowSuperNotCalledIfHole();
1319 return *this;
1320 }
1321
ThrowSuperAlreadyCalledIfNotHole()1322 BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperAlreadyCalledIfNotHole() {
1323 OutputThrowSuperAlreadyCalledIfNotHole();
1324 return *this;
1325 }
1326
ThrowIfNotSuperConstructor(Register constructor)1327 BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowIfNotSuperConstructor(
1328 Register constructor) {
1329 OutputThrowIfNotSuperConstructor(constructor);
1330 return *this;
1331 }
1332
Debugger()1333 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
1334 OutputDebugger();
1335 return *this;
1336 }
1337
IncBlockCounter(int coverage_array_slot)1338 BytecodeArrayBuilder& BytecodeArrayBuilder::IncBlockCounter(
1339 int coverage_array_slot) {
1340 OutputIncBlockCounter(coverage_array_slot);
1341 return *this;
1342 }
1343
ForInEnumerate(Register receiver)1344 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInEnumerate(Register receiver) {
1345 OutputForInEnumerate(receiver);
1346 return *this;
1347 }
1348
ForInPrepare(RegisterList cache_info_triple,int feedback_slot)1349 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
1350 RegisterList cache_info_triple, int feedback_slot) {
1351 DCHECK_EQ(3, cache_info_triple.register_count());
1352 OutputForInPrepare(cache_info_triple, feedback_slot);
1353 return *this;
1354 }
1355
ForInContinue(Register index,Register cache_length)1356 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
1357 Register index, Register cache_length) {
1358 OutputForInContinue(index, cache_length);
1359 return *this;
1360 }
1361
ForInNext(Register receiver,Register index,RegisterList cache_type_array_pair,int feedback_slot)1362 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
1363 Register receiver, Register index, RegisterList cache_type_array_pair,
1364 int feedback_slot) {
1365 DCHECK_EQ(2, cache_type_array_pair.register_count());
1366 OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
1367 return *this;
1368 }
1369
ForInStep(Register index)1370 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
1371 OutputForInStep(index);
1372 return *this;
1373 }
1374
StoreModuleVariable(int cell_index,int depth)1375 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
1376 int depth) {
1377 OutputStaModuleVariable(cell_index, depth);
1378 return *this;
1379 }
1380
LoadModuleVariable(int cell_index,int depth)1381 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
1382 int depth) {
1383 OutputLdaModuleVariable(cell_index, depth);
1384 return *this;
1385 }
1386
SuspendGenerator(Register generator,RegisterList registers,int suspend_id)1387 BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
1388 Register generator, RegisterList registers, int suspend_id) {
1389 OutputSuspendGenerator(generator, registers, registers.register_count(),
1390 suspend_id);
1391 return *this;
1392 }
1393
SwitchOnGeneratorState(Register generator,BytecodeJumpTable * jump_table)1394 BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnGeneratorState(
1395 Register generator, BytecodeJumpTable* jump_table) {
1396 DCHECK_EQ(jump_table->case_value_base(), 0);
1397 BytecodeNode node(CreateSwitchOnGeneratorStateNode(
1398 generator, jump_table->constant_pool_index(), jump_table->size()));
1399 WriteSwitch(&node, jump_table);
1400 return *this;
1401 }
1402
ResumeGenerator(Register generator,RegisterList registers)1403 BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
1404 Register generator, RegisterList registers) {
1405 OutputResumeGenerator(generator, registers, registers.register_count());
1406 return *this;
1407 }
1408
CallProperty(Register callable,RegisterList args,int feedback_slot)1409 BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable,
1410 RegisterList args,
1411 int feedback_slot) {
1412 if (args.register_count() == 1) {
1413 OutputCallProperty0(callable, args[0], feedback_slot);
1414 } else if (args.register_count() == 2) {
1415 OutputCallProperty1(callable, args[0], args[1], feedback_slot);
1416 } else if (args.register_count() == 3) {
1417 OutputCallProperty2(callable, args[0], args[1], args[2], feedback_slot);
1418 } else {
1419 OutputCallProperty(callable, args, args.register_count(), feedback_slot);
1420 }
1421 return *this;
1422 }
1423
CallUndefinedReceiver(Register callable,RegisterList args,int feedback_slot)1424 BytecodeArrayBuilder& BytecodeArrayBuilder::CallUndefinedReceiver(
1425 Register callable, RegisterList args, int feedback_slot) {
1426 if (args.register_count() == 0) {
1427 OutputCallUndefinedReceiver0(callable, feedback_slot);
1428 } else if (args.register_count() == 1) {
1429 OutputCallUndefinedReceiver1(callable, args[0], feedback_slot);
1430 } else if (args.register_count() == 2) {
1431 OutputCallUndefinedReceiver2(callable, args[0], args[1], feedback_slot);
1432 } else {
1433 OutputCallUndefinedReceiver(callable, args, args.register_count(),
1434 feedback_slot);
1435 }
1436 return *this;
1437 }
1438
CallAnyReceiver(Register callable,RegisterList args,int feedback_slot)1439 BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
1440 RegisterList args,
1441 int feedback_slot) {
1442 OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot);
1443 return *this;
1444 }
1445
CallWithSpread(Register callable,RegisterList args,int feedback_slot)1446 BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
1447 RegisterList args,
1448 int feedback_slot) {
1449 OutputCallWithSpread(callable, args, args.register_count(), feedback_slot);
1450 return *this;
1451 }
1452
Construct(Register constructor,RegisterList args,int feedback_slot_id)1453 BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
1454 RegisterList args,
1455 int feedback_slot_id) {
1456 OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
1457 return *this;
1458 }
1459
ConstructWithSpread(Register constructor,RegisterList args,int feedback_slot_id)1460 BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
1461 Register constructor, RegisterList args, int feedback_slot_id) {
1462 OutputConstructWithSpread(constructor, args, args.register_count(),
1463 feedback_slot_id);
1464 return *this;
1465 }
1466
CallRuntime(Runtime::FunctionId function_id,RegisterList args)1467 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1468 Runtime::FunctionId function_id, RegisterList args) {
1469 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
1470 DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
1471 OperandSize::kShort);
1472 if (IntrinsicsHelper::IsSupported(function_id)) {
1473 IntrinsicsHelper::IntrinsicId intrinsic_id =
1474 IntrinsicsHelper::FromRuntimeId(function_id);
1475 OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
1476 args.register_count());
1477 } else {
1478 OutputCallRuntime(static_cast<int>(function_id), args,
1479 args.register_count());
1480 }
1481 return *this;
1482 }
1483
CallRuntime(Runtime::FunctionId function_id,Register arg)1484 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1485 Runtime::FunctionId function_id, Register arg) {
1486 return CallRuntime(function_id, RegisterList(arg));
1487 }
1488
CallRuntime(Runtime::FunctionId function_id)1489 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1490 Runtime::FunctionId function_id) {
1491 return CallRuntime(function_id, RegisterList());
1492 }
1493
CallRuntimeForPair(Runtime::FunctionId function_id,RegisterList args,RegisterList return_pair)1494 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1495 Runtime::FunctionId function_id, RegisterList args,
1496 RegisterList return_pair) {
1497 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
1498 DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
1499 OperandSize::kShort);
1500 DCHECK_EQ(2, return_pair.register_count());
1501 OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
1502 args.register_count(), return_pair);
1503 return *this;
1504 }
1505
CallRuntimeForPair(Runtime::FunctionId function_id,Register arg,RegisterList return_pair)1506 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1507 Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
1508 return CallRuntimeForPair(function_id, RegisterList(arg), return_pair);
1509 }
1510
CallJSRuntime(int context_index,RegisterList args)1511 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
1512 RegisterList args) {
1513 OutputCallJSRuntime(context_index, args, args.register_count());
1514 return *this;
1515 }
1516
Delete(Register object,LanguageMode language_mode)1517 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
1518 LanguageMode language_mode) {
1519 if (language_mode == LanguageMode::kSloppy) {
1520 OutputDeletePropertySloppy(object);
1521 } else {
1522 DCHECK_EQ(language_mode, LanguageMode::kStrict);
1523 OutputDeletePropertyStrict(object);
1524 }
1525 return *this;
1526 }
1527
GetConstantPoolEntry(const AstRawString * raw_string)1528 size_t BytecodeArrayBuilder::GetConstantPoolEntry(
1529 const AstRawString* raw_string) {
1530 return constant_array_builder()->Insert(raw_string);
1531 }
1532
GetConstantPoolEntry(AstBigInt bigint)1533 size_t BytecodeArrayBuilder::GetConstantPoolEntry(AstBigInt bigint) {
1534 return constant_array_builder()->Insert(bigint);
1535 }
1536
GetConstantPoolEntry(const Scope * scope)1537 size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
1538 return constant_array_builder()->Insert(scope);
1539 }
1540
GetConstantPoolEntry(double number)1541 size_t BytecodeArrayBuilder::GetConstantPoolEntry(double number) {
1542 return constant_array_builder()->Insert(number);
1543 }
1544
1545 #define ENTRY_GETTER(NAME, ...) \
1546 size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \
1547 return constant_array_builder()->Insert##NAME(); \
1548 }
SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)1549 SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
1550 #undef ENTRY_GETTER
1551
1552 BytecodeJumpTable* BytecodeArrayBuilder::AllocateJumpTable(
1553 int size, int case_value_base) {
1554 DCHECK_GT(size, 0);
1555
1556 size_t constant_pool_index = constant_array_builder()->InsertJumpTable(size);
1557
1558 return zone()->New<BytecodeJumpTable>(constant_pool_index, size,
1559 case_value_base, zone());
1560 }
1561
AllocateDeferredConstantPoolEntry()1562 size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
1563 return constant_array_builder()->InsertDeferred();
1564 }
1565
SetDeferredConstantPoolEntry(size_t entry,Handle<Object> object)1566 void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
1567 Handle<Object> object) {
1568 constant_array_builder()->SetDeferredAt(entry, object);
1569 }
1570
RegisterIsValid(Register reg) const1571 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
1572 if (!reg.is_valid()) {
1573 return false;
1574 }
1575
1576 if (reg.is_current_context() || reg.is_function_closure()) {
1577 return true;
1578 } else if (reg.is_parameter()) {
1579 int parameter_index = reg.ToParameterIndex();
1580 return parameter_index >= 0 && parameter_index < parameter_count();
1581 } else if (reg.index() < fixed_register_count()) {
1582 return true;
1583 } else {
1584 return register_allocator()->RegisterIsLive(reg);
1585 }
1586 }
1587
RegisterListIsValid(RegisterList reg_list) const1588 bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const {
1589 if (reg_list.register_count() == 0) {
1590 return reg_list.first_register() == Register(0);
1591 } else {
1592 int first_reg_index = reg_list.first_register().index();
1593 for (int i = 0; i < reg_list.register_count(); i++) {
1594 if (!RegisterIsValid(Register(first_reg_index + i))) {
1595 return false;
1596 }
1597 }
1598 return true;
1599 }
1600 }
1601
1602 template <Bytecode bytecode, ImplicitRegisterUse implicit_register_use>
PrepareToOutputBytecode()1603 void BytecodeArrayBuilder::PrepareToOutputBytecode() {
1604 if (register_optimizer_)
1605 register_optimizer_->PrepareForBytecode<bytecode, implicit_register_use>();
1606 }
1607
GetInputRegisterOperand(Register reg)1608 uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
1609 DCHECK(RegisterIsValid(reg));
1610 if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
1611 return static_cast<uint32_t>(reg.ToOperand());
1612 }
1613
GetOutputRegisterOperand(Register reg)1614 uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
1615 DCHECK(RegisterIsValid(reg));
1616 if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
1617 return static_cast<uint32_t>(reg.ToOperand());
1618 }
1619
GetInputRegisterListOperand(RegisterList reg_list)1620 uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
1621 RegisterList reg_list) {
1622 DCHECK(RegisterListIsValid(reg_list));
1623 if (register_optimizer_)
1624 reg_list = register_optimizer_->GetInputRegisterList(reg_list);
1625 return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1626 }
1627
GetOutputRegisterListOperand(RegisterList reg_list)1628 uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
1629 RegisterList reg_list) {
1630 DCHECK(RegisterListIsValid(reg_list));
1631 if (register_optimizer_)
1632 register_optimizer_->PrepareOutputRegisterList(reg_list);
1633 return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1634 }
1635
EmitFunctionStartSourcePosition(int position)1636 void BytecodeArrayBuilder::EmitFunctionStartSourcePosition(int position) {
1637 bytecode_array_writer_.SetFunctionEntrySourcePosition(position);
1638 // Force an expression position to make sure we have one. If the next bytecode
1639 // overwrites it, it’s fine since it would mean we have a source position
1640 // anyway.
1641 latest_source_info_.ForceExpressionPosition(position);
1642 }
1643
operator <<(std::ostream & os,const BytecodeArrayBuilder::ToBooleanMode & mode)1644 std::ostream& operator<<(std::ostream& os,
1645 const BytecodeArrayBuilder::ToBooleanMode& mode) {
1646 switch (mode) {
1647 case BytecodeArrayBuilder::ToBooleanMode::kAlreadyBoolean:
1648 return os << "AlreadyBoolean";
1649 case BytecodeArrayBuilder::ToBooleanMode::kConvertToBoolean:
1650 return os << "ConvertToBoolean";
1651 }
1652 UNREACHABLE();
1653 }
1654
1655 } // namespace interpreter
1656 } // namespace internal
1657 } // namespace v8
1658