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 :
17 : namespace v8 {
18 : namespace internal {
19 : namespace interpreter {
20 :
21 : class RegisterTransferWriter final
22 : : public NON_EXPORTED_BASE(BytecodeRegisterOptimizer::BytecodeWriter),
23 : public NON_EXPORTED_BASE(ZoneObject) {
24 : public:
25 2154155 : RegisterTransferWriter(BytecodeArrayBuilder* builder) : builder_(builder) {}
26 0 : ~RegisterTransferWriter() override {}
27 :
28 2384671 : void EmitLdar(Register input) override { builder_->OutputLdarRaw(input); }
29 :
30 19054270 : void EmitStar(Register output) override { builder_->OutputStarRaw(output); }
31 :
32 1698720 : void EmitMov(Register input, Register output) override {
33 1698720 : builder_->OutputMovRaw(input, output);
34 1698720 : }
35 :
36 : private:
37 : BytecodeArrayBuilder* builder_;
38 : };
39 :
40 2154788 : BytecodeArrayBuilder::BytecodeArrayBuilder(
41 : Isolate* isolate, Zone* zone, int parameter_count, int locals_count,
42 : FeedbackVectorSpec* feedback_vector_spec,
43 : SourcePositionTableBuilder::RecordingMode source_position_mode)
44 : : zone_(zone),
45 : feedback_vector_spec_(feedback_vector_spec),
46 : bytecode_generated_(false),
47 : constant_array_builder_(zone),
48 : handler_table_builder_(zone),
49 : return_seen_in_block_(false),
50 : parameter_count_(parameter_count),
51 : local_register_count_(locals_count),
52 : register_allocator_(fixed_register_count()),
53 : bytecode_array_writer_(zone, &constant_array_builder_,
54 : source_position_mode),
55 4309578 : register_optimizer_(nullptr) {
56 : DCHECK_GE(parameter_count_, 0);
57 : DCHECK_GE(local_register_count_, 0);
58 :
59 2154794 : if (FLAG_ignition_reo) {
60 : register_optimizer_ = new (zone) BytecodeRegisterOptimizer(
61 : zone, ®ister_allocator_, fixed_register_count(), parameter_count,
62 2154155 : new (zone) RegisterTransferWriter(this));
63 : }
64 2154793 : }
65 :
66 2178086 : Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
67 : DCHECK_GE(parameter_index, 0);
68 : // The parameter indices are shifted by 1 (receiver is the
69 : // first entry).
70 2178086 : return Register::FromParameterIndex(parameter_index + 1, parameter_count());
71 : }
72 :
73 505592 : Register BytecodeArrayBuilder::Receiver() const {
74 505592 : return Register::FromParameterIndex(0, parameter_count());
75 : }
76 :
77 6472262 : Register BytecodeArrayBuilder::Local(int index) const {
78 : // TODO(marja): Make a DCHECK once crbug.com/706234 is fixed.
79 6472262 : CHECK_LT(index, locals_count());
80 6472262 : return Register(index);
81 : }
82 :
83 4307743 : Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
84 : DCHECK(return_seen_in_block_);
85 : DCHECK(!bytecode_generated_);
86 2153871 : bytecode_generated_ = true;
87 :
88 : int register_count = total_register_count();
89 :
90 4307104 : if (register_optimizer_) {
91 2153233 : register_optimizer_->Flush();
92 4306466 : register_count = register_optimizer_->maxiumum_register_index() + 1;
93 : }
94 :
95 : Handle<FixedArray> handler_table =
96 2153871 : handler_table_builder()->ToHandlerTable(isolate);
97 : return bytecode_array_writer_.ToBytecodeArray(
98 2153872 : isolate, register_count, parameter_count(), handler_table);
99 : }
100 :
101 : BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
102 : Bytecode bytecode) {
103 79098993 : BytecodeSourceInfo source_position;
104 79099000 : if (latest_source_info_.is_valid()) {
105 : // Statement positions need to be emitted immediately. Expression
106 : // positions can be pushed back until a bytecode is found that can
107 : // throw (if expression position filtering is turned on). We only
108 : // invalidate the existing source position information if it is used.
109 97315439 : if (latest_source_info_.is_statement() ||
110 60748557 : !FLAG_ignition_filter_expression_positions ||
111 24184391 : !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
112 28119061 : source_position = latest_source_info_;
113 28119061 : latest_source_info_.set_invalid();
114 : }
115 : }
116 79099009 : return source_position;
117 : }
118 :
119 0 : void BytecodeArrayBuilder::SetDeferredSourceInfo(
120 : BytecodeSourceInfo source_info) {
121 31744009 : if (!source_info.is_valid()) return;
122 2043543 : deferred_source_info_ = source_info;
123 : }
124 :
125 0 : void BytecodeArrayBuilder::AttachOrEmitDeferredSourceInfo(BytecodeNode* node) {
126 70492384 : if (!deferred_source_info_.is_valid()) return;
127 2033066 : if (!node->source_info().is_valid()) {
128 : node->set_source_info(deferred_source_info_);
129 605477 : } else if (deferred_source_info_.is_statement() &&
130 : node->source_info().is_expression()) {
131 : BytecodeSourceInfo source_position = node->source_info();
132 : source_position.MakeStatementPosition(source_position.source_position());
133 : node->set_source_info(source_position);
134 : }
135 : deferred_source_info_.set_invalid();
136 : }
137 :
138 68014072 : void BytecodeArrayBuilder::Write(BytecodeNode* node) {
139 : AttachOrEmitDeferredSourceInfo(node);
140 68014072 : bytecode_array_writer_.Write(node);
141 68014165 : }
142 :
143 2449618 : void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
144 : AttachOrEmitDeferredSourceInfo(node);
145 2449618 : bytecode_array_writer_.WriteJump(node, label);
146 2449619 : }
147 :
148 28694 : void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node,
149 : BytecodeJumpTable* jump_table) {
150 : AttachOrEmitDeferredSourceInfo(node);
151 28694 : bytecode_array_writer_.WriteSwitch(node, jump_table);
152 28694 : }
153 :
154 2384671 : void BytecodeArrayBuilder::OutputLdarRaw(Register reg) {
155 2384671 : uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
156 : BytecodeNode node(BytecodeNode::Ldar(BytecodeSourceInfo(), operand));
157 2384672 : Write(&node);
158 2384672 : }
159 :
160 19054270 : void BytecodeArrayBuilder::OutputStarRaw(Register reg) {
161 19054270 : uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
162 : BytecodeNode node(BytecodeNode::Star(BytecodeSourceInfo(), operand));
163 19054273 : Write(&node);
164 19054277 : }
165 :
166 1698720 : void BytecodeArrayBuilder::OutputMovRaw(Register src, Register dest) {
167 1698720 : uint32_t operand0 = static_cast<uint32_t>(src.ToOperand());
168 1698720 : uint32_t operand1 = static_cast<uint32_t>(dest.ToOperand());
169 : BytecodeNode node(
170 : BytecodeNode::Mov(BytecodeSourceInfo(), operand0, operand1));
171 1698720 : Write(&node);
172 1698720 : }
173 :
174 : namespace {
175 :
176 : template <OperandTypeInfo type_info>
177 : class UnsignedOperandHelper {
178 : public:
179 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, size_t value)) {
180 : DCHECK(IsValid(value));
181 37889594 : return static_cast<uint32_t>(value);
182 : }
183 :
184 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
185 : DCHECK_GE(value, 0);
186 34042100 : return Convert(builder, static_cast<size_t>(value));
187 : }
188 :
189 : private:
190 : static bool IsValid(size_t value) {
191 : switch (type_info) {
192 : case OperandTypeInfo::kFixedUnsignedByte:
193 : return value <= kMaxUInt8;
194 : case OperandTypeInfo::kFixedUnsignedShort:
195 : return value <= kMaxUInt16;
196 : case OperandTypeInfo::kScalableUnsignedByte:
197 : return value <= kMaxUInt32;
198 : default:
199 : UNREACHABLE();
200 : }
201 : }
202 : };
203 :
204 : template <OperandType>
205 : class OperandHelper {};
206 :
207 : #define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \
208 : template <> \
209 : class OperandHelper<OperandType::k##Name> \
210 : : public UnsignedOperandHelper<Type> {};
211 : UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
212 : UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
213 : #undef DEFINE_UNSIGNED_OPERAND_HELPER
214 :
215 : template <>
216 : class OperandHelper<OperandType::kImm> {
217 : public:
218 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
219 5170098 : return static_cast<uint32_t>(value);
220 : }
221 : };
222 :
223 : template <>
224 : class OperandHelper<OperandType::kReg> {
225 : public:
226 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) {
227 11748077 : return builder->GetInputRegisterOperand(reg);
228 : }
229 : };
230 :
231 : template <>
232 : class OperandHelper<OperandType::kRegList> {
233 : public:
234 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
235 : RegisterList reg_list)) {
236 1806235 : return builder->GetInputRegisterListOperand(reg_list);
237 : }
238 : };
239 :
240 : template <>
241 : class OperandHelper<OperandType::kRegPair> {
242 : public:
243 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
244 : RegisterList reg_list)) {
245 : DCHECK_EQ(reg_list.register_count(), 2);
246 6073 : return builder->GetInputRegisterListOperand(reg_list);
247 : }
248 : };
249 :
250 : template <>
251 : class OperandHelper<OperandType::kRegOut> {
252 : public:
253 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) {
254 634853 : return builder->GetOutputRegisterOperand(reg);
255 : }
256 : };
257 :
258 : template <>
259 : class OperandHelper<OperandType::kRegOutList> {
260 : public:
261 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
262 : RegisterList reg_list)) {
263 20047 : return builder->GetOutputRegisterListOperand(reg_list);
264 : }
265 : };
266 :
267 : template <>
268 : class OperandHelper<OperandType::kRegOutPair> {
269 : public:
270 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
271 : RegisterList reg_list)) {
272 : DCHECK_EQ(2, reg_list.register_count());
273 2150 : return builder->GetOutputRegisterListOperand(reg_list);
274 : }
275 : };
276 :
277 : template <>
278 : class OperandHelper<OperandType::kRegOutTriple> {
279 : public:
280 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
281 : RegisterList reg_list)) {
282 : DCHECK_EQ(3, reg_list.register_count());
283 6081 : return builder->GetOutputRegisterListOperand(reg_list);
284 : }
285 : };
286 :
287 : } // namespace
288 :
289 : template <Bytecode bytecode, AccumulatorUse accumulator_use,
290 : OperandType... operand_types>
291 : class BytecodeNodeBuilder {
292 : public:
293 : template <typename... Operands>
294 1534982 : INLINE(static BytecodeNode Make(BytecodeArrayBuilder* builder,
295 : Operands... operands)) {
296 : static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands,
297 : "too many operands for bytecode");
298 47354985 : builder->PrepareToOutputBytecode<bytecode, accumulator_use>();
299 : // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
300 : // expand both the OperandType... and Operands... parameter packs e.g. for:
301 : // BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
302 : // Register, int>(..., Register reg, int immediate)
303 : // the code will expand into:
304 : // OperandHelper<OperandType::kReg>::Convert(builder, reg),
305 : // OperandHelper<OperandType::kImm>::Convert(builder, immediate),
306 : return BytecodeNode::Create<bytecode, accumulator_use, operand_types...>(
307 : builder->CurrentSourcePosition(bytecode),
308 401142 : OperandHelper<operand_types>::Convert(builder, operands)...);
309 : }
310 : };
311 :
312 : #define DEFINE_BYTECODE_OUTPUT(name, ...) \
313 : template <typename... Operands> \
314 : BytecodeNode BytecodeArrayBuilder::Create##name##Node( \
315 : Operands... operands) { \
316 : return BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make( \
317 : this, operands...); \
318 : } \
319 : \
320 : template <typename... Operands> \
321 : void BytecodeArrayBuilder::Output##name(Operands... operands) { \
322 : BytecodeNode node(Create##name##Node(operands...)); \
323 : Write(&node); \
324 : } \
325 : \
326 : template <typename... Operands> \
327 : void BytecodeArrayBuilder::Output##name(BytecodeLabel* label, \
328 : Operands... operands) { \
329 : DCHECK(Bytecodes::IsJump(Bytecode::k##name)); \
330 : BytecodeNode node(Create##name##Node(operands...)); \
331 : WriteJump(&node, label); \
332 : LeaveBasicBlock(); \
333 : }
334 47326307 : BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
335 : #undef DEFINE_BYTECODE_OUTPUT
336 :
337 : void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback(
338 86082 : BytecodeJumpTable* jump_table) {
339 : BytecodeNode node(CreateSwitchOnSmiNoFeedbackNode(
340 : jump_table->constant_pool_index(), jump_table->size(),
341 86082 : jump_table->case_value_base()));
342 28694 : WriteSwitch(&node, jump_table);
343 28694 : LeaveBasicBlock();
344 : }
345 :
346 709699 : BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
347 : Register reg,
348 : int feedback_slot) {
349 709699 : switch (op) {
350 : case Token::Value::ADD:
351 : OutputAdd(reg, feedback_slot);
352 : break;
353 : case Token::Value::SUB:
354 : OutputSub(reg, feedback_slot);
355 : break;
356 : case Token::Value::MUL:
357 : OutputMul(reg, feedback_slot);
358 : break;
359 : case Token::Value::DIV:
360 : OutputDiv(reg, feedback_slot);
361 : break;
362 : case Token::Value::MOD:
363 : OutputMod(reg, feedback_slot);
364 : break;
365 : case Token::Value::BIT_OR:
366 : OutputBitwiseOr(reg, feedback_slot);
367 : break;
368 : case Token::Value::BIT_XOR:
369 : OutputBitwiseXor(reg, feedback_slot);
370 : break;
371 : case Token::Value::BIT_AND:
372 : OutputBitwiseAnd(reg, feedback_slot);
373 : break;
374 : case Token::Value::SHL:
375 : OutputShiftLeft(reg, feedback_slot);
376 : break;
377 : case Token::Value::SAR:
378 : OutputShiftRight(reg, feedback_slot);
379 : break;
380 : case Token::Value::SHR:
381 : OutputShiftRightLogical(reg, feedback_slot);
382 : break;
383 : default:
384 0 : UNREACHABLE();
385 : }
386 709700 : return *this;
387 : }
388 :
389 207306 : BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
390 : Token::Value op, Smi* literal, int feedback_slot) {
391 207306 : switch (op) {
392 : case Token::Value::ADD:
393 : OutputAddSmi(literal->value(), feedback_slot);
394 : break;
395 : case Token::Value::SUB:
396 : OutputSubSmi(literal->value(), feedback_slot);
397 : break;
398 : case Token::Value::MUL:
399 : OutputMulSmi(literal->value(), feedback_slot);
400 : break;
401 : case Token::Value::DIV:
402 : OutputDivSmi(literal->value(), feedback_slot);
403 : break;
404 : case Token::Value::MOD:
405 : OutputModSmi(literal->value(), feedback_slot);
406 : break;
407 : case Token::Value::BIT_OR:
408 : OutputBitwiseOrSmi(literal->value(), feedback_slot);
409 : break;
410 : case Token::Value::BIT_XOR:
411 : OutputBitwiseXorSmi(literal->value(), feedback_slot);
412 : break;
413 : case Token::Value::BIT_AND:
414 : OutputBitwiseAndSmi(literal->value(), feedback_slot);
415 : break;
416 : case Token::Value::SHL:
417 : OutputShiftLeftSmi(literal->value(), feedback_slot);
418 : break;
419 : case Token::Value::SAR:
420 : OutputShiftRightSmi(literal->value(), feedback_slot);
421 : break;
422 : case Token::Value::SHR:
423 : OutputShiftRightLogicalSmi(literal->value(), feedback_slot);
424 : break;
425 : default:
426 0 : UNREACHABLE();
427 : }
428 207306 : return *this;
429 : }
430 :
431 253726 : BytecodeArrayBuilder& BytecodeArrayBuilder::UnaryOperation(Token::Value op,
432 : int feedback_slot) {
433 253726 : switch (op) {
434 : case Token::Value::INC:
435 : OutputInc(feedback_slot);
436 : break;
437 : case Token::Value::DEC:
438 : OutputDec(feedback_slot);
439 : break;
440 : case Token::Value::ADD:
441 : OutputToNumber(feedback_slot);
442 : break;
443 : case Token::Value::SUB:
444 : OutputNegate(feedback_slot);
445 : break;
446 : case Token::Value::BIT_NOT:
447 : OutputBitwiseNot(feedback_slot);
448 : break;
449 : default:
450 0 : UNREACHABLE();
451 : }
452 253726 : return *this;
453 : }
454 :
455 61449 : BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
456 61449 : if (mode == ToBooleanMode::kAlreadyBoolean) {
457 : OutputLogicalNot();
458 : } else {
459 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
460 : OutputToBooleanLogicalNot();
461 : }
462 61449 : return *this;
463 : }
464 :
465 57825 : BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
466 : OutputTypeOf();
467 57825 : return *this;
468 : }
469 :
470 3763 : BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
471 : OutputGetSuperConstructor(out);
472 3763 : return *this;
473 : }
474 :
475 959147 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
476 : Token::Value op, Register reg, int feedback_slot) {
477 959147 : switch (op) {
478 : case Token::Value::EQ:
479 : OutputTestEqual(reg, feedback_slot);
480 : break;
481 : case Token::Value::EQ_STRICT:
482 : OutputTestEqualStrict(reg, feedback_slot);
483 : break;
484 : case Token::Value::LT:
485 : OutputTestLessThan(reg, feedback_slot);
486 : break;
487 : case Token::Value::GT:
488 : OutputTestGreaterThan(reg, feedback_slot);
489 : break;
490 : case Token::Value::LTE:
491 : OutputTestLessThanOrEqual(reg, feedback_slot);
492 : break;
493 : case Token::Value::GTE:
494 : OutputTestGreaterThanOrEqual(reg, feedback_slot);
495 : break;
496 : default:
497 0 : UNREACHABLE();
498 : }
499 959147 : return *this;
500 : }
501 :
502 68189 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
503 : Register reg) {
504 68189 : switch (op) {
505 : case Token::Value::EQ_STRICT:
506 : OutputTestEqualStrictNoFeedback(reg);
507 : break;
508 : case Token::Value::INSTANCEOF:
509 : OutputTestInstanceOf(reg);
510 : break;
511 : case Token::Value::IN:
512 : OutputTestIn(reg);
513 : break;
514 : default:
515 0 : UNREACHABLE();
516 : }
517 68189 : return *this;
518 : }
519 :
520 32054 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndetectable() {
521 : OutputTestUndetectable();
522 32054 : return *this;
523 : }
524 :
525 8935 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndefined() {
526 : OutputTestUndefined();
527 8935 : return *this;
528 : }
529 :
530 1032 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNull() {
531 : OutputTestNull();
532 1032 : return *this;
533 : }
534 :
535 11839 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNil(Token::Value op,
536 : NilValue nil) {
537 11839 : if (op == Token::EQ) {
538 1874 : return CompareUndetectable();
539 : } else {
540 : DCHECK_EQ(Token::EQ_STRICT, op);
541 9965 : if (nil == kUndefinedValue) {
542 8934 : return CompareUndefined();
543 : } else {
544 : DCHECK_EQ(kNullValue, nil);
545 1031 : return CompareNull();
546 : }
547 : }
548 : }
549 :
550 145417 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
551 : TestTypeOfFlags::LiteralFlag literal_flag) {
552 : DCHECK_NE(literal_flag, TestTypeOfFlags::LiteralFlag::kOther);
553 145417 : OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
554 145417 : return *this;
555 : }
556 :
557 88918 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
558 : size_t entry) {
559 : OutputLdaConstant(entry);
560 88918 : return *this;
561 : }
562 :
563 6125631 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
564 : v8::internal::Smi* smi) {
565 : int32_t raw_smi = smi->value();
566 6125631 : if (raw_smi == 0) {
567 : OutputLdaZero();
568 : } else {
569 : OutputLdaSmi(raw_smi);
570 : }
571 6125632 : return *this;
572 : }
573 :
574 2458519 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
575 : const AstRawString* raw_string) {
576 : size_t entry = GetConstantPoolEntry(raw_string);
577 : OutputLdaConstant(entry);
578 2458520 : return *this;
579 : }
580 :
581 8659 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(const Scope* scope) {
582 : size_t entry = GetConstantPoolEntry(scope);
583 : OutputLdaConstant(entry);
584 8659 : return *this;
585 : }
586 :
587 8409022 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
588 8409022 : const AstValue* ast_value) {
589 8409022 : if (ast_value->IsSmi()) {
590 5037680 : return LoadLiteral(ast_value->AsSmi());
591 3371342 : } else if (ast_value->IsUndefined()) {
592 121061 : return LoadUndefined();
593 3250281 : } else if (ast_value->IsTrue()) {
594 119650 : return LoadTrue();
595 3130631 : } else if (ast_value->IsFalse()) {
596 211012 : return LoadFalse();
597 2919619 : } else if (ast_value->IsNull()) {
598 31534 : return LoadNull();
599 2888085 : } else if (ast_value->IsTheHole()) {
600 0 : return LoadTheHole();
601 2888085 : } else if (ast_value->IsString()) {
602 2159802 : return LoadLiteral(ast_value->AsString());
603 728283 : } else if (ast_value->IsHeapNumber() || ast_value->IsBigInt()) {
604 : size_t entry = GetConstantPoolEntry(ast_value);
605 : OutputLdaConstant(entry);
606 726438 : return *this;
607 : } else {
608 : // This should be the only ast value type left.
609 : DCHECK(ast_value->IsSymbol());
610 : size_t entry;
611 1845 : switch (ast_value->AsSymbol()) {
612 : case AstSymbol::kHomeObjectSymbol:
613 : entry = HomeObjectSymbolConstantPoolEntry();
614 1845 : break;
615 : // No default case so that we get a warning if AstSymbol changes
616 : }
617 : OutputLdaConstant(entry);
618 1845 : return *this;
619 : }
620 : }
621 :
622 619088 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
623 : OutputLdaUndefined();
624 619088 : return *this;
625 : }
626 :
627 34962 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
628 : OutputLdaNull();
629 34962 : return *this;
630 : }
631 :
632 579310 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
633 : OutputLdaTheHole();
634 579310 : return *this;
635 : }
636 :
637 122001 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
638 : OutputLdaTrue();
639 122001 : return *this;
640 : }
641 :
642 215999 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
643 : OutputLdaFalse();
644 215999 : return *this;
645 : }
646 :
647 371 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBoolean(bool value) {
648 371 : return value ? LoadTrue() : LoadFalse();
649 : }
650 :
651 7838618 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
652 : Register reg) {
653 7838618 : 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 7836234 : register_optimizer_->DoLdar(reg);
658 : } else {
659 : OutputLdar(reg);
660 : }
661 7838628 : return *this;
662 : }
663 :
664 23185709 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
665 : Register reg) {
666 23185709 : 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 23181004 : register_optimizer_->DoStar(reg);
671 : } else {
672 : OutputStar(reg);
673 : }
674 23185719 : return *this;
675 : }
676 :
677 727221 : BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
678 : Register to) {
679 : DCHECK(from != to);
680 727221 : 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 726771 : register_optimizer_->DoMov(from, to);
685 : } else {
686 : OutputMov(from, to);
687 : }
688 727221 : return *this;
689 : }
690 :
691 2431448 : 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 2431448 : 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 2431448 : return *this;
706 : }
707 :
708 1064787 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
709 : const AstRawString* name, int feedback_slot, LanguageMode language_mode) {
710 : size_t name_index = GetConstantPoolEntry(name);
711 1064787 : if (language_mode == LanguageMode::kSloppy) {
712 : OutputStaGlobalSloppy(name_index, feedback_slot);
713 : } else {
714 : DCHECK_EQ(language_mode, LanguageMode::kStrict);
715 : OutputStaGlobalStrict(name_index, feedback_slot);
716 : }
717 1064787 : return *this;
718 : }
719 :
720 2841759 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
721 : Register context, int slot_index, int depth,
722 : ContextSlotMutability mutability) {
723 2841759 : if (context.is_current_context() && depth == 0) {
724 2717557 : if (mutability == kImmutableSlot) {
725 : OutputLdaImmutableCurrentContextSlot(slot_index);
726 : } else {
727 : DCHECK_EQ(kMutableSlot, mutability);
728 : OutputLdaCurrentContextSlot(slot_index);
729 : }
730 124202 : } else if (mutability == kImmutableSlot) {
731 : OutputLdaImmutableContextSlot(context, slot_index, depth);
732 : } else {
733 : DCHECK_EQ(mutability, kMutableSlot);
734 : OutputLdaContextSlot(context, slot_index, depth);
735 : }
736 2841758 : return *this;
737 : }
738 :
739 2595832 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
740 : int slot_index,
741 : int depth) {
742 2595832 : if (context.is_current_context() && depth == 0) {
743 : OutputStaCurrentContextSlot(slot_index);
744 : } else {
745 : OutputStaContextSlot(context, slot_index, depth);
746 : }
747 2595832 : return *this;
748 : }
749 :
750 11815 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
751 : const AstRawString* name, TypeofMode typeof_mode) {
752 : size_t name_index = GetConstantPoolEntry(name);
753 11815 : if (typeof_mode == INSIDE_TYPEOF) {
754 : OutputLdaLookupSlotInsideTypeof(name_index);
755 : } else {
756 : DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
757 : OutputLdaLookupSlot(name_index);
758 : }
759 11815 : return *this;
760 : }
761 :
762 3834 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
763 : const AstRawString* name, TypeofMode typeof_mode, int slot_index,
764 : int depth) {
765 : size_t name_index = GetConstantPoolEntry(name);
766 3834 : if (typeof_mode == INSIDE_TYPEOF) {
767 : OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
768 : } else {
769 : DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
770 : OutputLdaLookupContextSlot(name_index, slot_index, depth);
771 : }
772 3834 : return *this;
773 : }
774 :
775 365761 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
776 : const AstRawString* name, TypeofMode typeof_mode, int feedback_slot,
777 : int depth) {
778 : size_t name_index = GetConstantPoolEntry(name);
779 365761 : if (typeof_mode == INSIDE_TYPEOF) {
780 : OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth);
781 : } else {
782 : DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
783 : OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth);
784 : }
785 365761 : return *this;
786 : }
787 :
788 30941 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
789 : const AstRawString* name, LanguageMode language_mode,
790 : LookupHoistingMode lookup_hoisting_mode) {
791 : size_t name_index = GetConstantPoolEntry(name);
792 : uint8_t flags =
793 30941 : StoreLookupSlotFlags::Encode(language_mode, lookup_hoisting_mode);
794 : OutputStaLookupSlot(name_index, flags);
795 30941 : return *this;
796 : }
797 :
798 3518026 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
799 : Register object, const AstRawString* name, int feedback_slot) {
800 : size_t name_index = GetConstantPoolEntry(name);
801 : OutputLdaNamedProperty(object, name_index, feedback_slot);
802 3518027 : return *this;
803 : }
804 :
805 217432 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
806 : Register object, int feedback_slot) {
807 : OutputLdaKeyedProperty(object, feedback_slot);
808 217432 : return *this;
809 : }
810 :
811 26721 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
812 : Register object, int feedback_slot) {
813 : size_t name_index = IteratorSymbolConstantPoolEntry();
814 : OutputLdaNamedProperty(object, name_index, feedback_slot);
815 26721 : return *this;
816 : }
817 :
818 330 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
819 : Register object, int feedback_slot) {
820 : size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
821 : OutputLdaNamedProperty(object, name_index, feedback_slot);
822 330 : return *this;
823 : }
824 :
825 391769 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
826 : Register object, Register name, DataPropertyInLiteralFlags flags,
827 : int feedback_slot) {
828 : OutputStaDataPropertyInLiteral(object, name, flags, feedback_slot);
829 391769 : return *this;
830 : }
831 :
832 205 : BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
833 : OutputCollectTypeProfile(position);
834 205 : return *this;
835 : }
836 :
837 1657760 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
838 : Register object, size_t name_index, int feedback_slot,
839 : LanguageMode language_mode) {
840 : // Ensure that language mode is in sync with the IC slot kind.
841 : DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
842 : FeedbackVector::ToSlot(feedback_slot))),
843 : language_mode);
844 : OutputStaNamedProperty(object, name_index, feedback_slot);
845 1657760 : return *this;
846 : }
847 :
848 1537798 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
849 : Register object, const AstRawString* name, int feedback_slot,
850 : LanguageMode language_mode) {
851 : size_t name_index = GetConstantPoolEntry(name);
852 1537798 : return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
853 : }
854 :
855 327969 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedOwnProperty(
856 : Register object, const AstRawString* name, int feedback_slot) {
857 : size_t name_index = GetConstantPoolEntry(name);
858 : // Ensure that the store operation is in sync with the IC slot kind.
859 : DCHECK_EQ(
860 : FeedbackSlotKind::kStoreOwnNamed,
861 : feedback_vector_spec()->GetKind(FeedbackVector::ToSlot(feedback_slot)));
862 : OutputStaNamedOwnProperty(object, name_index, feedback_slot);
863 327969 : return *this;
864 : }
865 :
866 345955 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
867 : Register object, Register key, int feedback_slot,
868 : LanguageMode language_mode) {
869 : // Ensure that language mode is in sync with the IC slot kind.
870 : DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(
871 : FeedbackVector::ToSlot(feedback_slot))),
872 : language_mode);
873 : OutputStaKeyedProperty(object, key, feedback_slot);
874 345955 : return *this;
875 : }
876 :
877 119962 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreHomeObjectProperty(
878 : Register object, int feedback_slot, LanguageMode language_mode) {
879 : size_t name_index = HomeObjectSymbolConstantPoolEntry();
880 119962 : return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
881 : }
882 :
883 3969996 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
884 : size_t shared_function_info_entry, int slot, int flags) {
885 : OutputCreateClosure(shared_function_info_entry, slot, flags);
886 3969999 : return *this;
887 : }
888 :
889 56532 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
890 : const Scope* scope) {
891 : size_t entry = GetConstantPoolEntry(scope);
892 : OutputCreateBlockContext(entry);
893 56532 : return *this;
894 : }
895 :
896 102123 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
897 : Register exception, const AstRawString* name, const Scope* scope) {
898 : size_t name_index = GetConstantPoolEntry(name);
899 : size_t scope_index = GetConstantPoolEntry(scope);
900 : OutputCreateCatchContext(exception, name_index, scope_index);
901 102123 : return *this;
902 : }
903 :
904 146653 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) {
905 : OutputCreateFunctionContext(slots);
906 146653 : return *this;
907 : }
908 :
909 20740 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(int slots) {
910 : OutputCreateEvalContext(slots);
911 20740 : return *this;
912 : }
913 :
914 3025 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
915 : Register object, const Scope* scope) {
916 : size_t scope_index = GetConstantPoolEntry(scope);
917 : OutputCreateWithContext(object, scope_index);
918 3025 : return *this;
919 : }
920 :
921 99690 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
922 : CreateArgumentsType type) {
923 99690 : switch (type) {
924 : case CreateArgumentsType::kMappedArguments:
925 : OutputCreateMappedArguments();
926 : break;
927 : case CreateArgumentsType::kUnmappedArguments:
928 : OutputCreateUnmappedArguments();
929 : break;
930 : case CreateArgumentsType::kRestParameter:
931 : OutputCreateRestParameter();
932 : break;
933 : default:
934 0 : UNREACHABLE();
935 : }
936 99690 : return *this;
937 : }
938 :
939 57589 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
940 : const AstRawString* pattern, int literal_index, int flags) {
941 : size_t pattern_entry = GetConstantPoolEntry(pattern);
942 : OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
943 57589 : return *this;
944 : }
945 :
946 137207 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyArrayLiteral(
947 : int literal_index) {
948 : OutputCreateEmptyArrayLiteral(literal_index);
949 137207 : return *this;
950 : }
951 :
952 111461 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
953 : size_t constant_elements_entry, int literal_index, int flags) {
954 : OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
955 111461 : return *this;
956 : }
957 :
958 263563 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
959 : size_t constant_properties_entry, int literal_index, int flags,
960 : Register output) {
961 : OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags,
962 : output);
963 263563 : return *this;
964 : }
965 :
966 40225 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyObjectLiteral() {
967 : OutputCreateEmptyObjectLiteral();
968 40225 : return *this;
969 : }
970 :
971 1440 : BytecodeArrayBuilder& BytecodeArrayBuilder::GetTemplateObject(
972 : size_t template_object_description_entry) {
973 : OutputGetTemplateObject(template_object_description_entry);
974 1440 : return *this;
975 : }
976 :
977 346020 : BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
978 : OutputPushContext(context);
979 346020 : return *this;
980 : }
981 :
982 354028 : BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
983 : OutputPopContext(context);
984 354028 : return *this;
985 : }
986 :
987 9097 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToObject(Register out) {
988 : OutputToObject(out);
989 9097 : return *this;
990 : }
991 :
992 7253 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToName(Register out) {
993 : OutputToName(out);
994 7253 : return *this;
995 : }
996 :
997 1 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumber(int feedback_slot) {
998 : OutputToNumber(feedback_slot);
999 1 : return *this;
1000 : }
1001 :
1002 29056 : BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(int feedback_slot) {
1003 : OutputToNumeric(feedback_slot);
1004 29056 : return *this;
1005 : }
1006 :
1007 3003371 : BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
1008 : // Flush the register optimizer when binding a label to ensure all
1009 : // expected registers are valid when jumping to this label.
1010 3003371 : if (register_optimizer_) register_optimizer_->Flush();
1011 3003373 : bytecode_array_writer_.BindLabel(label);
1012 : LeaveBasicBlock();
1013 3003372 : return *this;
1014 : }
1015 :
1016 0 : BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
1017 : BytecodeLabel* label) {
1018 0 : bytecode_array_writer_.BindLabel(target, label);
1019 : LeaveBasicBlock();
1020 0 : return *this;
1021 : }
1022 :
1023 62833 : BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeJumpTable* jump_table,
1024 : int case_value) {
1025 : // Flush the register optimizer when binding a jump table entry to ensure
1026 : // all expected registers are valid when jumping to this location.
1027 62833 : if (register_optimizer_) register_optimizer_->Flush();
1028 62833 : bytecode_array_writer_.BindJumpTableEntry(jump_table, case_value);
1029 : LeaveBasicBlock();
1030 62833 : return *this;
1031 : }
1032 :
1033 553381 : BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
1034 : DCHECK(!label->is_bound());
1035 : OutputJump(label, 0);
1036 553380 : return *this;
1037 : }
1038 :
1039 489072 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
1040 : BytecodeLabel* label) {
1041 : DCHECK(!label->is_bound());
1042 489072 : if (mode == ToBooleanMode::kAlreadyBoolean) {
1043 : OutputJumpIfTrue(label, 0);
1044 : } else {
1045 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1046 : OutputJumpIfToBooleanTrue(label, 0);
1047 : }
1048 489072 : return *this;
1049 : }
1050 :
1051 1035985 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
1052 : BytecodeLabel* label) {
1053 : DCHECK(!label->is_bound());
1054 1035985 : if (mode == ToBooleanMode::kAlreadyBoolean) {
1055 : OutputJumpIfFalse(label, 0);
1056 : } else {
1057 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1058 : OutputJumpIfToBooleanFalse(label, 0);
1059 : }
1060 1035985 : return *this;
1061 : }
1062 :
1063 12992 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
1064 : DCHECK(!label->is_bound());
1065 : OutputJumpIfNull(label, 0);
1066 12992 : return *this;
1067 : }
1068 :
1069 16810 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
1070 : BytecodeLabel* label) {
1071 : DCHECK(!label->is_bound());
1072 : OutputJumpIfNotNull(label, 0);
1073 16810 : return *this;
1074 : }
1075 :
1076 59082 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
1077 : BytecodeLabel* label) {
1078 : DCHECK(!label->is_bound());
1079 : OutputJumpIfUndefined(label, 0);
1080 59082 : return *this;
1081 : }
1082 :
1083 32155 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotUndefined(
1084 : BytecodeLabel* label) {
1085 : DCHECK(!label->is_bound());
1086 : OutputJumpIfNotUndefined(label, 0);
1087 32155 : return *this;
1088 : }
1089 :
1090 44023 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
1091 : Token::Value op,
1092 : NilValue nil) {
1093 44023 : if (op == Token::EQ) {
1094 : // TODO(rmcilroy): Implement JumpIfUndetectable.
1095 573 : return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
1096 573 : label);
1097 : } else {
1098 : DCHECK_EQ(Token::EQ_STRICT, op);
1099 43450 : if (nil == kUndefinedValue) {
1100 37591 : return JumpIfUndefined(label);
1101 : } else {
1102 : DCHECK_EQ(kNullValue, nil);
1103 5859 : return JumpIfNull(label);
1104 : }
1105 : }
1106 : }
1107 :
1108 78567 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
1109 : Token::Value op,
1110 : NilValue nil) {
1111 78567 : if (op == Token::EQ) {
1112 : // TODO(rmcilroy): Implement JumpIfUndetectable.
1113 29606 : return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
1114 29606 : label);
1115 : } else {
1116 : DCHECK_EQ(Token::EQ_STRICT, op);
1117 48961 : if (nil == kUndefinedValue) {
1118 32153 : return JumpIfNotUndefined(label);
1119 : } else {
1120 : DCHECK_EQ(kNullValue, nil);
1121 16808 : return JumpIfNotNull(label);
1122 : }
1123 : }
1124 : }
1125 :
1126 27209 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
1127 : BytecodeLabel* label) {
1128 : DCHECK(!label->is_bound());
1129 : OutputJumpIfJSReceiver(label, 0);
1130 27209 : return *this;
1131 : }
1132 :
1133 222935 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
1134 : int loop_depth) {
1135 : DCHECK(label->is_bound());
1136 : OutputJumpLoop(label, 0, loop_depth);
1137 222935 : return *this;
1138 : }
1139 :
1140 28694 : BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnSmiNoFeedback(
1141 : BytecodeJumpTable* jump_table) {
1142 : OutputSwitchOnSmiNoFeedback(jump_table);
1143 28694 : return *this;
1144 : }
1145 :
1146 2354340 : BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
1147 2354340 : if (position != kNoSourcePosition) {
1148 : // We need to attach a non-breakable source position to a stack
1149 : // check, so we simply add it as expression position. There can be
1150 : // a prior statement position from constructs like:
1151 : //
1152 : // do var x; while (false);
1153 : //
1154 : // A Nop could be inserted for empty statements, but since no code
1155 : // is associated with these positions, instead we force the stack
1156 : // check's expression position which eliminates the empty
1157 : // statement's position.
1158 : latest_source_info_.ForceExpressionPosition(position);
1159 : }
1160 : OutputStackCheck();
1161 2354342 : return *this;
1162 : }
1163 :
1164 150350 : BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
1165 : OutputSetPendingMessage();
1166 150350 : return *this;
1167 : }
1168 :
1169 79501 : BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
1170 : OutputThrow();
1171 79501 : return *this;
1172 : }
1173 :
1174 47029 : BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
1175 : OutputReThrow();
1176 47029 : return *this;
1177 : }
1178 :
1179 9373 : BytecodeArrayBuilder& BytecodeArrayBuilder::Abort(BailoutReason reason) {
1180 : OutputAbort(reason);
1181 9373 : return *this;
1182 : }
1183 :
1184 2629337 : BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
1185 : OutputReturn();
1186 2629339 : return_seen_in_block_ = true;
1187 2629339 : return *this;
1188 : }
1189 :
1190 209672 : BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowReferenceErrorIfHole(
1191 : const AstRawString* name) {
1192 : size_t entry = GetConstantPoolEntry(name);
1193 : OutputThrowReferenceErrorIfHole(entry);
1194 209672 : return *this;
1195 : }
1196 :
1197 16388 : BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperNotCalledIfHole() {
1198 : OutputThrowSuperNotCalledIfHole();
1199 16388 : return *this;
1200 : }
1201 :
1202 2116 : BytecodeArrayBuilder& BytecodeArrayBuilder::ThrowSuperAlreadyCalledIfNotHole() {
1203 : OutputThrowSuperAlreadyCalledIfNotHole();
1204 2116 : return *this;
1205 : }
1206 :
1207 7340 : BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
1208 : OutputDebugger();
1209 7340 : return *this;
1210 : }
1211 :
1212 2465 : BytecodeArrayBuilder& BytecodeArrayBuilder::IncBlockCounter(
1213 : int coverage_array_slot) {
1214 : OutputIncBlockCounter(coverage_array_slot);
1215 2465 : return *this;
1216 : }
1217 :
1218 6073 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInEnumerate(Register receiver) {
1219 : OutputForInEnumerate(receiver);
1220 6073 : return *this;
1221 : }
1222 :
1223 6081 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
1224 : RegisterList cache_info_triple, int feedback_slot) {
1225 : DCHECK_EQ(3, cache_info_triple.register_count());
1226 : OutputForInPrepare(cache_info_triple, feedback_slot);
1227 6081 : return *this;
1228 : }
1229 :
1230 6073 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
1231 : Register index, Register cache_length) {
1232 : OutputForInContinue(index, cache_length);
1233 6073 : return *this;
1234 : }
1235 :
1236 6073 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
1237 : Register receiver, Register index, RegisterList cache_type_array_pair,
1238 : int feedback_slot) {
1239 : DCHECK_EQ(2, cache_type_array_pair.register_count());
1240 : OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
1241 6073 : return *this;
1242 : }
1243 :
1244 6073 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
1245 : OutputForInStep(index);
1246 6073 : return *this;
1247 : }
1248 :
1249 34663 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
1250 : int depth) {
1251 : OutputStaModuleVariable(cell_index, depth);
1252 34663 : return *this;
1253 : }
1254 :
1255 1566 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
1256 : int depth) {
1257 : OutputLdaModuleVariable(cell_index, depth);
1258 1566 : return *this;
1259 : }
1260 :
1261 20047 : BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
1262 : Register generator, RegisterList registers, int suspend_id) {
1263 : OutputSuspendGenerator(generator, registers, registers.register_count(),
1264 : suspend_id);
1265 20047 : return *this;
1266 : }
1267 :
1268 8287 : BytecodeArrayBuilder& BytecodeArrayBuilder::RestoreGeneratorState(
1269 : Register generator) {
1270 : OutputRestoreGeneratorState(generator);
1271 8287 : return *this;
1272 : }
1273 :
1274 20047 : BytecodeArrayBuilder& BytecodeArrayBuilder::RestoreGeneratorRegisters(
1275 : Register generator, RegisterList registers) {
1276 : OutputRestoreGeneratorRegisters(generator, registers,
1277 : registers.register_count());
1278 20047 : return *this;
1279 : }
1280 :
1281 138435 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
1282 : int handler_id, HandlerTable::CatchPrediction catch_prediction) {
1283 : BytecodeLabel handler;
1284 138435 : Bind(&handler);
1285 138435 : handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
1286 138435 : handler_table_builder()->SetPrediction(handler_id, catch_prediction);
1287 138435 : return *this;
1288 : }
1289 :
1290 138435 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
1291 : Register context) {
1292 : BytecodeLabel try_begin;
1293 138435 : Bind(&try_begin);
1294 138435 : handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
1295 138435 : handler_table_builder()->SetContextRegister(handler_id, context);
1296 138435 : return *this;
1297 : }
1298 :
1299 138435 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
1300 : BytecodeLabel try_end;
1301 138435 : Bind(&try_end);
1302 138435 : handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
1303 138435 : return *this;
1304 : }
1305 :
1306 862646 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable,
1307 : RegisterList args,
1308 : int feedback_slot) {
1309 862646 : if (args.register_count() == 1) {
1310 : OutputCallProperty0(callable, args[0], feedback_slot);
1311 700411 : } else if (args.register_count() == 2) {
1312 : OutputCallProperty1(callable, args[0], args[1], feedback_slot);
1313 189445 : } else if (args.register_count() == 3) {
1314 : OutputCallProperty2(callable, args[0], args[1], args[2], feedback_slot);
1315 : } else {
1316 : OutputCallProperty(callable, args, args.register_count(), feedback_slot);
1317 : }
1318 862646 : return *this;
1319 : }
1320 :
1321 1823479 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallUndefinedReceiver(
1322 : Register callable, RegisterList args, int feedback_slot) {
1323 1823479 : if (args.register_count() == 0) {
1324 : OutputCallUndefinedReceiver0(callable, feedback_slot);
1325 1643751 : } else if (args.register_count() == 1) {
1326 : OutputCallUndefinedReceiver1(callable, args[0], feedback_slot);
1327 994882 : } else if (args.register_count() == 2) {
1328 : OutputCallUndefinedReceiver2(callable, args[0], args[1], feedback_slot);
1329 : } else {
1330 : OutputCallUndefinedReceiver(callable, args, args.register_count(),
1331 : feedback_slot);
1332 : }
1333 1823481 : return *this;
1334 : }
1335 :
1336 2525 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
1337 : RegisterList args,
1338 : int feedback_slot) {
1339 : OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot);
1340 2525 : return *this;
1341 : }
1342 :
1343 1492 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
1344 : RegisterList args,
1345 : int feedback_slot) {
1346 : OutputCallWithSpread(callable, args, args.register_count(), feedback_slot);
1347 1492 : return *this;
1348 : }
1349 :
1350 157028 : BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
1351 : RegisterList args,
1352 : int feedback_slot_id) {
1353 : OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
1354 157028 : return *this;
1355 : }
1356 :
1357 2972 : BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
1358 : Register constructor, RegisterList args, int feedback_slot_id) {
1359 : OutputConstructWithSpread(constructor, args, args.register_count(),
1360 : feedback_slot_id);
1361 2972 : return *this;
1362 : }
1363 :
1364 1216124 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1365 : Runtime::FunctionId function_id, RegisterList args) {
1366 : DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
1367 : DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
1368 : OperandSize::kShort);
1369 1216124 : if (IntrinsicsHelper::IsSupported(function_id)) {
1370 : IntrinsicsHelper::IntrinsicId intrinsic_id =
1371 259220 : IntrinsicsHelper::FromRuntimeId(function_id);
1372 : OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
1373 : args.register_count());
1374 : } else {
1375 : OutputCallRuntime(static_cast<int>(function_id), args,
1376 : args.register_count());
1377 : }
1378 1216124 : return *this;
1379 : }
1380 :
1381 446140 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1382 : Runtime::FunctionId function_id, Register arg) {
1383 446140 : return CallRuntime(function_id, RegisterList(arg.index(), 1));
1384 : }
1385 :
1386 61440 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1387 : Runtime::FunctionId function_id) {
1388 61440 : return CallRuntime(function_id, RegisterList());
1389 : }
1390 :
1391 2150 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1392 : Runtime::FunctionId function_id, RegisterList args,
1393 : RegisterList return_pair) {
1394 : DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
1395 : DCHECK_LE(Bytecodes::SizeForUnsignedOperand(function_id),
1396 : OperandSize::kShort);
1397 : DCHECK_EQ(2, return_pair.register_count());
1398 : OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
1399 2150 : args.register_count(), return_pair);
1400 2150 : return *this;
1401 : }
1402 :
1403 2149 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1404 : Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
1405 : return CallRuntimeForPair(function_id, RegisterList(arg.index(), 1),
1406 2149 : return_pair);
1407 : }
1408 :
1409 90349 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
1410 : RegisterList args) {
1411 : OutputCallJSRuntime(context_index, args, args.register_count());
1412 90349 : return *this;
1413 : }
1414 :
1415 9508 : BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
1416 : LanguageMode language_mode) {
1417 9508 : if (language_mode == LanguageMode::kSloppy) {
1418 : OutputDeletePropertySloppy(object);
1419 : } else {
1420 : DCHECK_EQ(language_mode, LanguageMode::kStrict);
1421 : OutputDeletePropertyStrict(object);
1422 : }
1423 9508 : return *this;
1424 : }
1425 :
1426 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(
1427 : const AstRawString* raw_string) {
1428 12120282 : return constant_array_builder()->Insert(raw_string);
1429 : }
1430 :
1431 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(const AstValue* heap_number) {
1432 : DCHECK(heap_number->IsHeapNumber() || heap_number->IsBigInt());
1433 726438 : return constant_array_builder()->Insert(heap_number);
1434 : }
1435 :
1436 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
1437 170339 : return constant_array_builder()->Insert(scope);
1438 : }
1439 :
1440 : #define ENTRY_GETTER(NAME, ...) \
1441 : size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \
1442 : return constant_array_builder()->Insert##NAME(); \
1443 : }
1444 155721 : SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
1445 : #undef ENTRY_GETTER
1446 :
1447 28694 : BytecodeJumpTable* BytecodeArrayBuilder::AllocateJumpTable(
1448 28694 : int size, int case_value_base) {
1449 : DCHECK_GT(size, 0);
1450 :
1451 28694 : size_t constant_pool_index = constant_array_builder()->InsertJumpTable(size);
1452 :
1453 : return new (zone())
1454 28694 : BytecodeJumpTable(constant_pool_index, size, case_value_base, zone());
1455 : }
1456 :
1457 4428508 : size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
1458 4428508 : return constant_array_builder()->InsertDeferred();
1459 : }
1460 :
1461 4428506 : void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
1462 : Handle<Object> object) {
1463 4428506 : constant_array_builder()->SetDeferredAt(entry, object);
1464 4428506 : }
1465 :
1466 0 : bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
1467 0 : if (!reg.is_valid()) {
1468 : return false;
1469 : }
1470 :
1471 0 : if (reg.is_current_context() || reg.is_function_closure()) {
1472 : return true;
1473 0 : } else if (reg.is_parameter()) {
1474 0 : int parameter_index = reg.ToParameterIndex(parameter_count());
1475 0 : return parameter_index >= 0 && parameter_index < parameter_count();
1476 0 : } else if (reg.index() < fixed_register_count()) {
1477 : return true;
1478 : } else {
1479 0 : return register_allocator()->RegisterIsLive(reg);
1480 : }
1481 : }
1482 :
1483 0 : bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const {
1484 0 : if (reg_list.register_count() == 0) {
1485 : return reg_list.first_register() == Register(0);
1486 : } else {
1487 : int first_reg_index = reg_list.first_register().index();
1488 0 : for (int i = 0; i < reg_list.register_count(); i++) {
1489 0 : if (!RegisterIsValid(Register(first_reg_index + i))) {
1490 : return false;
1491 : }
1492 : }
1493 : return true;
1494 : }
1495 : }
1496 :
1497 : template <Bytecode bytecode, AccumulatorUse accumulator_use>
1498 47354987 : void BytecodeArrayBuilder::PrepareToOutputBytecode() {
1499 47354987 : if (register_optimizer_)
1500 : register_optimizer_->PrepareForBytecode<bytecode, accumulator_use>();
1501 47354996 : }
1502 :
1503 16200244 : uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
1504 : DCHECK(RegisterIsValid(reg));
1505 16200244 : if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
1506 16200245 : return static_cast<uint32_t>(reg.ToOperand());
1507 : }
1508 :
1509 634853 : uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
1510 : DCHECK(RegisterIsValid(reg));
1511 634853 : if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
1512 634853 : return static_cast<uint32_t>(reg.ToOperand());
1513 : }
1514 :
1515 1812308 : uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
1516 : RegisterList reg_list) {
1517 : DCHECK(RegisterListIsValid(reg_list));
1518 1812308 : if (register_optimizer_)
1519 1811515 : reg_list = register_optimizer_->GetInputRegisterList(reg_list);
1520 1812308 : return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1521 : }
1522 :
1523 28278 : uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
1524 : RegisterList reg_list) {
1525 : DCHECK(RegisterListIsValid(reg_list));
1526 28278 : if (register_optimizer_)
1527 28278 : register_optimizer_->PrepareOutputRegisterList(reg_list);
1528 28278 : return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1529 : }
1530 :
1531 0 : std::ostream& operator<<(std::ostream& os,
1532 : const BytecodeArrayBuilder::ToBooleanMode& mode) {
1533 0 : switch (mode) {
1534 : case BytecodeArrayBuilder::ToBooleanMode::kAlreadyBoolean:
1535 0 : return os << "AlreadyBoolean";
1536 : case BytecodeArrayBuilder::ToBooleanMode::kConvertToBoolean:
1537 0 : return os << "ConvertToBoolean";
1538 : }
1539 0 : UNREACHABLE();
1540 : }
1541 :
1542 : } // namespace interpreter
1543 : } // namespace internal
1544 : } // namespace v8
|