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 3788115 : void EmitLdar(Register input) override { builder_->OutputLdarRaw(input); }
30 :
31 20365225 : void EmitStar(Register output) override { builder_->OutputStarRaw(output); }
32 :
33 1345606 : void EmitMov(Register input, Register output) override {
34 1345606 : builder_->OutputMovRaw(input, output);
35 1345668 : }
36 :
37 : private:
38 : BytecodeArrayBuilder* builder_;
39 : };
40 :
41 2129980 : 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 : return_seen_in_block_(false),
51 : parameter_count_(parameter_count),
52 : local_register_count_(locals_count),
53 : register_allocator_(fixed_register_count()),
54 : bytecode_array_writer_(zone, &constant_array_builder_,
55 : source_position_mode),
56 4259943 : register_optimizer_(nullptr) {
57 : DCHECK_GE(parameter_count_, 0);
58 : DCHECK_GE(local_register_count_, 0);
59 :
60 2129973 : if (FLAG_ignition_reo) {
61 : register_optimizer_ = new (zone) BytecodeRegisterOptimizer(
62 : zone, ®ister_allocator_, fixed_register_count(), parameter_count,
63 2129431 : new (zone) RegisterTransferWriter(this));
64 : }
65 2130008 : }
66 :
67 1359229 : Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
68 : DCHECK_GE(parameter_index, 0);
69 : // The parameter indices are shifted by 1 (receiver is the
70 : // first entry).
71 1359229 : return Register::FromParameterIndex(parameter_index + 1, parameter_count());
72 : }
73 :
74 2507641 : Register BytecodeArrayBuilder::Receiver() const {
75 2507641 : return Register::FromParameterIndex(0, parameter_count());
76 : }
77 :
78 4898026 : Register BytecodeArrayBuilder::Local(int index) const {
79 : // TODO(marja): Make a DCHECK once crbug.com/706234 is fixed.
80 4898026 : CHECK_LT(index, locals_count());
81 4898026 : return Register(index);
82 : }
83 :
84 4211615 : Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
85 : DCHECK(return_seen_in_block_);
86 : DCHECK(!bytecode_generated_);
87 2105797 : bytecode_generated_ = true;
88 :
89 : int register_count = total_register_count();
90 :
91 4211080 : if (register_optimizer_) {
92 2105271 : register_optimizer_->Flush();
93 4210566 : register_count = register_optimizer_->maxiumum_register_index() + 1;
94 : }
95 :
96 : Handle<ByteArray> handler_table =
97 2105809 : handler_table_builder()->ToHandlerTable(isolate);
98 : return bytecode_array_writer_.ToBytecodeArray(
99 2105818 : isolate, register_count, parameter_count(), handler_table);
100 : }
101 :
102 : BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
103 : Bytecode bytecode) {
104 87808411 : BytecodeSourceInfo source_position;
105 87808559 : if (latest_source_info_.is_valid()) {
106 : // Statement positions need to be emitted immediately. Expression
107 : // positions can be pushed back until a bytecode is found that can
108 : // throw (if expression position filtering is turned on). We only
109 : // invalidate the existing source position information if it is used.
110 101965962 : if (latest_source_info_.is_statement() ||
111 63531743 : !FLAG_ignition_filter_expression_positions ||
112 25099253 : !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
113 32230500 : source_position = latest_source_info_;
114 32230500 : latest_source_info_.set_invalid();
115 : }
116 : }
117 87808947 : return source_position;
118 : }
119 :
120 0 : void BytecodeArrayBuilder::SetDeferredSourceInfo(
121 : BytecodeSourceInfo source_info) {
122 33648025 : if (!source_info.is_valid()) return;
123 3449109 : deferred_source_info_ = source_info;
124 : }
125 :
126 0 : void BytecodeArrayBuilder::AttachOrEmitDeferredSourceInfo(BytecodeNode* node) {
127 79581239 : if (!deferred_source_info_.is_valid()) return;
128 3442795 : if (!node->source_info().is_valid()) {
129 : node->set_source_info(deferred_source_info_);
130 402856 : } else if (deferred_source_info_.is_statement() &&
131 : node->source_info().is_expression()) {
132 : BytecodeSourceInfo source_position = node->source_info();
133 : source_position.MakeStatementPosition(source_position.source_position());
134 : node->set_source_info(source_position);
135 : }
136 : deferred_source_info_.set_invalid();
137 : }
138 :
139 77477814 : void BytecodeArrayBuilder::Write(BytecodeNode* node) {
140 : AttachOrEmitDeferredSourceInfo(node);
141 77477814 : bytecode_array_writer_.Write(node);
142 77487016 : }
143 :
144 2083364 : void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
145 : AttachOrEmitDeferredSourceInfo(node);
146 2083364 : bytecode_array_writer_.WriteJump(node, label);
147 2083435 : }
148 :
149 20061 : void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node,
150 : BytecodeJumpTable* jump_table) {
151 : AttachOrEmitDeferredSourceInfo(node);
152 20061 : bytecode_array_writer_.WriteSwitch(node, jump_table);
153 20061 : }
154 :
155 3788078 : void BytecodeArrayBuilder::OutputLdarRaw(Register reg) {
156 3788078 : uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
157 : BytecodeNode node(BytecodeNode::Ldar(BytecodeSourceInfo(), operand));
158 3788183 : Write(&node);
159 3788200 : }
160 :
161 20364750 : void BytecodeArrayBuilder::OutputStarRaw(Register reg) {
162 20364750 : uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
163 : BytecodeNode node(BytecodeNode::Star(BytecodeSourceInfo(), operand));
164 20363725 : Write(&node);
165 20360910 : }
166 :
167 1345603 : void BytecodeArrayBuilder::OutputMovRaw(Register src, Register dest) {
168 1345603 : uint32_t operand0 = static_cast<uint32_t>(src.ToOperand());
169 1345603 : uint32_t operand1 = static_cast<uint32_t>(dest.ToOperand());
170 : BytecodeNode node(
171 : BytecodeNode::Mov(BytecodeSourceInfo(), operand0, operand1));
172 1345595 : Write(&node);
173 1345668 : }
174 :
175 : namespace {
176 :
177 : template <OperandTypeInfo type_info>
178 : class UnsignedOperandHelper {
179 : public:
180 : V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
181 : size_t value) {
182 : DCHECK(IsValid(value));
183 37615699 : return static_cast<uint32_t>(value);
184 : }
185 :
186 : V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
187 : DCHECK_GE(value, 0);
188 32484738 : return Convert(builder, static_cast<size_t>(value));
189 : }
190 :
191 : private:
192 : static bool IsValid(size_t value) {
193 : switch (type_info) {
194 : case OperandTypeInfo::kFixedUnsignedByte:
195 : return value <= kMaxUInt8;
196 : case OperandTypeInfo::kFixedUnsignedShort:
197 : return value <= kMaxUInt16;
198 : case OperandTypeInfo::kScalableUnsignedByte:
199 : return value <= kMaxUInt32;
200 : default:
201 : UNREACHABLE();
202 : }
203 : }
204 : };
205 :
206 : template <OperandType>
207 : class OperandHelper {};
208 :
209 : #define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \
210 : template <> \
211 : class OperandHelper<OperandType::k##Name> \
212 : : public UnsignedOperandHelper<Type> {};
213 : UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
214 : UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
215 : #undef DEFINE_UNSIGNED_OPERAND_HELPER
216 :
217 : template <>
218 : class OperandHelper<OperandType::kImm> {
219 : public:
220 : V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder, int value) {
221 6762637 : return static_cast<uint32_t>(value);
222 : }
223 : };
224 :
225 : template <>
226 : class OperandHelper<OperandType::kReg> {
227 : public:
228 : V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
229 : Register reg) {
230 13186513 : return builder->GetInputRegisterOperand(reg);
231 : }
232 : };
233 :
234 : template <>
235 : class OperandHelper<OperandType::kRegList> {
236 : public:
237 : V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
238 : RegisterList reg_list) {
239 2873357 : return builder->GetInputRegisterListOperand(reg_list);
240 : }
241 : };
242 :
243 : template <>
244 : class OperandHelper<OperandType::kRegPair> {
245 : public:
246 : V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
247 : RegisterList reg_list) {
248 : DCHECK_EQ(reg_list.register_count(), 2);
249 4751 : return builder->GetInputRegisterListOperand(reg_list);
250 : }
251 : };
252 :
253 : template <>
254 : class OperandHelper<OperandType::kRegOut> {
255 : public:
256 : V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
257 : Register reg) {
258 347522 : return builder->GetOutputRegisterOperand(reg);
259 : }
260 : };
261 :
262 : template <>
263 : class OperandHelper<OperandType::kRegOutList> {
264 : public:
265 : V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
266 : RegisterList reg_list) {
267 23637 : return builder->GetOutputRegisterListOperand(reg_list);
268 : }
269 : };
270 :
271 : template <>
272 : class OperandHelper<OperandType::kRegOutPair> {
273 : public:
274 : V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
275 : RegisterList reg_list) {
276 : DCHECK_EQ(2, reg_list.register_count());
277 4596 : return builder->GetOutputRegisterListOperand(reg_list);
278 : }
279 : };
280 :
281 : template <>
282 : class OperandHelper<OperandType::kRegOutTriple> {
283 : public:
284 : V8_INLINE static uint32_t Convert(BytecodeArrayBuilder* builder,
285 : RegisterList reg_list) {
286 : DCHECK_EQ(3, reg_list.register_count());
287 4760 : return builder->GetOutputRegisterListOperand(reg_list);
288 : }
289 : };
290 :
291 : } // namespace
292 :
293 : template <Bytecode bytecode, AccumulatorUse accumulator_use,
294 : OperandType... operand_types>
295 : class BytecodeNodeBuilder {
296 : public:
297 : template <typename... Operands>
298 1425273 : V8_INLINE static BytecodeNode Make(BytecodeArrayBuilder* builder,
299 : Operands... operands) {
300 : static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands,
301 : "too many operands for bytecode");
302 54158482 : builder->PrepareToOutputBytecode<bytecode, accumulator_use>();
303 : // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
304 : // expand both the OperandType... and Operands... parameter packs e.g. for:
305 : // BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
306 : // Register, int>(..., Register reg, int immediate)
307 : // the code will expand into:
308 : // OperandHelper<OperandType::kReg>::Convert(builder, reg),
309 : // OperandHelper<OperandType::kImm>::Convert(builder, immediate),
310 : return BytecodeNode::Create<bytecode, accumulator_use, operand_types...>(
311 : builder->CurrentSourcePosition(bytecode),
312 2404 : OperandHelper<operand_types>::Convert(builder, operands)...);
313 : }
314 : };
315 :
316 : #define DEFINE_BYTECODE_OUTPUT(name, ...) \
317 : template <typename... Operands> \
318 : BytecodeNode BytecodeArrayBuilder::Create##name##Node( \
319 : Operands... operands) { \
320 : return BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make( \
321 : this, operands...); \
322 : } \
323 : \
324 : template <typename... Operands> \
325 : void BytecodeArrayBuilder::Output##name(Operands... operands) { \
326 : BytecodeNode node(Create##name##Node(operands...)); \
327 : Write(&node); \
328 : } \
329 : \
330 : template <typename... Operands> \
331 : void BytecodeArrayBuilder::Output##name(BytecodeLabel* label, \
332 : Operands... operands) { \
333 : DCHECK(Bytecodes::IsJump(Bytecode::k##name)); \
334 : BytecodeNode node(Create##name##Node(operands...)); \
335 : WriteJump(&node, label); \
336 : LeaveBasicBlock(); \
337 : }
338 54139074 : BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
339 : #undef DEFINE_BYTECODE_OUTPUT
340 :
341 : void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback(
342 32643 : BytecodeJumpTable* jump_table) {
343 : BytecodeNode node(CreateSwitchOnSmiNoFeedbackNode(
344 : jump_table->constant_pool_index(), jump_table->size(),
345 32643 : jump_table->case_value_base()));
346 10882 : WriteSwitch(&node, jump_table);
347 10882 : LeaveBasicBlock();
348 : }
349 :
350 608317 : BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
351 : Register reg,
352 : int feedback_slot) {
353 608317 : switch (op) {
354 : case Token::Value::ADD:
355 : OutputAdd(reg, feedback_slot);
356 : break;
357 : case Token::Value::SUB:
358 : OutputSub(reg, feedback_slot);
359 : break;
360 : case Token::Value::MUL:
361 : OutputMul(reg, feedback_slot);
362 : break;
363 : case Token::Value::DIV:
364 : OutputDiv(reg, feedback_slot);
365 : break;
366 : case Token::Value::MOD:
367 : OutputMod(reg, feedback_slot);
368 : break;
369 : case Token::Value::EXP:
370 : OutputExp(reg, feedback_slot);
371 : break;
372 : case Token::Value::BIT_OR:
373 : OutputBitwiseOr(reg, feedback_slot);
374 : break;
375 : case Token::Value::BIT_XOR:
376 : OutputBitwiseXor(reg, feedback_slot);
377 : break;
378 : case Token::Value::BIT_AND:
379 : OutputBitwiseAnd(reg, feedback_slot);
380 : break;
381 : case Token::Value::SHL:
382 : OutputShiftLeft(reg, feedback_slot);
383 : break;
384 : case Token::Value::SAR:
385 : OutputShiftRight(reg, feedback_slot);
386 : break;
387 : case Token::Value::SHR:
388 : OutputShiftRightLogical(reg, feedback_slot);
389 : break;
390 : default:
391 0 : UNREACHABLE();
392 : }
393 608357 : return *this;
394 : }
395 :
396 191805 : BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
397 : Token::Value op, Smi literal, int feedback_slot) {
398 191805 : switch (op) {
399 : case Token::Value::ADD:
400 : OutputAddSmi(literal->value(), feedback_slot);
401 : break;
402 : case Token::Value::SUB:
403 : OutputSubSmi(literal->value(), feedback_slot);
404 : break;
405 : case Token::Value::MUL:
406 : OutputMulSmi(literal->value(), feedback_slot);
407 : break;
408 : case Token::Value::DIV:
409 : OutputDivSmi(literal->value(), feedback_slot);
410 : break;
411 : case Token::Value::MOD:
412 : OutputModSmi(literal->value(), feedback_slot);
413 : break;
414 : case Token::Value::EXP:
415 : OutputExpSmi(literal->value(), feedback_slot);
416 : break;
417 : case Token::Value::BIT_OR:
418 : OutputBitwiseOrSmi(literal->value(), feedback_slot);
419 : break;
420 : case Token::Value::BIT_XOR:
421 : OutputBitwiseXorSmi(literal->value(), feedback_slot);
422 : break;
423 : case Token::Value::BIT_AND:
424 : OutputBitwiseAndSmi(literal->value(), feedback_slot);
425 : break;
426 : case Token::Value::SHL:
427 : OutputShiftLeftSmi(literal->value(), feedback_slot);
428 : break;
429 : case Token::Value::SAR:
430 : OutputShiftRightSmi(literal->value(), feedback_slot);
431 : break;
432 : case Token::Value::SHR:
433 : OutputShiftRightLogicalSmi(literal->value(), feedback_slot);
434 : break;
435 : default:
436 0 : UNREACHABLE();
437 : }
438 191832 : return *this;
439 : }
440 :
441 306951 : BytecodeArrayBuilder& BytecodeArrayBuilder::UnaryOperation(Token::Value op,
442 : int feedback_slot) {
443 306951 : switch (op) {
444 : case Token::Value::INC:
445 : OutputInc(feedback_slot);
446 : break;
447 : case Token::Value::DEC:
448 : OutputDec(feedback_slot);
449 : break;
450 : case Token::Value::ADD:
451 : OutputToNumber(feedback_slot);
452 : break;
453 : case Token::Value::SUB:
454 : OutputNegate(feedback_slot);
455 : break;
456 : case Token::Value::BIT_NOT:
457 : OutputBitwiseNot(feedback_slot);
458 : break;
459 : default:
460 0 : UNREACHABLE();
461 : }
462 307006 : return *this;
463 : }
464 :
465 25405 : BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
466 25405 : if (mode == ToBooleanMode::kAlreadyBoolean) {
467 : OutputLogicalNot();
468 : } else {
469 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
470 : OutputToBooleanLogicalNot();
471 : }
472 25407 : return *this;
473 : }
474 :
475 51626 : BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
476 : OutputTypeOf();
477 51629 : return *this;
478 : }
479 :
480 5290 : BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
481 : OutputGetSuperConstructor(out);
482 5291 : return *this;
483 : }
484 :
485 784884 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
486 : Token::Value op, Register reg, int feedback_slot) {
487 784884 : switch (op) {
488 : case Token::Value::EQ:
489 : OutputTestEqual(reg, feedback_slot);
490 : break;
491 : case Token::Value::EQ_STRICT:
492 : OutputTestEqualStrict(reg, feedback_slot);
493 : break;
494 : case Token::Value::LT:
495 : OutputTestLessThan(reg, feedback_slot);
496 : break;
497 : case Token::Value::GT:
498 : OutputTestGreaterThan(reg, feedback_slot);
499 : break;
500 : case Token::Value::LTE:
501 : OutputTestLessThanOrEqual(reg, feedback_slot);
502 : break;
503 : case Token::Value::GTE:
504 : OutputTestGreaterThanOrEqual(reg, feedback_slot);
505 : break;
506 : case Token::Value::INSTANCEOF:
507 : OutputTestInstanceOf(reg, feedback_slot);
508 : break;
509 : default:
510 0 : UNREACHABLE();
511 : }
512 784956 : return *this;
513 : }
514 :
515 2422 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
516 : Register reg) {
517 2422 : switch (op) {
518 : case Token::Value::IN:
519 : OutputTestIn(reg);
520 : break;
521 : default:
522 0 : UNREACHABLE();
523 : }
524 2426 : return *this;
525 : }
526 :
527 97797 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareReference(Register reg) {
528 : OutputTestReferenceEqual(reg);
529 97808 : return *this;
530 : }
531 :
532 3248 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndetectable() {
533 : OutputTestUndetectable();
534 3249 : return *this;
535 : }
536 :
537 9448 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndefined() {
538 : OutputTestUndefined();
539 9449 : return *this;
540 : }
541 :
542 1019 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNull() {
543 : OutputTestNull();
544 1020 : return *this;
545 : }
546 :
547 12316 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNil(Token::Value op,
548 : NilValue nil) {
549 12316 : if (op == Token::EQ) {
550 1850 : return CompareUndetectable();
551 : } else {
552 : DCHECK_EQ(Token::EQ_STRICT, op);
553 10466 : if (nil == kUndefinedValue) {
554 9448 : return CompareUndefined();
555 : } else {
556 : DCHECK_EQ(kNullValue, nil);
557 1018 : return CompareNull();
558 : }
559 : }
560 : }
561 :
562 133128 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
563 : TestTypeOfFlags::LiteralFlag literal_flag) {
564 : DCHECK_NE(literal_flag, TestTypeOfFlags::LiteralFlag::kOther);
565 133128 : OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
566 133138 : return *this;
567 : }
568 :
569 464201 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
570 : size_t entry) {
571 : OutputLdaConstant(entry);
572 464336 : return *this;
573 : }
574 :
575 8065191 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Smi smi) {
576 : int32_t raw_smi = smi->value();
577 8065191 : if (raw_smi == 0) {
578 : OutputLdaZero();
579 : } else {
580 : OutputLdaSmi(raw_smi);
581 : }
582 8064968 : return *this;
583 : }
584 :
585 614778 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(double value) {
586 : size_t entry = GetConstantPoolEntry(value);
587 : OutputLdaConstant(entry);
588 614786 : return *this;
589 : }
590 :
591 2038158 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
592 : const AstRawString* raw_string) {
593 : size_t entry = GetConstantPoolEntry(raw_string);
594 : OutputLdaConstant(entry);
595 2038168 : return *this;
596 : }
597 :
598 14693 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(const Scope* scope) {
599 : size_t entry = GetConstantPoolEntry(scope);
600 : OutputLdaConstant(entry);
601 14693 : return *this;
602 : }
603 :
604 10426 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstBigInt bigint) {
605 : size_t entry = GetConstantPoolEntry(bigint);
606 : OutputLdaConstant(entry);
607 10426 : return *this;
608 : }
609 :
610 1981 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstSymbol symbol) {
611 : size_t entry;
612 1981 : switch (symbol) {
613 : case AstSymbol::kHomeObjectSymbol:
614 : entry = HomeObjectSymbolConstantPoolEntry();
615 1981 : break;
616 : // No default case so that we get a warning if AstSymbol changes
617 : }
618 : OutputLdaConstant(entry);
619 1981 : return *this;
620 : }
621 :
622 1512573 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
623 : OutputLdaUndefined();
624 1512970 : return *this;
625 : }
626 :
627 25548 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
628 : OutputLdaNull();
629 25546 : return *this;
630 : }
631 :
632 907691 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
633 : OutputLdaTheHole();
634 907776 : return *this;
635 : }
636 :
637 166058 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
638 : OutputLdaTrue();
639 166094 : return *this;
640 : }
641 :
642 285109 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
643 : OutputLdaFalse();
644 285139 : return *this;
645 : }
646 :
647 320059 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBoolean(bool value) {
648 320059 : return value ? LoadTrue() : LoadFalse();
649 : }
650 :
651 7621057 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
652 : Register reg) {
653 7621057 : 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 7620172 : register_optimizer_->DoLdar(reg);
658 : } else {
659 : OutputLdar(reg);
660 : }
661 7621442 : return *this;
662 : }
663 :
664 25299572 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
665 : Register reg) {
666 25299572 : 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 25295875 : register_optimizer_->DoStar(reg);
671 : } else {
672 : OutputStar(reg);
673 : }
674 25300615 : return *this;
675 : }
676 :
677 732241 : BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
678 : Register to) {
679 : DCHECK(from != to);
680 732241 : 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 731978 : register_optimizer_->DoMov(from, to);
685 : } else {
686 : OutputMov(from, to);
687 : }
688 732311 : return *this;
689 : }
690 :
691 5862489 : 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 5862463 : 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 5862555 : return *this;
706 : }
707 :
708 1421148 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
709 : const AstRawString* name, int feedback_slot) {
710 : size_t name_index = GetConstantPoolEntry(name);
711 : OutputStaGlobal(name_index, feedback_slot);
712 1421193 : return *this;
713 : }
714 :
715 1038702 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
716 : Register context, int slot_index, int depth,
717 : ContextSlotMutability mutability) {
718 1038702 : if (context.is_current_context() && depth == 0) {
719 952463 : if (mutability == kImmutableSlot) {
720 : OutputLdaImmutableCurrentContextSlot(slot_index);
721 : } else {
722 : DCHECK_EQ(kMutableSlot, mutability);
723 : OutputLdaCurrentContextSlot(slot_index);
724 : }
725 86241 : } 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 1038742 : return *this;
732 : }
733 :
734 2815251 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
735 : int slot_index,
736 : int depth) {
737 2815251 : if (context.is_current_context() && depth == 0) {
738 : OutputStaCurrentContextSlot(slot_index);
739 : } else {
740 : OutputStaContextSlot(context, slot_index, depth);
741 : }
742 2815027 : return *this;
743 : }
744 :
745 25858 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
746 : const AstRawString* name, TypeofMode typeof_mode) {
747 : size_t name_index = GetConstantPoolEntry(name);
748 25858 : 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 25857 : return *this;
755 : }
756 :
757 3649 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
758 : const AstRawString* name, TypeofMode typeof_mode, int slot_index,
759 : int depth) {
760 : size_t name_index = GetConstantPoolEntry(name);
761 3649 : 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 3649 : return *this;
768 : }
769 :
770 372472 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
771 : const AstRawString* name, TypeofMode typeof_mode, int feedback_slot,
772 : int depth) {
773 : size_t name_index = GetConstantPoolEntry(name);
774 372472 : 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 372472 : return *this;
781 : }
782 :
783 37548 : 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 37549 : StoreLookupSlotFlags::Encode(language_mode, lookup_hoisting_mode);
789 : OutputStaLookupSlot(name_index, flags);
790 37549 : return *this;
791 : }
792 :
793 1308192 : 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 1308253 : return *this;
798 : }
799 :
800 1256904 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyNoFeedback(
801 : Register object, const AstRawString* name) {
802 : size_t name_index = GetConstantPoolEntry(name);
803 : OutputLdaNamedPropertyNoFeedback(object, name_index);
804 1257055 : return *this;
805 : }
806 :
807 139472 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
808 : Register object, int feedback_slot) {
809 : OutputLdaKeyedProperty(object, feedback_slot);
810 139484 : return *this;
811 : }
812 :
813 42592 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
814 : Register object, int feedback_slot) {
815 : size_t name_index = IteratorSymbolConstantPoolEntry();
816 : OutputLdaNamedProperty(object, name_index, feedback_slot);
817 42603 : return *this;
818 : }
819 :
820 347 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
821 : Register object, int feedback_slot) {
822 : size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
823 : OutputLdaNamedProperty(object, name_index, feedback_slot);
824 347 : return *this;
825 : }
826 :
827 2403 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
828 : Register object, Register name, DataPropertyInLiteralFlags flags,
829 : int feedback_slot) {
830 : OutputStaDataPropertyInLiteral(object, name, flags, feedback_slot);
831 2407 : return *this;
832 : }
833 :
834 205 : BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
835 : OutputCollectTypeProfile(position);
836 205 : return *this;
837 : }
838 :
839 2283607 : 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 2283615 : return *this;
848 : }
849 :
850 2281987 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
851 : Register object, const AstRawString* name, int feedback_slot,
852 : LanguageMode language_mode) {
853 : size_t name_index = GetConstantPoolEntry(name);
854 2281996 : return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
855 : }
856 :
857 114657 : 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 114803 : return *this;
863 : }
864 :
865 245032 : 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 245063 : return *this;
874 : }
875 :
876 34383 : 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 34406 : return *this;
885 : }
886 :
887 242525 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreInArrayLiteral(
888 : Register array, Register index, int feedback_slot) {
889 : OutputStaInArrayLiteral(array, index, feedback_slot);
890 242557 : 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 912 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreClassFieldsInitializer(
900 : Register constructor, int feedback_slot) {
901 : size_t name_index = ClassFieldsSymbolConstantPoolEntry();
902 : return StoreNamedProperty(constructor, name_index, feedback_slot,
903 912 : LanguageMode::kStrict);
904 : }
905 :
906 837 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadClassFieldsInitializer(
907 : Register constructor, int feedback_slot) {
908 : size_t name_index = ClassFieldsSymbolConstantPoolEntry();
909 : OutputLdaNamedProperty(constructor, name_index, feedback_slot);
910 837 : return *this;
911 : }
912 :
913 2606927 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
914 : size_t shared_function_info_entry, int slot, int flags) {
915 : OutputCreateClosure(shared_function_info_entry, slot, flags);
916 2606942 : return *this;
917 : }
918 :
919 58323 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
920 : const Scope* scope) {
921 : size_t entry = GetConstantPoolEntry(scope);
922 : OutputCreateBlockContext(entry);
923 58334 : return *this;
924 : }
925 :
926 69597 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
927 : Register exception, const Scope* scope) {
928 : size_t scope_index = GetConstantPoolEntry(scope);
929 : OutputCreateCatchContext(exception, scope_index);
930 69622 : return *this;
931 : }
932 :
933 134623 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(
934 : const Scope* scope, int slots) {
935 : size_t scope_index = GetConstantPoolEntry(scope);
936 : OutputCreateFunctionContext(scope_index, slots);
937 134623 : return *this;
938 : }
939 :
940 42321 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(
941 : const Scope* scope, int slots) {
942 : size_t scope_index = GetConstantPoolEntry(scope);
943 : OutputCreateEvalContext(scope_index, slots);
944 42321 : return *this;
945 : }
946 :
947 2956 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
948 : Register object, const Scope* scope) {
949 : size_t scope_index = GetConstantPoolEntry(scope);
950 : OutputCreateWithContext(object, scope_index);
951 2957 : return *this;
952 : }
953 :
954 105815 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
955 : CreateArgumentsType type) {
956 105815 : 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 105816 : return *this;
970 : }
971 :
972 44999 : 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 45003 : return *this;
977 : }
978 :
979 154495 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyArrayLiteral(
980 : int literal_index) {
981 : OutputCreateEmptyArrayLiteral(literal_index);
982 154498 : return *this;
983 : }
984 :
985 31958 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
986 : size_t constant_elements_entry, int literal_index, int flags) {
987 : OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
988 31969 : return *this;
989 : }
990 :
991 2112 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayFromIterable() {
992 : OutputCreateArrayFromIterable();
993 2113 : return *this;
994 : }
995 :
996 87521 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
997 : size_t constant_properties_entry, int literal_index, int flags) {
998 : OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags);
999 87528 : return *this;
1000 : }
1001 :
1002 28154 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyObjectLiteral() {
1003 : OutputCreateEmptyObjectLiteral();
1004 28165 : return *this;
1005 : }
1006 :
1007 262 : BytecodeArrayBuilder& BytecodeArrayBuilder::CloneObject(Register source,
1008 : int flags,
1009 : int feedback_slot) {
1010 : OutputCloneObject(source, flags, feedback_slot);
1011 263 : return *this;
1012 : }
1013 :
1014 2044 : BytecodeArrayBuilder& BytecodeArrayBuilder::GetTemplateObject(
1015 : size_t template_object_description_entry, int feedback_slot) {
1016 : OutputGetTemplateObject(template_object_description_entry, feedback_slot);
1017 2044 : return *this;
1018 : }
1019 :
1020 322509 : BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
1021 : OutputPushContext(context);
1022 322546 : return *this;
1023 : }
1024 :
1025 331997 : BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
1026 : OutputPopContext(context);
1027 332042 : return *this;
1028 : }
1029 :
1030 7967 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToObject(Register out) {
1031 : OutputToObject(out);
1032 7968 : return *this;
1033 : }
1034 :
1035 8051 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToName(Register out) {
1036 : OutputToName(out);
1037 8053 : return *this;
1038 : }
1039 :
1040 10590 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToString() {
1041 : OutputToString();
1042 10592 : return *this;
1043 : }
1044 :
1045 1 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumber(int feedback_slot) {
1046 : OutputToNumber(feedback_slot);
1047 1 : return *this;
1048 : }
1049 :
1050 26920 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(int feedback_slot) {
1051 : OutputToNumeric(feedback_slot);
1052 26921 : return *this;
1053 : }
1054 :
1055 2701376 : BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
1056 : // Flush the register optimizer when binding a label to ensure all
1057 : // expected registers are valid when jumping to this label.
1058 2701376 : if (register_optimizer_) register_optimizer_->Flush();
1059 2701450 : bytecode_array_writer_.BindLabel(label);
1060 : LeaveBasicBlock();
1061 2701499 : return *this;
1062 : }
1063 :
1064 0 : BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
1065 : BytecodeLabel* label) {
1066 0 : bytecode_array_writer_.BindLabel(target, label);
1067 : LeaveBasicBlock();
1068 0 : return *this;
1069 : }
1070 :
1071 46734 : BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeJumpTable* jump_table,
1072 : int case_value) {
1073 : // Flush the register optimizer when binding a jump table entry to ensure
1074 : // all expected registers are valid when jumping to this location.
1075 46734 : if (register_optimizer_) register_optimizer_->Flush();
1076 46734 : bytecode_array_writer_.BindJumpTableEntry(jump_table, case_value);
1077 : LeaveBasicBlock();
1078 46734 : return *this;
1079 : }
1080 :
1081 319043 : BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
1082 : DCHECK(!label->is_bound());
1083 : OutputJump(label, 0);
1084 319080 : return *this;
1085 : }
1086 :
1087 540744 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
1088 : BytecodeLabel* label) {
1089 : DCHECK(!label->is_bound());
1090 540744 : if (mode == ToBooleanMode::kAlreadyBoolean) {
1091 : OutputJumpIfTrue(label, 0);
1092 : } else {
1093 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1094 : OutputJumpIfToBooleanTrue(label, 0);
1095 : }
1096 540763 : return *this;
1097 : }
1098 :
1099 677751 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
1100 : BytecodeLabel* label) {
1101 : DCHECK(!label->is_bound());
1102 677751 : if (mode == ToBooleanMode::kAlreadyBoolean) {
1103 : OutputJumpIfFalse(label, 0);
1104 : } else {
1105 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1106 : OutputJumpIfToBooleanFalse(label, 0);
1107 : }
1108 677822 : return *this;
1109 : }
1110 :
1111 59641 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
1112 : DCHECK(!label->is_bound());
1113 : OutputJumpIfNull(label, 0);
1114 59651 : return *this;
1115 : }
1116 :
1117 496 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
1118 : BytecodeLabel* label) {
1119 : DCHECK(!label->is_bound());
1120 : OutputJumpIfNotNull(label, 0);
1121 496 : return *this;
1122 : }
1123 :
1124 66662 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
1125 : BytecodeLabel* label) {
1126 : DCHECK(!label->is_bound());
1127 : OutputJumpIfUndefined(label, 0);
1128 66677 : return *this;
1129 : }
1130 :
1131 26607 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotUndefined(
1132 : BytecodeLabel* label) {
1133 : DCHECK(!label->is_bound());
1134 : OutputJumpIfNotUndefined(label, 0);
1135 26610 : return *this;
1136 : }
1137 :
1138 16660 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
1139 : Token::Value op,
1140 : NilValue nil) {
1141 16660 : if (op == Token::EQ) {
1142 : // TODO(rmcilroy): Implement JumpIfUndetectable.
1143 315 : return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
1144 315 : label);
1145 : } else {
1146 : DCHECK_EQ(Token::EQ_STRICT, op);
1147 16345 : if (nil == kUndefinedValue) {
1148 14385 : return JumpIfUndefined(label);
1149 : } else {
1150 : DCHECK_EQ(kNullValue, nil);
1151 1960 : return JumpIfNull(label);
1152 : }
1153 : }
1154 : }
1155 :
1156 15294 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
1157 : Token::Value op,
1158 : NilValue nil) {
1159 15294 : if (op == Token::EQ) {
1160 : // TODO(rmcilroy): Implement JumpIfUndetectable.
1161 1082 : return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
1162 1082 : label);
1163 : } else {
1164 : DCHECK_EQ(Token::EQ_STRICT, op);
1165 14212 : if (nil == kUndefinedValue) {
1166 13718 : return JumpIfNotUndefined(label);
1167 : } else {
1168 : DCHECK_EQ(kNullValue, nil);
1169 494 : return JumpIfNotNull(label);
1170 : }
1171 : }
1172 : }
1173 :
1174 127562 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
1175 : BytecodeLabel* label) {
1176 : DCHECK(!label->is_bound());
1177 : OutputJumpIfJSReceiver(label, 0);
1178 127576 : return *this;
1179 : }
1180 :
1181 264776 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
1182 : int loop_depth) {
1183 : DCHECK(label->is_bound());
1184 : OutputJumpLoop(label, 0, loop_depth);
1185 264837 : return *this;
1186 : }
1187 :
1188 10881 : BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnSmiNoFeedback(
1189 : BytecodeJumpTable* jump_table) {
1190 : OutputSwitchOnSmiNoFeedback(jump_table);
1191 10882 : return *this;
1192 : }
1193 :
1194 2372327 : BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
1195 2372327 : if (position != kNoSourcePosition) {
1196 : // We need to attach a non-breakable source position to a stack
1197 : // check, so we simply add it as expression position. There can be
1198 : // a prior statement position from constructs like:
1199 : //
1200 : // do var x; while (false);
1201 : //
1202 : // A Nop could be inserted for empty statements, but since no code
1203 : // is associated with these positions, instead we force the stack
1204 : // check's expression position which eliminates the empty
1205 : // statement's position.
1206 : latest_source_info_.ForceExpressionPosition(position);
1207 : }
1208 : OutputStackCheck();
1209 2372493 : return *this;
1210 : }
1211 :
1212 157884 : BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
1213 : OutputSetPendingMessage();
1214 157880 : return *this;
1215 : }
1216 :
1217 68384 : BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
1218 : OutputThrow();
1219 68391 : return *this;
1220 : }
1221 :
1222 93335 : BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
1223 : OutputReThrow();
1224 93345 : return *this;
1225 : }
1226 :
1227 1 : BytecodeArrayBuilder& BytecodeArrayBuilder::Abort(AbortReason reason) {
1228 : DCHECK_LT(reason, AbortReason::kLastErrorMessage);
1229 : DCHECK_GE(reason, AbortReason::kNoReason);
1230 1 : OutputAbort(static_cast<int>(reason));
1231 1 : return *this;
1232 : }
1233 :
1234 2460904 : BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
1235 : OutputReturn();
1236 2461391 : return_seen_in_block_ = true;
1237 2461391 : return *this;
1238 : }
1239 :
1240 282650 : BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowReferenceErrorIfHole(
1241 : const AstRawString* name) {
1242 : size_t entry = GetConstantPoolEntry(name);
1243 : OutputThrowReferenceErrorIfHole(entry);
1244 282655 : return *this;
1245 : }
1246 :
1247 2170498 : BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperNotCalledIfHole() {
1248 : OutputThrowSuperNotCalledIfHole();
1249 2170498 : return *this;
1250 : }
1251 :
1252 2532 : BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperAlreadyCalledIfNotHole() {
1253 : OutputThrowSuperAlreadyCalledIfNotHole();
1254 2532 : return *this;
1255 : }
1256 :
1257 7561 : BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
1258 : OutputDebugger();
1259 7561 : return *this;
1260 : }
1261 :
1262 2511 : BytecodeArrayBuilder& BytecodeArrayBuilder::IncBlockCounter(
1263 : int coverage_array_slot) {
1264 : OutputIncBlockCounter(coverage_array_slot);
1265 2511 : return *this;
1266 : }
1267 :
1268 4749 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInEnumerate(Register receiver) {
1269 : OutputForInEnumerate(receiver);
1270 4752 : return *this;
1271 : }
1272 :
1273 4760 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
1274 : RegisterList cache_info_triple, int feedback_slot) {
1275 : DCHECK_EQ(3, cache_info_triple.register_count());
1276 : OutputForInPrepare(cache_info_triple, feedback_slot);
1277 4760 : return *this;
1278 : }
1279 :
1280 4750 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
1281 : Register index, Register cache_length) {
1282 : OutputForInContinue(index, cache_length);
1283 4752 : return *this;
1284 : }
1285 :
1286 4752 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
1287 : Register receiver, Register index, RegisterList cache_type_array_pair,
1288 : int feedback_slot) {
1289 : DCHECK_EQ(2, cache_type_array_pair.register_count());
1290 : OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
1291 4752 : return *this;
1292 : }
1293 :
1294 4752 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
1295 : OutputForInStep(index);
1296 4751 : return *this;
1297 : }
1298 :
1299 34738 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
1300 : int depth) {
1301 : OutputStaModuleVariable(cell_index, depth);
1302 34738 : return *this;
1303 : }
1304 :
1305 1435 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
1306 : int depth) {
1307 : OutputLdaModuleVariable(cell_index, depth);
1308 1435 : return *this;
1309 : }
1310 :
1311 23637 : BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
1312 : Register generator, RegisterList registers, int suspend_id) {
1313 : OutputSuspendGenerator(generator, registers, registers.register_count(),
1314 : suspend_id);
1315 23637 : return *this;
1316 : }
1317 :
1318 9179 : BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnGeneratorState(
1319 9179 : Register generator, BytecodeJumpTable* jump_table) {
1320 : DCHECK_EQ(jump_table->case_value_base(), 0);
1321 : BytecodeNode node(CreateSwitchOnGeneratorStateNode(
1322 : generator, jump_table->constant_pool_index(), jump_table->size()));
1323 9179 : WriteSwitch(&node, jump_table);
1324 : LeaveBasicBlock();
1325 9179 : return *this;
1326 : }
1327 :
1328 23637 : BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
1329 : Register generator, RegisterList registers) {
1330 : OutputResumeGenerator(generator, registers, registers.register_count());
1331 23636 : return *this;
1332 : }
1333 :
1334 154509 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
1335 : int handler_id, HandlerTable::CatchPrediction catch_prediction) {
1336 : BytecodeLabel handler;
1337 154509 : Bind(&handler);
1338 154538 : handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
1339 154542 : handler_table_builder()->SetPrediction(handler_id, catch_prediction);
1340 154541 : return *this;
1341 : }
1342 :
1343 154507 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
1344 : Register context) {
1345 : // TODO(leszeks): Do we need to start a new basic block here? Could we simply
1346 : // get the current bytecode offset from the array writer instead?
1347 : BytecodeLabel try_begin;
1348 154507 : Bind(&try_begin);
1349 154531 : handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
1350 154532 : handler_table_builder()->SetContextRegister(handler_id, context);
1351 154526 : return *this;
1352 : }
1353 :
1354 154511 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
1355 : BytecodeLabel try_end;
1356 154511 : Bind(&try_end);
1357 154532 : handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
1358 154531 : return *this;
1359 : }
1360 :
1361 628042 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable,
1362 : RegisterList args,
1363 : int feedback_slot) {
1364 628042 : if (args.register_count() == 1) {
1365 : OutputCallProperty0(callable, args[0], feedback_slot);
1366 437099 : } else if (args.register_count() == 2) {
1367 : OutputCallProperty1(callable, args[0], args[1], feedback_slot);
1368 104146 : } else if (args.register_count() == 3) {
1369 : OutputCallProperty2(callable, args[0], args[1], args[2], feedback_slot);
1370 : } else {
1371 : OutputCallProperty(callable, args, args.register_count(), feedback_slot);
1372 : }
1373 628119 : return *this;
1374 : }
1375 :
1376 3411196 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallUndefinedReceiver(
1377 : Register callable, RegisterList args, int feedback_slot) {
1378 3411196 : if (args.register_count() == 0) {
1379 : OutputCallUndefinedReceiver0(callable, feedback_slot);
1380 1008414 : } else if (args.register_count() == 1) {
1381 : OutputCallUndefinedReceiver1(callable, args[0], feedback_slot);
1382 637135 : } else if (args.register_count() == 2) {
1383 : OutputCallUndefinedReceiver2(callable, args[0], args[1], feedback_slot);
1384 : } else {
1385 : OutputCallUndefinedReceiver(callable, args, args.register_count(),
1386 : feedback_slot);
1387 : }
1388 3411267 : return *this;
1389 : }
1390 :
1391 3354 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
1392 : RegisterList args,
1393 : int feedback_slot) {
1394 : OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot);
1395 3354 : return *this;
1396 : }
1397 :
1398 1247097 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallNoFeedback(Register callable,
1399 : RegisterList args) {
1400 : OutputCallNoFeedback(callable, args, args.register_count());
1401 1247409 : return *this;
1402 : }
1403 :
1404 1811 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
1405 : RegisterList args,
1406 : int feedback_slot) {
1407 : OutputCallWithSpread(callable, args, args.register_count(), feedback_slot);
1408 1811 : return *this;
1409 : }
1410 :
1411 143376 : BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
1412 : RegisterList args,
1413 : int feedback_slot_id) {
1414 : OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
1415 143441 : return *this;
1416 : }
1417 :
1418 4104 : BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
1419 : Register constructor, RegisterList args, int feedback_slot_id) {
1420 : OutputConstructWithSpread(constructor, args, args.register_count(),
1421 : feedback_slot_id);
1422 4104 : return *this;
1423 : }
1424 :
1425 1219429 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1426 : Runtime::FunctionId function_id, RegisterList args) {
1427 : DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
1428 : DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
1429 : OperandSize::kShort);
1430 1219429 : if (IntrinsicsHelper::IsSupported(function_id)) {
1431 : IntrinsicsHelper::IntrinsicId intrinsic_id =
1432 70236 : IntrinsicsHelper::FromRuntimeId(function_id);
1433 : OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
1434 : args.register_count());
1435 : } else {
1436 : OutputCallRuntime(static_cast<int>(function_id), args,
1437 : args.register_count());
1438 : }
1439 1219650 : return *this;
1440 : }
1441 :
1442 405689 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1443 : Runtime::FunctionId function_id, Register arg) {
1444 405689 : return CallRuntime(function_id, RegisterList(arg));
1445 : }
1446 :
1447 88471 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1448 : Runtime::FunctionId function_id) {
1449 88471 : return CallRuntime(function_id, RegisterList());
1450 : }
1451 :
1452 4596 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1453 : Runtime::FunctionId function_id, RegisterList args,
1454 : RegisterList return_pair) {
1455 : DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
1456 : DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
1457 : OperandSize::kShort);
1458 : DCHECK_EQ(2, return_pair.register_count());
1459 : OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
1460 4596 : args.register_count(), return_pair);
1461 4596 : return *this;
1462 : }
1463 :
1464 4595 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1465 : Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
1466 4595 : return CallRuntimeForPair(function_id, RegisterList(arg), return_pair);
1467 : }
1468 :
1469 412 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
1470 : RegisterList args) {
1471 : OutputCallJSRuntime(context_index, args, args.register_count());
1472 414 : return *this;
1473 : }
1474 :
1475 4366 : BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
1476 : LanguageMode language_mode) {
1477 4366 : if (language_mode == LanguageMode::kSloppy) {
1478 : OutputDeletePropertySloppy(object);
1479 : } else {
1480 : DCHECK_EQ(language_mode, LanguageMode::kStrict);
1481 : OutputDeletePropertyStrict(object);
1482 : }
1483 4367 : return *this;
1484 : }
1485 :
1486 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(
1487 : const AstRawString* raw_string) {
1488 15295743 : return constant_array_builder()->Insert(raw_string);
1489 : }
1490 :
1491 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(AstBigInt bigint) {
1492 10426 : return constant_array_builder()->Insert(bigint);
1493 : }
1494 :
1495 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
1496 322513 : return constant_array_builder()->Insert(scope);
1497 : }
1498 :
1499 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(double number) {
1500 614778 : return constant_array_builder()->Insert(number);
1501 : }
1502 :
1503 : #define ENTRY_GETTER(NAME, ...) \
1504 : size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \
1505 : return constant_array_builder()->Insert##NAME(); \
1506 : }
1507 96975 : SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
1508 : #undef ENTRY_GETTER
1509 :
1510 20060 : BytecodeJumpTable* BytecodeArrayBuilder::AllocateJumpTable(
1511 20060 : int size, int case_value_base) {
1512 : DCHECK_GT(size, 0);
1513 :
1514 20060 : size_t constant_pool_index = constant_array_builder()->InsertJumpTable(size);
1515 :
1516 : return new (zone())
1517 20059 : BytecodeJumpTable(constant_pool_index, size, case_value_base, zone());
1518 : }
1519 :
1520 3142753 : size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
1521 3142753 : return constant_array_builder()->InsertDeferred();
1522 : }
1523 :
1524 2832278 : void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
1525 : Handle<Object> object) {
1526 2832278 : constant_array_builder()->SetDeferredAt(entry, object);
1527 2832270 : }
1528 :
1529 0 : bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
1530 0 : if (!reg.is_valid()) {
1531 : return false;
1532 : }
1533 :
1534 0 : if (reg.is_current_context() || reg.is_function_closure()) {
1535 : return true;
1536 0 : } else if (reg.is_parameter()) {
1537 0 : int parameter_index = reg.ToParameterIndex(parameter_count());
1538 0 : return parameter_index >= 0 && parameter_index < parameter_count();
1539 0 : } else if (reg.index() < fixed_register_count()) {
1540 : return true;
1541 : } else {
1542 0 : return register_allocator()->RegisterIsLive(reg);
1543 : }
1544 : }
1545 :
1546 0 : bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const {
1547 0 : if (reg_list.register_count() == 0) {
1548 : return reg_list.first_register() == Register(0);
1549 : } else {
1550 : int first_reg_index = reg_list.first_register().index();
1551 0 : for (int i = 0; i < reg_list.register_count(); i++) {
1552 0 : if (!RegisterIsValid(Register(first_reg_index + i))) {
1553 : return false;
1554 : }
1555 : }
1556 : return true;
1557 : }
1558 : }
1559 :
1560 : template <Bytecode bytecode, AccumulatorUse accumulator_use>
1561 54158179 : void BytecodeArrayBuilder::PrepareToOutputBytecode() {
1562 54158179 : if (register_optimizer_)
1563 : register_optimizer_->PrepareForBytecode<bytecode, accumulator_use>();
1564 54160013 : }
1565 :
1566 15812315 : uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
1567 : DCHECK(RegisterIsValid(reg));
1568 15812315 : if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
1569 15812308 : return static_cast<uint32_t>(reg.ToOperand());
1570 : }
1571 :
1572 347517 : uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
1573 : DCHECK(RegisterIsValid(reg));
1574 347517 : if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
1575 347517 : return static_cast<uint32_t>(reg.ToOperand());
1576 : }
1577 :
1578 2877764 : uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
1579 : RegisterList reg_list) {
1580 : DCHECK(RegisterListIsValid(reg_list));
1581 2877764 : if (register_optimizer_)
1582 2877112 : reg_list = register_optimizer_->GetInputRegisterList(reg_list);
1583 2877983 : return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1584 : }
1585 :
1586 32993 : uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
1587 : RegisterList reg_list) {
1588 : DCHECK(RegisterListIsValid(reg_list));
1589 32993 : if (register_optimizer_)
1590 32992 : register_optimizer_->PrepareOutputRegisterList(reg_list);
1591 32993 : return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1592 : }
1593 :
1594 0 : std::ostream& operator<<(std::ostream& os,
1595 : const BytecodeArrayBuilder::ToBooleanMode& mode) {
1596 0 : switch (mode) {
1597 : case BytecodeArrayBuilder::ToBooleanMode::kAlreadyBoolean:
1598 0 : return os << "AlreadyBoolean";
1599 : case BytecodeArrayBuilder::ToBooleanMode::kConvertToBoolean:
1600 0 : return os << "ConvertToBoolean";
1601 : }
1602 0 : UNREACHABLE();
1603 : }
1604 :
1605 : } // namespace interpreter
1606 : } // namespace internal
1607 183867 : } // namespace v8
|