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 3776826 : void EmitLdar(Register input) override { builder_->OutputLdarRaw(input); }
30 :
31 19942038 : void EmitStar(Register output) override { builder_->OutputStarRaw(output); }
32 :
33 1343551 : void EmitMov(Register input, Register output) override {
34 1343551 : builder_->OutputMovRaw(input, output);
35 1343591 : }
36 :
37 : private:
38 : BytecodeArrayBuilder* builder_;
39 : };
40 :
41 2107288 : 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 4214572 : register_optimizer_(nullptr) {
57 : DCHECK_GE(parameter_count_, 0);
58 : DCHECK_GE(local_register_count_, 0);
59 :
60 2107287 : if (FLAG_ignition_reo) {
61 : register_optimizer_ = new (zone) BytecodeRegisterOptimizer(
62 : zone, ®ister_allocator_, fixed_register_count(), parameter_count,
63 2106747 : new (zone) RegisterTransferWriter(this));
64 : }
65 2107301 : }
66 :
67 1434925 : 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 1434925 : return Register::FromParameterIndex(parameter_index + 1, parameter_count());
72 : }
73 :
74 2499794 : Register BytecodeArrayBuilder::Receiver() const {
75 2499794 : return Register::FromParameterIndex(0, parameter_count());
76 : }
77 :
78 4806027 : Register BytecodeArrayBuilder::Local(int index) const {
79 : // TODO(marja): Make a DCHECK once crbug.com/706234 is fixed.
80 4806027 : CHECK_LT(index, locals_count());
81 4806027 : return Register(index);
82 : }
83 :
84 4165935 : Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
85 : DCHECK(return_seen_in_block_);
86 : DCHECK(!bytecode_generated_);
87 2082965 : bytecode_generated_ = true;
88 :
89 : int register_count = total_register_count();
90 :
91 4165402 : if (register_optimizer_) {
92 2082431 : register_optimizer_->Flush();
93 4164874 : register_count = register_optimizer_->maxiumum_register_index() + 1;
94 : }
95 :
96 : Handle<ByteArray> handler_table =
97 2082971 : handler_table_builder()->ToHandlerTable(isolate);
98 : return bytecode_array_writer_.ToBytecodeArray(
99 2082970 : isolate, register_count, parameter_count(), handler_table);
100 : }
101 :
102 : BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
103 : Bytecode bytecode) {
104 86771682 : BytecodeSourceInfo source_position;
105 86771845 : 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 100898267 : if (latest_source_info_.is_statement() ||
111 62879691 : !FLAG_ignition_filter_expression_positions ||
112 24863100 : !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
113 31844149 : source_position = latest_source_info_;
114 31844149 : latest_source_info_.set_invalid();
115 : }
116 : }
117 86771995 : return source_position;
118 : }
119 :
120 0 : void BytecodeArrayBuilder::SetDeferredSourceInfo(
121 : BytecodeSourceInfo source_info) {
122 33254316 : if (!source_info.is_valid()) return;
123 3421863 : deferred_source_info_ = source_info;
124 : }
125 :
126 0 : void BytecodeArrayBuilder::AttachOrEmitDeferredSourceInfo(BytecodeNode* node) {
127 78530292 : if (!deferred_source_info_.is_valid()) return;
128 3415541 : if (!node->source_info().is_valid()) {
129 : node->set_source_info(deferred_source_info_);
130 388855 : } 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 76439590 : void BytecodeArrayBuilder::Write(BytecodeNode* node) {
140 : AttachOrEmitDeferredSourceInfo(node);
141 76439590 : bytecode_array_writer_.Write(node);
142 76450529 : }
143 :
144 2070444 : void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
145 : AttachOrEmitDeferredSourceInfo(node);
146 2070444 : bytecode_array_writer_.WriteJump(node, label);
147 2070497 : }
148 :
149 20258 : void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node,
150 : BytecodeJumpTable* jump_table) {
151 : AttachOrEmitDeferredSourceInfo(node);
152 20258 : bytecode_array_writer_.WriteSwitch(node, jump_table);
153 20258 : }
154 :
155 3776803 : void BytecodeArrayBuilder::OutputLdarRaw(Register reg) {
156 3776803 : uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
157 : BytecodeNode node(BytecodeNode::Ldar(BytecodeSourceInfo(), operand));
158 3776869 : Write(&node);
159 3776890 : }
160 :
161 19941799 : void BytecodeArrayBuilder::OutputStarRaw(Register reg) {
162 19941799 : uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
163 : BytecodeNode node(BytecodeNode::Star(BytecodeSourceInfo(), operand));
164 19940923 : Write(&node);
165 19939737 : }
166 :
167 1343550 : void BytecodeArrayBuilder::OutputMovRaw(Register src, Register dest) {
168 1343550 : uint32_t operand0 = static_cast<uint32_t>(src.ToOperand());
169 1343550 : uint32_t operand1 = static_cast<uint32_t>(dest.ToOperand());
170 : BytecodeNode node(
171 : BytecodeNode::Mov(BytecodeSourceInfo(), operand0, operand1));
172 1343567 : Write(&node);
173 1343593 : }
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 37287369 : 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 32191191 : 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 6660964 : 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 13088895 : 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 2806096 : 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 4740 : 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 344521 : 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 23609 : 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 4531 : 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 4751 : 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 1409921 : V8_INLINE static BytecodeNode Make(BytecodeArrayBuilder* builder,
299 : Operands... operands) {
300 : static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands,
301 : "too many operands for bytecode");
302 53516381 : 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 2356 : 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 53496269 : BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
339 : #undef DEFINE_BYTECODE_OUTPUT
340 :
341 : void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback(
342 32967 : BytecodeJumpTable* jump_table) {
343 : BytecodeNode node(CreateSwitchOnSmiNoFeedbackNode(
344 : jump_table->constant_pool_index(), jump_table->size(),
345 32967 : jump_table->case_value_base()));
346 10989 : WriteSwitch(&node, jump_table);
347 10989 : LeaveBasicBlock();
348 : }
349 :
350 643317 : BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
351 : Register reg,
352 : int feedback_slot) {
353 643317 : 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 643288 : return *this;
394 : }
395 :
396 185580 : BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
397 : Token::Value op, Smi literal, int feedback_slot) {
398 185580 : 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 185598 : return *this;
439 : }
440 :
441 308191 : BytecodeArrayBuilder& BytecodeArrayBuilder::UnaryOperation(Token::Value op,
442 : int feedback_slot) {
443 308191 : 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 308219 : return *this;
463 : }
464 :
465 29625 : BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
466 29625 : if (mode == ToBooleanMode::kAlreadyBoolean) {
467 : OutputLogicalNot();
468 : } else {
469 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
470 : OutputToBooleanLogicalNot();
471 : }
472 29628 : return *this;
473 : }
474 :
475 63024 : BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
476 : OutputTypeOf();
477 63026 : return *this;
478 : }
479 :
480 5290 : BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
481 : OutputGetSuperConstructor(out);
482 5291 : return *this;
483 : }
484 :
485 794231 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
486 : Token::Value op, Register reg, int feedback_slot) {
487 794231 : 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 794272 : return *this;
513 : }
514 :
515 2400 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
516 : Register reg) {
517 2400 : switch (op) {
518 : case Token::Value::IN:
519 : OutputTestIn(reg);
520 : break;
521 : default:
522 0 : UNREACHABLE();
523 : }
524 2401 : return *this;
525 : }
526 :
527 92588 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareReference(Register reg) {
528 : OutputTestReferenceEqual(reg);
529 92595 : return *this;
530 : }
531 :
532 3111 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndetectable() {
533 : OutputTestUndetectable();
534 3111 : return *this;
535 : }
536 :
537 9185 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndefined() {
538 : OutputTestUndefined();
539 9188 : return *this;
540 : }
541 :
542 1020 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNull() {
543 : OutputTestNull();
544 1020 : return *this;
545 : }
546 :
547 12064 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNil(Token::Value op,
548 : NilValue nil) {
549 12064 : if (op == Token::EQ) {
550 1861 : return CompareUndetectable();
551 : } else {
552 : DCHECK_EQ(Token::EQ_STRICT, op);
553 10203 : if (nil == kUndefinedValue) {
554 9184 : return CompareUndefined();
555 : } else {
556 : DCHECK_EQ(kNullValue, nil);
557 1019 : return CompareNull();
558 : }
559 : }
560 : }
561 :
562 137356 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
563 : TestTypeOfFlags::LiteralFlag literal_flag) {
564 : DCHECK_NE(literal_flag, TestTypeOfFlags::LiteralFlag::kOther);
565 137356 : OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
566 137364 : return *this;
567 : }
568 :
569 457913 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
570 : size_t entry) {
571 : OutputLdaConstant(entry);
572 457945 : return *this;
573 : }
574 :
575 7898369 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Smi smi) {
576 : int32_t raw_smi = smi->value();
577 7898369 : if (raw_smi == 0) {
578 : OutputLdaZero();
579 : } else {
580 : OutputLdaSmi(raw_smi);
581 : }
582 7898285 : return *this;
583 : }
584 :
585 611852 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(double value) {
586 : size_t entry = GetConstantPoolEntry(value);
587 : OutputLdaConstant(entry);
588 611861 : return *this;
589 : }
590 :
591 2003418 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
592 : const AstRawString* raw_string) {
593 : size_t entry = GetConstantPoolEntry(raw_string);
594 : OutputLdaConstant(entry);
595 2003433 : return *this;
596 : }
597 :
598 13024 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(const Scope* scope) {
599 : size_t entry = GetConstantPoolEntry(scope);
600 : OutputLdaConstant(entry);
601 13025 : return *this;
602 : }
603 :
604 10451 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(AstBigInt bigint) {
605 : size_t entry = GetConstantPoolEntry(bigint);
606 : OutputLdaConstant(entry);
607 10445 : 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 1484861 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
623 : OutputLdaUndefined();
624 1485101 : return *this;
625 : }
626 :
627 26053 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
628 : OutputLdaNull();
629 26057 : return *this;
630 : }
631 :
632 837901 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
633 : OutputLdaTheHole();
634 837915 : return *this;
635 : }
636 :
637 165097 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
638 : OutputLdaTrue();
639 165119 : return *this;
640 : }
641 :
642 286728 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
643 : OutputLdaFalse();
644 286747 : return *this;
645 : }
646 :
647 328475 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBoolean(bool value) {
648 328475 : return value ? LoadTrue() : LoadFalse();
649 : }
650 :
651 7630836 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
652 : Register reg) {
653 7630836 : 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 7629789 : register_optimizer_->DoLdar(reg);
658 : } else {
659 : OutputLdar(reg);
660 : }
661 7631004 : return *this;
662 : }
663 :
664 24902933 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
665 : Register reg) {
666 24902933 : 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 24899474 : register_optimizer_->DoStar(reg);
671 : } else {
672 : OutputStar(reg);
673 : }
674 24903482 : return *this;
675 : }
676 :
677 725368 : BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
678 : Register to) {
679 : DCHECK(from != to);
680 725368 : 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 725053 : register_optimizer_->DoMov(from, to);
685 : } else {
686 : OutputMov(from, to);
687 : }
688 725384 : return *this;
689 : }
690 :
691 5767438 : 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 5767392 : 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 5767334 : return *this;
706 : }
707 :
708 1438551 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
709 : const AstRawString* name, int feedback_slot) {
710 : size_t name_index = GetConstantPoolEntry(name);
711 : OutputStaGlobal(name_index, feedback_slot);
712 1438562 : return *this;
713 : }
714 :
715 1030036 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
716 : Register context, int slot_index, int depth,
717 : ContextSlotMutability mutability) {
718 1030036 : if (context.is_current_context() && depth == 0) {
719 932752 : if (mutability == kImmutableSlot) {
720 : OutputLdaImmutableCurrentContextSlot(slot_index);
721 : } else {
722 : DCHECK_EQ(kMutableSlot, mutability);
723 : OutputLdaCurrentContextSlot(slot_index);
724 : }
725 97288 : } 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 1030047 : return *this;
732 : }
733 :
734 2717414 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
735 : int slot_index,
736 : int depth) {
737 2717414 : if (context.is_current_context() && depth == 0) {
738 : OutputStaCurrentContextSlot(slot_index);
739 : } else {
740 : OutputStaContextSlot(context, slot_index, depth);
741 : }
742 2717428 : return *this;
743 : }
744 :
745 25834 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
746 : const AstRawString* name, TypeofMode typeof_mode) {
747 : size_t name_index = GetConstantPoolEntry(name);
748 25835 : 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 25835 : return *this;
755 : }
756 :
757 3379 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
758 : const AstRawString* name, TypeofMode typeof_mode, int slot_index,
759 : int depth) {
760 : size_t name_index = GetConstantPoolEntry(name);
761 3379 : 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 3379 : return *this;
768 : }
769 :
770 354328 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
771 : const AstRawString* name, TypeofMode typeof_mode, int feedback_slot,
772 : int depth) {
773 : size_t name_index = GetConstantPoolEntry(name);
774 354328 : 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 354327 : return *this;
781 : }
782 :
783 37245 : 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 37246 : StoreLookupSlotFlags::Encode(language_mode, lookup_hoisting_mode);
789 : OutputStaLookupSlot(name_index, flags);
790 37246 : return *this;
791 : }
792 :
793 1272526 : 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 1272561 : return *this;
798 : }
799 :
800 1248850 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyNoFeedback(
801 : Register object, const AstRawString* name) {
802 : size_t name_index = GetConstantPoolEntry(name);
803 : OutputLdaNamedPropertyNoFeedback(object, name_index);
804 1248911 : return *this;
805 : }
806 :
807 143228 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
808 : Register object, int feedback_slot) {
809 : OutputLdaKeyedProperty(object, feedback_slot);
810 143243 : return *this;
811 : }
812 :
813 39857 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
814 : Register object, int feedback_slot) {
815 : size_t name_index = IteratorSymbolConstantPoolEntry();
816 : OutputLdaNamedProperty(object, name_index, feedback_slot);
817 39862 : return *this;
818 : }
819 :
820 346 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
821 : Register object, int feedback_slot) {
822 : size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
823 : OutputLdaNamedProperty(object, name_index, feedback_slot);
824 346 : return *this;
825 : }
826 :
827 2354 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
828 : Register object, Register name, DataPropertyInLiteralFlags flags,
829 : int feedback_slot) {
830 : OutputStaDataPropertyInLiteral(object, name, flags, feedback_slot);
831 2356 : return *this;
832 : }
833 :
834 164 : BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
835 : OutputCollectTypeProfile(position);
836 164 : return *this;
837 : }
838 :
839 2279242 : 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 2279244 : return *this;
848 : }
849 :
850 2277591 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
851 : Register object, const AstRawString* name, int feedback_slot,
852 : LanguageMode language_mode) {
853 : size_t name_index = GetConstantPoolEntry(name);
854 2277592 : return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
855 : }
856 :
857 112862 : 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 112890 : return *this;
863 : }
864 :
865 240777 : 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 240798 : return *this;
874 : }
875 :
876 33770 : 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 33789 : return *this;
885 : }
886 :
887 222699 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreInArrayLiteral(
888 : Register array, Register index, int feedback_slot) {
889 : OutputStaInArrayLiteral(array, index, feedback_slot);
890 222698 : return *this;
891 : }
892 :
893 705 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreHomeObjectProperty(
894 : Register object, int feedback_slot, LanguageMode language_mode) {
895 : size_t name_index = HomeObjectSymbolConstantPoolEntry();
896 705 : return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
897 : }
898 :
899 946 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreClassFieldsInitializer(
900 : Register constructor, int feedback_slot) {
901 : size_t name_index = ClassFieldsSymbolConstantPoolEntry();
902 : return StoreNamedProperty(constructor, name_index, feedback_slot,
903 947 : LanguageMode::kStrict);
904 : }
905 :
906 856 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadClassFieldsInitializer(
907 : Register constructor, int feedback_slot) {
908 : size_t name_index = ClassFieldsSymbolConstantPoolEntry();
909 : OutputLdaNamedProperty(constructor, name_index, feedback_slot);
910 856 : return *this;
911 : }
912 :
913 2652064 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
914 : size_t shared_function_info_entry, int slot, int flags) {
915 : OutputCreateClosure(shared_function_info_entry, slot, flags);
916 2651973 : return *this;
917 : }
918 :
919 58499 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
920 : const Scope* scope) {
921 : size_t entry = GetConstantPoolEntry(scope);
922 : OutputCreateBlockContext(entry);
923 58503 : return *this;
924 : }
925 :
926 68827 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
927 : Register exception, const Scope* scope) {
928 : size_t scope_index = GetConstantPoolEntry(scope);
929 : OutputCreateCatchContext(exception, scope_index);
930 68843 : return *this;
931 : }
932 :
933 133988 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(
934 : const Scope* scope, int slots) {
935 : size_t scope_index = GetConstantPoolEntry(scope);
936 : OutputCreateFunctionContext(scope_index, slots);
937 133989 : return *this;
938 : }
939 :
940 42278 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(
941 : const Scope* scope, int slots) {
942 : size_t scope_index = GetConstantPoolEntry(scope);
943 : OutputCreateEvalContext(scope_index, slots);
944 42278 : return *this;
945 : }
946 :
947 2954 : 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 105050 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
955 : CreateArgumentsType type) {
956 105050 : 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 105049 : return *this;
970 : }
971 :
972 44889 : 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 44893 : return *this;
977 : }
978 :
979 138950 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyArrayLiteral(
980 : int literal_index) {
981 : OutputCreateEmptyArrayLiteral(literal_index);
982 138951 : return *this;
983 : }
984 :
985 29636 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
986 : size_t constant_elements_entry, int literal_index, int flags) {
987 : OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
988 29637 : return *this;
989 : }
990 :
991 2049 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayFromIterable() {
992 : OutputCreateArrayFromIterable();
993 2050 : return *this;
994 : }
995 :
996 86283 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
997 : size_t constant_properties_entry, int literal_index, int flags) {
998 : OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags);
999 86283 : return *this;
1000 : }
1001 :
1002 27619 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyObjectLiteral() {
1003 : OutputCreateEmptyObjectLiteral();
1004 27628 : return *this;
1005 : }
1006 :
1007 268 : BytecodeArrayBuilder& BytecodeArrayBuilder::CloneObject(Register source,
1008 : int flags,
1009 : int feedback_slot) {
1010 : OutputCloneObject(source, flags, feedback_slot);
1011 268 : return *this;
1012 : }
1013 :
1014 1918 : BytecodeArrayBuilder& BytecodeArrayBuilder::GetTemplateObject(
1015 : size_t template_object_description_entry, int feedback_slot) {
1016 : OutputGetTemplateObject(template_object_description_entry, feedback_slot);
1017 1918 : return *this;
1018 : }
1019 :
1020 319570 : BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
1021 : OutputPushContext(context);
1022 319590 : return *this;
1023 : }
1024 :
1025 329029 : BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
1026 : OutputPopContext(context);
1027 329043 : return *this;
1028 : }
1029 :
1030 7959 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToObject(Register out) {
1031 : OutputToObject(out);
1032 7965 : return *this;
1033 : }
1034 :
1035 8019 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToName(Register out) {
1036 : OutputToName(out);
1037 8020 : return *this;
1038 : }
1039 :
1040 10178 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToString() {
1041 : OutputToString();
1042 10178 : return *this;
1043 : }
1044 :
1045 1 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumber(int feedback_slot) {
1046 : OutputToNumber(feedback_slot);
1047 1 : return *this;
1048 : }
1049 :
1050 26825 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(int feedback_slot) {
1051 : OutputToNumeric(feedback_slot);
1052 26825 : return *this;
1053 : }
1054 :
1055 2665108 : 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 2665108 : if (register_optimizer_) register_optimizer_->Flush();
1059 2665183 : bytecode_array_writer_.BindLabel(label);
1060 : LeaveBasicBlock();
1061 2665202 : 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 46919 : 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 46919 : if (register_optimizer_) register_optimizer_->Flush();
1076 46919 : bytecode_array_writer_.BindJumpTableEntry(jump_table, case_value);
1077 : LeaveBasicBlock();
1078 46919 : return *this;
1079 : }
1080 :
1081 301292 : BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
1082 : DCHECK(!label->is_bound());
1083 : OutputJump(label, 0);
1084 301308 : return *this;
1085 : }
1086 :
1087 547205 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
1088 : BytecodeLabel* label) {
1089 : DCHECK(!label->is_bound());
1090 547205 : if (mode == ToBooleanMode::kAlreadyBoolean) {
1091 : OutputJumpIfTrue(label, 0);
1092 : } else {
1093 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1094 : OutputJumpIfToBooleanTrue(label, 0);
1095 : }
1096 547214 : return *this;
1097 : }
1098 :
1099 671122 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
1100 : BytecodeLabel* label) {
1101 : DCHECK(!label->is_bound());
1102 671122 : if (mode == ToBooleanMode::kAlreadyBoolean) {
1103 : OutputJumpIfFalse(label, 0);
1104 : } else {
1105 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1106 : OutputJumpIfToBooleanFalse(label, 0);
1107 : }
1108 671169 : return *this;
1109 : }
1110 :
1111 57060 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
1112 : DCHECK(!label->is_bound());
1113 : OutputJumpIfNull(label, 0);
1114 57070 : return *this;
1115 : }
1116 :
1117 541 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
1118 : BytecodeLabel* label) {
1119 : DCHECK(!label->is_bound());
1120 : OutputJumpIfNotNull(label, 0);
1121 541 : return *this;
1122 : }
1123 :
1124 86477 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
1125 : BytecodeLabel* label) {
1126 : DCHECK(!label->is_bound());
1127 : OutputJumpIfUndefined(label, 0);
1128 86492 : return *this;
1129 : }
1130 :
1131 25769 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotUndefined(
1132 : BytecodeLabel* label) {
1133 : DCHECK(!label->is_bound());
1134 : OutputJumpIfNotUndefined(label, 0);
1135 25772 : return *this;
1136 : }
1137 :
1138 38965 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
1139 : Token::Value op,
1140 : NilValue nil) {
1141 38965 : if (op == Token::EQ) {
1142 : // TODO(rmcilroy): Implement JumpIfUndetectable.
1143 233 : return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
1144 233 : label);
1145 : } else {
1146 : DCHECK_EQ(Token::EQ_STRICT, op);
1147 38732 : if (nil == kUndefinedValue) {
1148 36782 : return JumpIfUndefined(label);
1149 : } else {
1150 : DCHECK_EQ(kNullValue, nil);
1151 1950 : return JumpIfNull(label);
1152 : }
1153 : }
1154 : }
1155 :
1156 14428 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
1157 : Token::Value op,
1158 : NilValue nil) {
1159 14428 : if (op == Token::EQ) {
1160 : // TODO(rmcilroy): Implement JumpIfUndetectable.
1161 1016 : return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
1162 1016 : label);
1163 : } else {
1164 : DCHECK_EQ(Token::EQ_STRICT, op);
1165 13412 : if (nil == kUndefinedValue) {
1166 12873 : return JumpIfNotUndefined(label);
1167 : } else {
1168 : DCHECK_EQ(kNullValue, nil);
1169 539 : return JumpIfNotNull(label);
1170 : }
1171 : }
1172 : }
1173 :
1174 119474 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
1175 : BytecodeLabel* label) {
1176 : DCHECK(!label->is_bound());
1177 : OutputJumpIfJSReceiver(label, 0);
1178 119483 : return *this;
1179 : }
1180 :
1181 261435 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
1182 : int loop_depth) {
1183 : DCHECK(label->is_bound());
1184 : OutputJumpLoop(label, 0, loop_depth);
1185 261475 : return *this;
1186 : }
1187 :
1188 10989 : BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnSmiNoFeedback(
1189 : BytecodeJumpTable* jump_table) {
1190 : OutputSwitchOnSmiNoFeedback(jump_table);
1191 10989 : return *this;
1192 : }
1193 :
1194 2346541 : BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
1195 2346541 : 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 2346604 : return *this;
1210 : }
1211 :
1212 152104 : BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
1213 : OutputSetPendingMessage();
1214 152108 : return *this;
1215 : }
1216 :
1217 65739 : BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
1218 : OutputThrow();
1219 65743 : return *this;
1220 : }
1221 :
1222 88765 : BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
1223 : OutputReThrow();
1224 88770 : 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 2458864 : BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
1235 : OutputReturn();
1236 2459040 : return_seen_in_block_ = true;
1237 2459040 : return *this;
1238 : }
1239 :
1240 300331 : BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowReferenceErrorIfHole(
1241 : const AstRawString* name) {
1242 : size_t entry = GetConstantPoolEntry(name);
1243 : OutputThrowReferenceErrorIfHole(entry);
1244 300334 : return *this;
1245 : }
1246 :
1247 2169589 : BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperNotCalledIfHole() {
1248 : OutputThrowSuperNotCalledIfHole();
1249 2169589 : return *this;
1250 : }
1251 :
1252 2524 : BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperAlreadyCalledIfNotHole() {
1253 : OutputThrowSuperAlreadyCalledIfNotHole();
1254 2524 : return *this;
1255 : }
1256 :
1257 7590 : BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
1258 : OutputDebugger();
1259 7591 : return *this;
1260 : }
1261 :
1262 2009 : BytecodeArrayBuilder& BytecodeArrayBuilder::IncBlockCounter(
1263 : int coverage_array_slot) {
1264 : OutputIncBlockCounter(coverage_array_slot);
1265 2009 : return *this;
1266 : }
1267 :
1268 4738 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInEnumerate(Register receiver) {
1269 : OutputForInEnumerate(receiver);
1270 4743 : return *this;
1271 : }
1272 :
1273 4751 : 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 4751 : return *this;
1278 : }
1279 :
1280 4741 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
1281 : Register index, Register cache_length) {
1282 : OutputForInContinue(index, cache_length);
1283 4743 : return *this;
1284 : }
1285 :
1286 4742 : 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 4743 : return *this;
1292 : }
1293 :
1294 4739 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
1295 : OutputForInStep(index);
1296 4742 : return *this;
1297 : }
1298 :
1299 34815 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
1300 : int depth) {
1301 : OutputStaModuleVariable(cell_index, depth);
1302 34815 : return *this;
1303 : }
1304 :
1305 1432 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
1306 : int depth) {
1307 : OutputLdaModuleVariable(cell_index, depth);
1308 1432 : return *this;
1309 : }
1310 :
1311 23608 : BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
1312 : Register generator, RegisterList registers, int suspend_id) {
1313 : OutputSuspendGenerator(generator, registers, registers.register_count(),
1314 : suspend_id);
1315 23609 : return *this;
1316 : }
1317 :
1318 9269 : BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnGeneratorState(
1319 9269 : 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 9269 : WriteSwitch(&node, jump_table);
1324 : LeaveBasicBlock();
1325 9269 : return *this;
1326 : }
1327 :
1328 23609 : BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
1329 : Register generator, RegisterList registers) {
1330 : OutputResumeGenerator(generator, registers, registers.register_count());
1331 23609 : return *this;
1332 : }
1333 :
1334 148676 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
1335 : int handler_id, HandlerTable::CatchPrediction catch_prediction) {
1336 : BytecodeLabel handler;
1337 148676 : Bind(&handler);
1338 148689 : handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
1339 148691 : handler_table_builder()->SetPrediction(handler_id, catch_prediction);
1340 148693 : return *this;
1341 : }
1342 :
1343 148671 : 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 148671 : Bind(&try_begin);
1349 148691 : handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
1350 148689 : handler_table_builder()->SetContextRegister(handler_id, context);
1351 148689 : return *this;
1352 : }
1353 :
1354 148668 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
1355 : BytecodeLabel try_end;
1356 148668 : Bind(&try_end);
1357 148692 : handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
1358 148693 : return *this;
1359 : }
1360 :
1361 606176 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable,
1362 : RegisterList args,
1363 : int feedback_slot) {
1364 606176 : if (args.register_count() == 1) {
1365 : OutputCallProperty0(callable, args[0], feedback_slot);
1366 423909 : } else if (args.register_count() == 2) {
1367 : OutputCallProperty1(callable, args[0], args[1], feedback_slot);
1368 100656 : } 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 606197 : return *this;
1374 : }
1375 :
1376 3399733 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallUndefinedReceiver(
1377 : Register callable, RegisterList args, int feedback_slot) {
1378 3399733 : if (args.register_count() == 0) {
1379 : OutputCallUndefinedReceiver0(callable, feedback_slot);
1380 995763 : } else if (args.register_count() == 1) {
1381 : OutputCallUndefinedReceiver1(callable, args[0], feedback_slot);
1382 606887 : } 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 3399772 : return *this;
1389 : }
1390 :
1391 3272 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
1392 : RegisterList args,
1393 : int feedback_slot) {
1394 : OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot);
1395 3272 : return *this;
1396 : }
1397 :
1398 1215016 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallNoFeedback(Register callable,
1399 : RegisterList args) {
1400 : OutputCallNoFeedback(callable, args, args.register_count());
1401 1215130 : return *this;
1402 : }
1403 :
1404 1710 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
1405 : RegisterList args,
1406 : int feedback_slot) {
1407 : OutputCallWithSpread(callable, args, args.register_count(), feedback_slot);
1408 1710 : return *this;
1409 : }
1410 :
1411 139076 : BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
1412 : RegisterList args,
1413 : int feedback_slot_id) {
1414 : OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
1415 139117 : return *this;
1416 : }
1417 :
1418 4113 : BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
1419 : Register constructor, RegisterList args, int feedback_slot_id) {
1420 : OutputConstructWithSpread(constructor, args, args.register_count(),
1421 : feedback_slot_id);
1422 4114 : return *this;
1423 : }
1424 :
1425 1199929 : 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 1199929 : if (IntrinsicsHelper::IsSupported(function_id)) {
1431 : IntrinsicsHelper::IntrinsicId intrinsic_id =
1432 69967 : 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 1199995 : return *this;
1440 : }
1441 :
1442 398599 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1443 : Runtime::FunctionId function_id, Register arg) {
1444 398599 : return CallRuntime(function_id, RegisterList(arg));
1445 : }
1446 :
1447 85734 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1448 : Runtime::FunctionId function_id) {
1449 85734 : return CallRuntime(function_id, RegisterList());
1450 : }
1451 :
1452 4530 : 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 4530 : args.register_count(), return_pair);
1461 4532 : return *this;
1462 : }
1463 :
1464 4529 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1465 : Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
1466 4529 : return CallRuntimeForPair(function_id, RegisterList(arg), return_pair);
1467 : }
1468 :
1469 392 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
1470 : RegisterList args) {
1471 : OutputCallJSRuntime(context_index, args, args.register_count());
1472 393 : return *this;
1473 : }
1474 :
1475 4377 : BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
1476 : LanguageMode language_mode) {
1477 4377 : if (language_mode == LanguageMode::kSloppy) {
1478 : OutputDeletePropertySloppy(object);
1479 : } else {
1480 : DCHECK_EQ(language_mode, LanguageMode::kStrict);
1481 : OutputDeletePropertyStrict(object);
1482 : }
1483 4380 : return *this;
1484 : }
1485 :
1486 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(
1487 : const AstRawString* raw_string) {
1488 15128019 : return constant_array_builder()->Insert(raw_string);
1489 : }
1490 :
1491 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(AstBigInt bigint) {
1492 10451 : return constant_array_builder()->Insert(bigint);
1493 : }
1494 :
1495 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
1496 319570 : return constant_array_builder()->Insert(scope);
1497 : }
1498 :
1499 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(double number) {
1500 611852 : 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 99143 : SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
1508 : #undef ENTRY_GETTER
1509 :
1510 20258 : BytecodeJumpTable* BytecodeArrayBuilder::AllocateJumpTable(
1511 20258 : int size, int case_value_base) {
1512 : DCHECK_GT(size, 0);
1513 :
1514 20258 : size_t constant_pool_index = constant_array_builder()->InsertJumpTable(size);
1515 :
1516 : return new (zone())
1517 20258 : BytecodeJumpTable(constant_pool_index, size, case_value_base, zone());
1518 : }
1519 :
1520 3173112 : size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
1521 3173112 : return constant_array_builder()->InsertDeferred();
1522 : }
1523 :
1524 2841656 : void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
1525 : Handle<Object> object) {
1526 2841656 : constant_array_builder()->SetDeferredAt(entry, object);
1527 2841656 : }
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 53516194 : void BytecodeArrayBuilder::PrepareToOutputBytecode() {
1562 53516194 : if (register_optimizer_)
1563 : register_optimizer_->PrepareForBytecode<bytecode, accumulator_use>();
1564 53517074 : }
1565 :
1566 15635347 : uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
1567 : DCHECK(RegisterIsValid(reg));
1568 15635347 : if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
1569 15635387 : return static_cast<uint32_t>(reg.ToOperand());
1570 : }
1571 :
1572 344521 : uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
1573 : DCHECK(RegisterIsValid(reg));
1574 344521 : if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
1575 344520 : return static_cast<uint32_t>(reg.ToOperand());
1576 : }
1577 :
1578 2810657 : uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
1579 : RegisterList reg_list) {
1580 : DCHECK(RegisterListIsValid(reg_list));
1581 2810657 : if (register_optimizer_)
1582 2809998 : reg_list = register_optimizer_->GetInputRegisterList(reg_list);
1583 2810759 : return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1584 : }
1585 :
1586 32890 : uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
1587 : RegisterList reg_list) {
1588 : DCHECK(RegisterListIsValid(reg_list));
1589 32890 : if (register_optimizer_)
1590 32889 : register_optimizer_->PrepareOutputRegisterList(reg_list);
1591 32892 : 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 178779 : } // namespace v8
|