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