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