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-label.h"
10 : #include "src/interpreter/bytecode-node.h"
11 : #include "src/interpreter/bytecode-register-optimizer.h"
12 : #include "src/interpreter/bytecode-source-info.h"
13 : #include "src/interpreter/interpreter-intrinsics.h"
14 : #include "src/objects-inl.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 : namespace interpreter {
19 :
20 : class RegisterTransferWriter final
21 : : public NON_EXPORTED_BASE(BytecodeRegisterOptimizer::BytecodeWriter),
22 : public NON_EXPORTED_BASE(ZoneObject) {
23 : public:
24 2104165 : RegisterTransferWriter(BytecodeArrayBuilder* builder) : builder_(builder) {}
25 0 : ~RegisterTransferWriter() override {}
26 :
27 2726160 : void EmitLdar(Register input) override { builder_->OutputLdarRaw(input); }
28 :
29 19578322 : void EmitStar(Register output) override { builder_->OutputStarRaw(output); }
30 :
31 2167152 : void EmitMov(Register input, Register output) override {
32 2167152 : builder_->OutputMovRaw(input, output);
33 2167153 : }
34 :
35 : private:
36 : BytecodeArrayBuilder* builder_;
37 : };
38 :
39 2104902 : BytecodeArrayBuilder::BytecodeArrayBuilder(
40 : Isolate* isolate, Zone* zone, int parameter_count, int context_count,
41 : int locals_count, FunctionLiteral* literal,
42 : SourcePositionTableBuilder::RecordingMode source_position_mode)
43 : : zone_(zone),
44 : literal_(literal),
45 : bytecode_generated_(false),
46 : constant_array_builder_(zone),
47 : handler_table_builder_(zone),
48 : return_seen_in_block_(false),
49 : parameter_count_(parameter_count),
50 : local_register_count_(locals_count),
51 : context_register_count_(context_count),
52 : register_allocator_(fixed_register_count()),
53 : bytecode_array_writer_(zone, &constant_array_builder_,
54 : source_position_mode),
55 4209802 : register_optimizer_(nullptr) {
56 : DCHECK_GE(parameter_count_, 0);
57 : DCHECK_GE(context_register_count_, 0);
58 : DCHECK_GE(local_register_count_, 0);
59 :
60 2104907 : if (FLAG_ignition_reo) {
61 : register_optimizer_ = new (zone) BytecodeRegisterOptimizer(
62 : zone, ®ister_allocator_, fixed_register_count(), parameter_count,
63 2104160 : new (zone) RegisterTransferWriter(this));
64 : }
65 :
66 2104912 : return_position_ = literal ? literal->return_position() : kNoSourcePosition;
67 2104912 : }
68 :
69 377307 : Register BytecodeArrayBuilder::first_context_register() const {
70 : DCHECK_GT(context_register_count_, 0);
71 377307 : return Register(local_register_count_);
72 : }
73 :
74 0 : Register BytecodeArrayBuilder::last_context_register() const {
75 : DCHECK_GT(context_register_count_, 0);
76 0 : return Register(local_register_count_ + context_register_count_ - 1);
77 : }
78 :
79 2318877 : Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
80 : DCHECK_GE(parameter_index, 0);
81 : // The parameter indices are shifted by 1 (receiver is the
82 : // first entry).
83 2318877 : return Register::FromParameterIndex(parameter_index + 1, parameter_count());
84 : }
85 :
86 874862 : Register BytecodeArrayBuilder::Receiver() const {
87 874862 : return Register::FromParameterIndex(0, parameter_count());
88 : }
89 :
90 7479103 : Register BytecodeArrayBuilder::Local(int index) const {
91 : // TODO(marja): Make a DCHECK once crbug.com/706234 is fixed.
92 7479103 : CHECK_LT(index, locals_count());
93 7479103 : return Register(index);
94 : }
95 :
96 4207635 : Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
97 : DCHECK(return_seen_in_block_);
98 : DCHECK(!bytecode_generated_);
99 2103814 : bytecode_generated_ = true;
100 :
101 : int register_count = total_register_count();
102 :
103 4206892 : if (register_optimizer_) {
104 2103076 : register_optimizer_->Flush();
105 4206156 : register_count = register_optimizer_->maxiumum_register_index() + 1;
106 : }
107 :
108 : Handle<FixedArray> handler_table =
109 2103816 : handler_table_builder()->ToHandlerTable(isolate);
110 : return bytecode_array_writer_.ToBytecodeArray(
111 2103821 : isolate, register_count, parameter_count(), handler_table);
112 : }
113 :
114 : BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition(
115 : Bytecode bytecode) {
116 81811116 : BytecodeSourceInfo source_position;
117 81811147 : if (latest_source_info_.is_valid()) {
118 : // Statement positions need to be emitted immediately. Expression
119 : // positions can be pushed back until a bytecode is found that can
120 : // throw (if expression position filtering is turned on). We only
121 : // invalidate the existing source position information if it is used.
122 100523653 : if (latest_source_info_.is_statement() ||
123 62913964 : !FLAG_ignition_filter_expression_positions ||
124 25307530 : !Bytecodes::IsWithoutExternalSideEffects(bytecode)) {
125 27584751 : source_position = latest_source_info_;
126 27584751 : latest_source_info_.set_invalid();
127 : }
128 : }
129 81811170 : return source_position;
130 : }
131 :
132 34246754 : void BytecodeArrayBuilder::SetDeferredSourceInfo(
133 : BytecodeSourceInfo source_info) {
134 68493508 : if (!source_info.is_valid()) return;
135 2496493 : if (deferred_source_info_.is_valid()) {
136 : // Emit any previous deferred source info now as a nop.
137 : BytecodeNode node = BytecodeNode::Nop(deferred_source_info_);
138 5055 : bytecode_array_writer_.Write(&node);
139 : }
140 2496493 : deferred_source_info_ = source_info;
141 : }
142 :
143 72035483 : void BytecodeArrayBuilder::AttachOrEmitDeferredSourceInfo(BytecodeNode* node) {
144 144070966 : if (!deferred_source_info_.is_valid()) return;
145 :
146 2491438 : if (!node->source_info().is_valid()) {
147 : node->set_source_info(deferred_source_info_);
148 : } else {
149 : BytecodeNode node = BytecodeNode::Nop(deferred_source_info_);
150 749168 : bytecode_array_writer_.Write(&node);
151 : }
152 : deferred_source_info_.set_invalid();
153 : }
154 :
155 44479719 : void BytecodeArrayBuilder::Write(BytecodeNode* node) {
156 68951361 : AttachOrEmitDeferredSourceInfo(node);
157 68951381 : bytecode_array_writer_.Write(node);
158 44479749 : }
159 :
160 3084450 : void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
161 3084450 : AttachOrEmitDeferredSourceInfo(node);
162 3084450 : bytecode_array_writer_.WriteJump(node, label);
163 3084448 : }
164 :
165 2726160 : void BytecodeArrayBuilder::OutputLdarRaw(Register reg) {
166 2726160 : uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
167 : BytecodeNode node(BytecodeNode::Ldar(BytecodeSourceInfo(), operand));
168 : Write(&node);
169 2726161 : }
170 :
171 19578323 : void BytecodeArrayBuilder::OutputStarRaw(Register reg) {
172 19578323 : uint32_t operand = static_cast<uint32_t>(reg.ToOperand());
173 : BytecodeNode node(BytecodeNode::Star(BytecodeSourceInfo(), operand));
174 : Write(&node);
175 19578326 : }
176 :
177 2167152 : void BytecodeArrayBuilder::OutputMovRaw(Register src, Register dest) {
178 2167152 : uint32_t operand0 = static_cast<uint32_t>(src.ToOperand());
179 2167152 : uint32_t operand1 = static_cast<uint32_t>(dest.ToOperand());
180 : BytecodeNode node(
181 : BytecodeNode::Mov(BytecodeSourceInfo(), operand0, operand1));
182 : Write(&node);
183 2167153 : }
184 :
185 : namespace {
186 :
187 : template <OperandTypeInfo type_info>
188 : class UnsignedOperandHelper {
189 : public:
190 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, size_t value)) {
191 : DCHECK(IsValid(value));
192 36822843 : return static_cast<uint32_t>(value);
193 : }
194 :
195 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
196 : DCHECK_GE(value, 0);
197 33144815 : return Convert(builder, static_cast<size_t>(value));
198 : }
199 :
200 : private:
201 : static bool IsValid(size_t value) {
202 : switch (type_info) {
203 : case OperandTypeInfo::kFixedUnsignedByte:
204 : return value <= kMaxUInt8;
205 : case OperandTypeInfo::kFixedUnsignedShort:
206 : return value <= kMaxUInt16;
207 : case OperandTypeInfo::kScalableUnsignedByte:
208 : return value <= kMaxUInt32;
209 : default:
210 : UNREACHABLE();
211 : return false;
212 : }
213 : }
214 : };
215 :
216 : template <OperandType>
217 : class OperandHelper {};
218 :
219 : #define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \
220 : template <> \
221 : class OperandHelper<OperandType::k##Name> \
222 : : public UnsignedOperandHelper<Type> {};
223 : UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
224 : UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER)
225 : #undef DEFINE_UNSIGNED_OPERAND_HELPER
226 :
227 : template <>
228 : class OperandHelper<OperandType::kImm> {
229 : public:
230 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
231 5664130 : return static_cast<uint32_t>(value);
232 : }
233 : };
234 :
235 : template <>
236 : class OperandHelper<OperandType::kReg> {
237 : public:
238 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) {
239 11596124 : return builder->GetInputRegisterOperand(reg);
240 : }
241 : };
242 :
243 : template <>
244 : class OperandHelper<OperandType::kRegList> {
245 : public:
246 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
247 : RegisterList reg_list)) {
248 2375782 : return builder->GetInputRegisterListOperand(reg_list);
249 : }
250 : };
251 :
252 : template <>
253 : class OperandHelper<OperandType::kRegPair> {
254 : public:
255 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
256 : RegisterList reg_list)) {
257 : DCHECK_EQ(reg_list.register_count(), 2);
258 5765 : return builder->GetInputRegisterListOperand(reg_list);
259 : }
260 : };
261 :
262 : template <>
263 : class OperandHelper<OperandType::kRegOut> {
264 : public:
265 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) {
266 789715 : return builder->GetOutputRegisterOperand(reg);
267 : }
268 : };
269 :
270 : template <>
271 : class OperandHelper<OperandType::kRegOutPair> {
272 : public:
273 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
274 : RegisterList reg_list)) {
275 : DCHECK_EQ(2, reg_list.register_count());
276 2763 : return builder->GetOutputRegisterListOperand(reg_list);
277 : }
278 : };
279 :
280 : template <>
281 : class OperandHelper<OperandType::kRegOutTriple> {
282 : public:
283 : INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder,
284 : RegisterList reg_list)) {
285 : DCHECK_EQ(3, reg_list.register_count());
286 5773 : return builder->GetOutputRegisterListOperand(reg_list);
287 : }
288 : };
289 :
290 : } // namespace
291 :
292 : template <Bytecode bytecode, AccumulatorUse accumulator_use,
293 : OperandType... operand_types>
294 : class BytecodeNodeBuilder {
295 : public:
296 : template <typename... Operands>
297 2791917 : INLINE(static BytecodeNode Make(BytecodeArrayBuilder* builder,
298 : BytecodeSourceInfo source_info,
299 : Operands... operands)) {
300 47564327 : builder->PrepareToOutputBytecode<bytecode, accumulator_use>();
301 : // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
302 : // expand both the OperandType... and Operands... parameter packs e.g. for:
303 : // BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
304 : // Register, int>(..., Register reg, int immediate)
305 : // the code will expand into:
306 : // OperandHelper<OperandType::kReg>::Convert(builder, reg),
307 : // OperandHelper<OperandType::kImm>::Convert(builder, immediate),
308 : return BytecodeNode::Create<bytecode, accumulator_use, operand_types...>(
309 : source_info,
310 293715 : OperandHelper<operand_types>::Convert(builder, operands)...);
311 : }
312 : };
313 :
314 : #define DEFINE_BYTECODE_OUTPUT(name, ...) \
315 : template <typename... Operands> \
316 : void BytecodeArrayBuilder::Output##name(Operands... operands) { \
317 : static_assert(sizeof...(Operands) <= Bytecodes::kMaxOperands, \
318 : "too many operands for bytecode"); \
319 : BytecodeNode node( \
320 : BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make< \
321 : Operands...>(this, CurrentSourcePosition(Bytecode::k##name), \
322 : 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( \
331 : BytecodeNodeBuilder<Bytecode::k##name, __VA_ARGS__>::Make< \
332 : Operands...>(this, CurrentSourcePosition(Bytecode::k##name), \
333 : operands...)); \
334 : WriteJump(&node, label); \
335 : LeaveBasicBlock(); \
336 : }
337 47564328 : BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
338 : #undef DEFINE_BYTECODE_OUTPUT
339 :
340 749618 : BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
341 : Register reg,
342 : int feedback_slot) {
343 749618 : switch (op) {
344 : case Token::Value::ADD:
345 : OutputAdd(reg, feedback_slot);
346 : break;
347 : case Token::Value::SUB:
348 : OutputSub(reg, feedback_slot);
349 : break;
350 : case Token::Value::MUL:
351 : OutputMul(reg, feedback_slot);
352 : break;
353 : case Token::Value::DIV:
354 : OutputDiv(reg, feedback_slot);
355 : break;
356 : case Token::Value::MOD:
357 : OutputMod(reg, feedback_slot);
358 : break;
359 : case Token::Value::BIT_OR:
360 : OutputBitwiseOr(reg, feedback_slot);
361 : break;
362 : case Token::Value::BIT_XOR:
363 : OutputBitwiseXor(reg, feedback_slot);
364 : break;
365 : case Token::Value::BIT_AND:
366 : OutputBitwiseAnd(reg, feedback_slot);
367 : break;
368 : case Token::Value::SHL:
369 : OutputShiftLeft(reg, feedback_slot);
370 : break;
371 : case Token::Value::SAR:
372 : OutputShiftRight(reg, feedback_slot);
373 : break;
374 : case Token::Value::SHR:
375 : OutputShiftRightLogical(reg, feedback_slot);
376 : break;
377 : default:
378 0 : UNREACHABLE();
379 : }
380 749618 : return *this;
381 : }
382 :
383 332158 : BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
384 : Token::Value op, Smi* literal, int feedback_slot) {
385 332158 : switch (op) {
386 : case Token::Value::ADD:
387 : OutputAddSmi(literal->value(), feedback_slot);
388 : break;
389 : case Token::Value::SUB:
390 : OutputSubSmi(literal->value(), feedback_slot);
391 : break;
392 : case Token::Value::MUL:
393 : OutputMulSmi(literal->value(), feedback_slot);
394 : break;
395 : case Token::Value::DIV:
396 : OutputDivSmi(literal->value(), feedback_slot);
397 : break;
398 : case Token::Value::MOD:
399 : OutputModSmi(literal->value(), feedback_slot);
400 : break;
401 : case Token::Value::BIT_OR:
402 : OutputBitwiseOrSmi(literal->value(), feedback_slot);
403 : break;
404 : case Token::Value::BIT_XOR:
405 : OutputBitwiseXorSmi(literal->value(), feedback_slot);
406 : break;
407 : case Token::Value::BIT_AND:
408 : OutputBitwiseAndSmi(literal->value(), feedback_slot);
409 : break;
410 : case Token::Value::SHL:
411 : OutputShiftLeftSmi(literal->value(), feedback_slot);
412 : break;
413 : case Token::Value::SAR:
414 : OutputShiftRightSmi(literal->value(), feedback_slot);
415 : break;
416 : case Token::Value::SHR:
417 : OutputShiftRightLogicalSmi(literal->value(), feedback_slot);
418 : break;
419 : default:
420 0 : UNREACHABLE();
421 : }
422 332158 : return *this;
423 : }
424 :
425 149205 : BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op,
426 : int feedback_slot) {
427 149205 : if (op == Token::Value::ADD) {
428 : OutputInc(feedback_slot);
429 : } else {
430 : DCHECK_EQ(op, Token::Value::SUB);
431 : OutputDec(feedback_slot);
432 : }
433 149205 : return *this;
434 : }
435 :
436 78436 : BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
437 78436 : if (mode == ToBooleanMode::kAlreadyBoolean) {
438 : OutputLogicalNot();
439 : } else {
440 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
441 : OutputToBooleanLogicalNot();
442 : }
443 78436 : return *this;
444 : }
445 :
446 51569 : BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
447 : OutputTypeOf();
448 51569 : return *this;
449 : }
450 :
451 4102 : BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
452 : OutputGetSuperConstructor(out);
453 4102 : return *this;
454 : }
455 :
456 960751 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
457 : Token::Value op, Register reg, int feedback_slot) {
458 : DCHECK(feedback_slot != kNoFeedbackSlot);
459 960751 : switch (op) {
460 : case Token::Value::EQ:
461 : OutputTestEqual(reg, feedback_slot);
462 : break;
463 : case Token::Value::EQ_STRICT:
464 : OutputTestEqualStrict(reg, feedback_slot);
465 : break;
466 : case Token::Value::LT:
467 : OutputTestLessThan(reg, feedback_slot);
468 : break;
469 : case Token::Value::GT:
470 : OutputTestGreaterThan(reg, feedback_slot);
471 : break;
472 : case Token::Value::LTE:
473 : OutputTestLessThanOrEqual(reg, feedback_slot);
474 : break;
475 : case Token::Value::GTE:
476 : OutputTestGreaterThanOrEqual(reg, feedback_slot);
477 : break;
478 : default:
479 0 : UNREACHABLE();
480 : }
481 960751 : return *this;
482 : }
483 :
484 181627 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
485 : Register reg) {
486 181627 : switch (op) {
487 : case Token::Value::EQ_STRICT:
488 : OutputTestEqualStrictNoFeedback(reg);
489 : break;
490 : case Token::Value::INSTANCEOF:
491 : OutputTestInstanceOf(reg);
492 : break;
493 : case Token::Value::IN:
494 : OutputTestIn(reg);
495 : break;
496 : default:
497 0 : UNREACHABLE();
498 : }
499 181628 : return *this;
500 : }
501 :
502 49867 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndetectable() {
503 : OutputTestUndetectable();
504 49867 : return *this;
505 : }
506 :
507 8917 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndefined() {
508 : OutputTestUndefined();
509 8917 : return *this;
510 : }
511 :
512 764 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNull() {
513 : OutputTestNull();
514 764 : return *this;
515 : }
516 :
517 11288 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNil(Token::Value op,
518 : NilValue nil) {
519 11288 : if (op == Token::EQ) {
520 1609 : return CompareUndetectable();
521 : } else {
522 : DCHECK_EQ(Token::EQ_STRICT, op);
523 9679 : if (nil == kUndefinedValue) {
524 8916 : return CompareUndefined();
525 : } else {
526 : DCHECK_EQ(kNullValue, nil);
527 763 : return CompareNull();
528 : }
529 : }
530 : }
531 :
532 160918 : BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
533 : TestTypeOfFlags::LiteralFlag literal_flag) {
534 : DCHECK(literal_flag != TestTypeOfFlags::LiteralFlag::kOther);
535 160918 : OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
536 160918 : return *this;
537 : }
538 :
539 77428 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
540 : size_t entry) {
541 : OutputLdaConstant(entry);
542 77428 : return *this;
543 : }
544 :
545 6638788 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
546 : v8::internal::Smi* smi) {
547 : int32_t raw_smi = smi->value();
548 6638788 : if (raw_smi == 0) {
549 : OutputLdaZero();
550 : } else {
551 : OutputLdaSmi(raw_smi);
552 : }
553 6638793 : return *this;
554 : }
555 :
556 2415921 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
557 : const AstRawString* raw_string) {
558 : size_t entry = GetConstantPoolEntry(raw_string);
559 : OutputLdaConstant(entry);
560 2415920 : return *this;
561 : }
562 :
563 8001 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(const Scope* scope) {
564 : size_t entry = GetConstantPoolEntry(scope);
565 : OutputLdaConstant(entry);
566 8001 : return *this;
567 : }
568 :
569 8628999 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
570 8628999 : const AstValue* ast_value) {
571 8628999 : if (ast_value->IsSmi()) {
572 5365418 : return LoadLiteral(ast_value->AsSmi());
573 3263581 : } else if (ast_value->IsUndefined()) {
574 124553 : return LoadUndefined();
575 3139028 : } else if (ast_value->IsTrue()) {
576 118534 : return LoadTrue();
577 3020494 : } else if (ast_value->IsFalse()) {
578 190882 : return LoadFalse();
579 2829612 : } else if (ast_value->IsNull()) {
580 72009 : return LoadNull();
581 2757603 : } else if (ast_value->IsTheHole()) {
582 0 : return LoadTheHole();
583 2757603 : } else if (ast_value->IsString()) {
584 1996919 : return LoadLiteral(ast_value->AsString());
585 760684 : } else if (ast_value->IsHeapNumber()) {
586 : size_t entry = GetConstantPoolEntry(ast_value);
587 : OutputLdaConstant(entry);
588 758484 : return *this;
589 : } else {
590 : // This should be the only ast value type left.
591 : DCHECK(ast_value->IsSymbol());
592 : size_t entry;
593 2200 : switch (ast_value->AsSymbol()) {
594 : case AstSymbol::kHomeObjectSymbol:
595 : entry = HomeObjectSymbolConstantPoolEntry();
596 2200 : break;
597 : // No default case so that we get a warning if AstSymbol changes
598 : }
599 : OutputLdaConstant(entry);
600 2200 : return *this;
601 : }
602 : }
603 :
604 806652 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
605 : OutputLdaUndefined();
606 806652 : return *this;
607 : }
608 :
609 75614 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
610 : OutputLdaNull();
611 75614 : return *this;
612 : }
613 :
614 643351 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
615 : OutputLdaTheHole();
616 643351 : return *this;
617 : }
618 :
619 140292 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
620 : OutputLdaTrue();
621 140292 : return *this;
622 : }
623 :
624 192602 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
625 : OutputLdaFalse();
626 192602 : return *this;
627 : }
628 :
629 8912204 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
630 : Register reg) {
631 8912204 : if (register_optimizer_) {
632 : // Defer source info so that if we elide the bytecode transfer, we attach
633 : // the source info to a subsequent bytecode or to a nop.
634 8909429 : SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kLdar));
635 8909423 : register_optimizer_->DoLdar(reg);
636 : } else {
637 : OutputLdar(reg);
638 : }
639 8912212 : return *this;
640 : }
641 :
642 24511013 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
643 : Register reg) {
644 24511013 : if (register_optimizer_) {
645 : // Defer source info so that if we elide the bytecode transfer, we attach
646 : // the source info to a subsequent bytecode or to a nop.
647 24505573 : SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kStar));
648 24505569 : register_optimizer_->DoStar(reg);
649 : } else {
650 : OutputStar(reg);
651 : }
652 24511027 : return *this;
653 : }
654 :
655 832366 : BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
656 : Register to) {
657 : DCHECK(from != to);
658 832366 : if (register_optimizer_) {
659 : // Defer source info so that if we elide the bytecode transfer, we attach
660 : // the source info to a subsequent bytecode or to a nop.
661 831841 : SetDeferredSourceInfo(CurrentSourcePosition(Bytecode::kMov));
662 831841 : register_optimizer_->DoMov(from, to);
663 : } else {
664 : OutputMov(from, to);
665 : }
666 832366 : return *this;
667 : }
668 :
669 1786901 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(const AstRawString* name,
670 : int feedback_slot,
671 : TypeofMode typeof_mode) {
672 : size_t name_index = GetConstantPoolEntry(name);
673 : // Ensure that typeof mode is in sync with the IC slot kind if the function
674 : // literal is available (not a unit test case).
675 : // TODO(ishell): check only in debug mode.
676 1786900 : if (literal_) {
677 : FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
678 1786888 : CHECK_EQ(GetTypeofModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
679 : typeof_mode);
680 : }
681 1786900 : if (typeof_mode == INSIDE_TYPEOF) {
682 : OutputLdaGlobalInsideTypeof(name_index, feedback_slot);
683 : } else {
684 : DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
685 : OutputLdaGlobal(name_index, feedback_slot);
686 : }
687 1786903 : return *this;
688 : }
689 :
690 828553 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
691 : const AstRawString* name, int feedback_slot, LanguageMode language_mode) {
692 : size_t name_index = GetConstantPoolEntry(name);
693 828553 : if (language_mode == SLOPPY) {
694 : OutputStaGlobalSloppy(name_index, feedback_slot);
695 : } else {
696 : DCHECK_EQ(language_mode, STRICT);
697 : OutputStaGlobalStrict(name_index, feedback_slot);
698 : }
699 828553 : return *this;
700 : }
701 :
702 2966915 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(
703 : Register context, int slot_index, int depth,
704 : ContextSlotMutability mutability) {
705 2966915 : if (context.is_current_context() && depth == 0) {
706 2810621 : if (mutability == kImmutableSlot) {
707 : OutputLdaImmutableCurrentContextSlot(slot_index);
708 : } else {
709 : DCHECK_EQ(kMutableSlot, mutability);
710 : OutputLdaCurrentContextSlot(slot_index);
711 : }
712 156295 : } else if (mutability == kImmutableSlot) {
713 : OutputLdaImmutableContextSlot(context, slot_index, depth);
714 : } else {
715 : DCHECK_EQ(mutability, kMutableSlot);
716 : OutputLdaContextSlot(context, slot_index, depth);
717 : }
718 2966917 : return *this;
719 : }
720 :
721 2381796 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
722 : int slot_index,
723 : int depth) {
724 2381796 : if (context.is_current_context() && depth == 0) {
725 : OutputStaCurrentContextSlot(slot_index);
726 : } else {
727 : OutputStaContextSlot(context, slot_index, depth);
728 : }
729 2381796 : return *this;
730 : }
731 :
732 16734 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
733 : const AstRawString* name, TypeofMode typeof_mode) {
734 : size_t name_index = GetConstantPoolEntry(name);
735 16734 : if (typeof_mode == INSIDE_TYPEOF) {
736 : OutputLdaLookupSlotInsideTypeof(name_index);
737 : } else {
738 : DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
739 : OutputLdaLookupSlot(name_index);
740 : }
741 16734 : return *this;
742 : }
743 :
744 3929 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot(
745 : const AstRawString* name, TypeofMode typeof_mode, int slot_index,
746 : int depth) {
747 : size_t name_index = GetConstantPoolEntry(name);
748 3929 : if (typeof_mode == INSIDE_TYPEOF) {
749 : OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth);
750 : } else {
751 : DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
752 : OutputLdaLookupContextSlot(name_index, slot_index, depth);
753 : }
754 3929 : return *this;
755 : }
756 :
757 463049 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot(
758 : const AstRawString* name, TypeofMode typeof_mode, int feedback_slot,
759 : int depth) {
760 : size_t name_index = GetConstantPoolEntry(name);
761 463049 : if (typeof_mode == INSIDE_TYPEOF) {
762 : OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth);
763 : } else {
764 : DCHECK(typeof_mode == NOT_INSIDE_TYPEOF);
765 : OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth);
766 : }
767 463049 : return *this;
768 : }
769 :
770 39473 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
771 : const AstRawString* name, LanguageMode language_mode) {
772 : size_t name_index = GetConstantPoolEntry(name);
773 39473 : if (language_mode == SLOPPY) {
774 : OutputStaLookupSlotSloppy(name_index);
775 : } else {
776 : DCHECK_EQ(language_mode, STRICT);
777 : OutputStaLookupSlotStrict(name_index);
778 : }
779 39473 : return *this;
780 : }
781 :
782 3658456 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
783 : Register object, const AstRawString* name, int feedback_slot) {
784 : size_t name_index = GetConstantPoolEntry(name);
785 : OutputLdaNamedProperty(object, name_index, feedback_slot);
786 3658453 : return *this;
787 : }
788 :
789 314189 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
790 : Register object, int feedback_slot) {
791 : OutputLdaKeyedProperty(object, feedback_slot);
792 314189 : return *this;
793 : }
794 :
795 34734 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadIteratorProperty(
796 : Register object, int feedback_slot) {
797 : size_t name_index = IteratorSymbolConstantPoolEntry();
798 : OutputLdaNamedProperty(object, name_index, feedback_slot);
799 34734 : return *this;
800 : }
801 :
802 375 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAsyncIteratorProperty(
803 : Register object, int feedback_slot) {
804 : size_t name_index = AsyncIteratorSymbolConstantPoolEntry();
805 : OutputLdaNamedProperty(object, name_index, feedback_slot);
806 375 : return *this;
807 : }
808 :
809 293715 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
810 : Register object, Register name, DataPropertyInLiteralFlags flags,
811 : int feedback_slot) {
812 : OutputStaDataPropertyInLiteral(object, name, flags, feedback_slot);
813 293715 : return *this;
814 : }
815 :
816 291 : BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
817 : DCHECK(FLAG_type_profile);
818 : OutputCollectTypeProfile(position);
819 291 : return *this;
820 : }
821 :
822 1466765 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
823 : Register object, size_t name_index, int feedback_slot,
824 : LanguageMode language_mode) {
825 : // Ensure that language mode is in sync with the IC slot kind if the function
826 : // literal is available (not a unit test case).
827 : // TODO(ishell): check only in debug mode.
828 1466765 : if (literal_) {
829 : FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
830 1466754 : CHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
831 : language_mode);
832 : }
833 1466765 : if (language_mode == SLOPPY) {
834 : OutputStaNamedPropertySloppy(object, name_index, feedback_slot);
835 : } else {
836 : DCHECK_EQ(language_mode, STRICT);
837 : OutputStaNamedPropertyStrict(object, name_index, feedback_slot);
838 : }
839 1466765 : return *this;
840 : }
841 :
842 1460441 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
843 : Register object, const AstRawString* name, int feedback_slot,
844 : LanguageMode language_mode) {
845 : size_t name_index = GetConstantPoolEntry(name);
846 1460441 : return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
847 : }
848 :
849 348382 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedOwnProperty(
850 : Register object, const AstRawString* name, int feedback_slot) {
851 : size_t name_index = GetConstantPoolEntry(name);
852 : // Ensure that the store operation is in sync with the IC slot kind if
853 : // the function literal is available (not a unit test case).
854 : // TODO(ishell): check only in debug mode.
855 348382 : if (literal_) {
856 : FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
857 348380 : CHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
858 : feedback_vector_spec()->GetKind(slot));
859 : }
860 : OutputStaNamedOwnProperty(object, name_index, feedback_slot);
861 348382 : return *this;
862 : }
863 :
864 319536 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
865 : Register object, Register key, int feedback_slot,
866 : LanguageMode language_mode) {
867 : // Ensure that language mode is in sync with the IC slot kind if the function
868 : // literal is available (not a unit test case).
869 : // TODO(ishell): check only in debug mode.
870 319536 : if (literal_) {
871 : FeedbackSlot slot = FeedbackVector::ToSlot(feedback_slot);
872 319525 : CHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
873 : language_mode);
874 : }
875 319536 : if (language_mode == SLOPPY) {
876 : OutputStaKeyedPropertySloppy(object, key, feedback_slot);
877 : } else {
878 : DCHECK_EQ(language_mode, STRICT);
879 : OutputStaKeyedPropertyStrict(object, key, feedback_slot);
880 : }
881 319536 : return *this;
882 : }
883 :
884 6324 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreHomeObjectProperty(
885 : Register object, int feedback_slot, LanguageMode language_mode) {
886 : size_t name_index = HomeObjectSymbolConstantPoolEntry();
887 6324 : return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
888 : }
889 :
890 3436917 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
891 : size_t shared_function_info_entry, int slot, int flags) {
892 : OutputCreateClosure(shared_function_info_entry, slot, flags);
893 3436922 : return *this;
894 : }
895 :
896 43951 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext(
897 : const Scope* scope) {
898 : size_t entry = GetConstantPoolEntry(scope);
899 : OutputCreateBlockContext(entry);
900 43951 : return *this;
901 : }
902 :
903 128267 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext(
904 : Register exception, const AstRawString* name, const Scope* scope) {
905 : size_t name_index = GetConstantPoolEntry(name);
906 : size_t scope_index = GetConstantPoolEntry(scope);
907 : OutputCreateCatchContext(exception, name_index, scope_index);
908 128267 : return *this;
909 : }
910 :
911 171820 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) {
912 : OutputCreateFunctionContext(slots);
913 171820 : return *this;
914 : }
915 :
916 21213 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEvalContext(int slots) {
917 : OutputCreateEvalContext(slots);
918 21213 : return *this;
919 : }
920 :
921 4054 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
922 : Register object, const Scope* scope) {
923 : size_t scope_index = GetConstantPoolEntry(scope);
924 : OutputCreateWithContext(object, scope_index);
925 4054 : return *this;
926 : }
927 :
928 122329 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
929 : CreateArgumentsType type) {
930 122329 : switch (type) {
931 : case CreateArgumentsType::kMappedArguments:
932 : OutputCreateMappedArguments();
933 : break;
934 : case CreateArgumentsType::kUnmappedArguments:
935 : OutputCreateUnmappedArguments();
936 : break;
937 : case CreateArgumentsType::kRestParameter:
938 : OutputCreateRestParameter();
939 : break;
940 : default:
941 0 : UNREACHABLE();
942 : }
943 122329 : return *this;
944 : }
945 :
946 52860 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
947 : const AstRawString* pattern, int literal_index, int flags) {
948 : size_t pattern_entry = GetConstantPoolEntry(pattern);
949 : OutputCreateRegExpLiteral(pattern_entry, literal_index, flags);
950 52860 : return *this;
951 : }
952 :
953 151464 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
954 : size_t constant_elements_entry, int literal_index, int flags) {
955 : OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
956 151464 : return *this;
957 : }
958 :
959 346964 : BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
960 : size_t constant_properties_entry, int literal_index, int flags,
961 : Register output) {
962 : OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags,
963 : output);
964 346964 : return *this;
965 : }
966 :
967 388127 : BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
968 : OutputPushContext(context);
969 388127 : return *this;
970 : }
971 :
972 239796 : BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
973 : OutputPopContext(context);
974 239796 : return *this;
975 : }
976 :
977 9818 : BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToObject(
978 : Register out) {
979 : OutputToObject(out);
980 9818 : return *this;
981 : }
982 :
983 9385 : BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToName(
984 : Register out) {
985 : OutputToName(out);
986 9385 : return *this;
987 : }
988 :
989 25344 : BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToNumber(
990 : Register out, int feedback_slot) {
991 : OutputToNumber(out, feedback_slot);
992 25344 : return *this;
993 : }
994 :
995 4749860 : BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
996 : // Flush the register optimizer when binding a label to ensure all
997 : // expected registers are valid when jumping to this label.
998 4749860 : if (register_optimizer_) register_optimizer_->Flush();
999 4749862 : bytecode_array_writer_.BindLabel(label);
1000 : LeaveBasicBlock();
1001 4749864 : return *this;
1002 : }
1003 :
1004 0 : BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
1005 : BytecodeLabel* label) {
1006 0 : bytecode_array_writer_.BindLabel(target, label);
1007 : LeaveBasicBlock();
1008 0 : return *this;
1009 : }
1010 :
1011 773087 : BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
1012 : DCHECK(!label->is_bound());
1013 : OutputJump(label, 0);
1014 773087 : return *this;
1015 : }
1016 :
1017 699822 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
1018 : BytecodeLabel* label) {
1019 : DCHECK(!label->is_bound());
1020 699822 : if (mode == ToBooleanMode::kAlreadyBoolean) {
1021 : OutputJumpIfTrue(label, 0);
1022 : } else {
1023 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1024 : OutputJumpIfToBooleanTrue(label, 0);
1025 : }
1026 699821 : return *this;
1027 : }
1028 :
1029 1100964 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
1030 : BytecodeLabel* label) {
1031 : DCHECK(!label->is_bound());
1032 1100964 : if (mode == ToBooleanMode::kAlreadyBoolean) {
1033 : OutputJumpIfFalse(label, 0);
1034 : } else {
1035 : DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1036 : OutputJumpIfToBooleanFalse(label, 0);
1037 : }
1038 1100964 : return *this;
1039 : }
1040 :
1041 16643 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
1042 : DCHECK(!label->is_bound());
1043 : OutputJumpIfNull(label, 0);
1044 16643 : return *this;
1045 : }
1046 :
1047 15846 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
1048 : BytecodeLabel* label) {
1049 : DCHECK(!label->is_bound());
1050 : OutputJumpIfNotNull(label, 0);
1051 15846 : return *this;
1052 : }
1053 :
1054 67140 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
1055 : BytecodeLabel* label) {
1056 : DCHECK(!label->is_bound());
1057 : OutputJumpIfUndefined(label, 0);
1058 67140 : return *this;
1059 : }
1060 :
1061 51576 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotUndefined(
1062 : BytecodeLabel* label) {
1063 : DCHECK(!label->is_bound());
1064 : OutputJumpIfNotUndefined(label, 0);
1065 51576 : return *this;
1066 : }
1067 :
1068 64102 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
1069 : Token::Value op,
1070 : NilValue nil) {
1071 64102 : if (op == Token::EQ) {
1072 : // TODO(rmcilroy): Implement JumpIfUndetectable.
1073 9184 : return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
1074 9184 : label);
1075 : } else {
1076 : DCHECK_EQ(Token::EQ_STRICT, op);
1077 54918 : if (nil == kUndefinedValue) {
1078 44416 : return JumpIfUndefined(label);
1079 : } else {
1080 : DCHECK_EQ(kNullValue, nil);
1081 10502 : return JumpIfNull(label);
1082 : }
1083 : }
1084 : }
1085 :
1086 106491 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
1087 : Token::Value op,
1088 : NilValue nil) {
1089 106491 : if (op == Token::EQ) {
1090 : // TODO(rmcilroy): Implement JumpIfUndetectable.
1091 39073 : return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
1092 39073 : label);
1093 : } else {
1094 : DCHECK_EQ(Token::EQ_STRICT, op);
1095 67418 : if (nil == kUndefinedValue) {
1096 51574 : return JumpIfNotUndefined(label);
1097 : } else {
1098 : DCHECK_EQ(kNullValue, nil);
1099 15844 : return JumpIfNotNull(label);
1100 : }
1101 : }
1102 : }
1103 :
1104 131834 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
1105 : BytecodeLabel* label) {
1106 : DCHECK(!label->is_bound());
1107 : OutputJumpIfNotHole(label, 0);
1108 131834 : return *this;
1109 : }
1110 :
1111 34736 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
1112 : BytecodeLabel* label) {
1113 : DCHECK(!label->is_bound());
1114 : OutputJumpIfJSReceiver(label, 0);
1115 34736 : return *this;
1116 : }
1117 :
1118 192804 : BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
1119 : int loop_depth) {
1120 : DCHECK(label->is_bound());
1121 : OutputJumpLoop(label, 0, loop_depth);
1122 192804 : return *this;
1123 : }
1124 :
1125 2270505 : BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
1126 2270505 : if (position != kNoSourcePosition) {
1127 : // We need to attach a non-breakable source position to a stack
1128 : // check, so we simply add it as expression position. There can be
1129 : // a prior statement position from constructs like:
1130 : //
1131 : // do var x; while (false);
1132 : //
1133 : // A Nop could be inserted for empty statements, but since no code
1134 : // is associated with these positions, instead we force the stack
1135 : // check's expression position which eliminates the empty
1136 : // statement's position.
1137 : latest_source_info_.ForceExpressionPosition(position);
1138 : }
1139 : OutputStackCheck();
1140 2270511 : return *this;
1141 : }
1142 :
1143 192740 : BytecodeArrayBuilder& BytecodeArrayBuilder::SetPendingMessage() {
1144 : OutputSetPendingMessage();
1145 192740 : return *this;
1146 : }
1147 :
1148 123692 : BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
1149 : OutputThrow();
1150 123692 : return *this;
1151 : }
1152 :
1153 57197 : BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
1154 : OutputReThrow();
1155 57197 : return *this;
1156 : }
1157 :
1158 2604077 : BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
1159 : SetReturnPosition();
1160 : OutputReturn();
1161 2604087 : return_seen_in_block_ = true;
1162 2604087 : return *this;
1163 : }
1164 :
1165 10286 : BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
1166 : OutputDebugger();
1167 10286 : return *this;
1168 : }
1169 :
1170 5773 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
1171 : Register receiver, RegisterList cache_info_triple) {
1172 : DCHECK_EQ(3, cache_info_triple.register_count());
1173 : OutputForInPrepare(receiver, cache_info_triple);
1174 5773 : return *this;
1175 : }
1176 :
1177 5765 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue(
1178 : Register index, Register cache_length) {
1179 : OutputForInContinue(index, cache_length);
1180 5765 : return *this;
1181 : }
1182 :
1183 5765 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
1184 : Register receiver, Register index, RegisterList cache_type_array_pair,
1185 : int feedback_slot) {
1186 : DCHECK_EQ(2, cache_type_array_pair.register_count());
1187 : OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot);
1188 5765 : return *this;
1189 : }
1190 :
1191 5765 : BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
1192 : OutputForInStep(index);
1193 5765 : return *this;
1194 : }
1195 :
1196 1820 : BytecodeArrayBuilder& BytecodeArrayBuilder::StoreModuleVariable(int cell_index,
1197 : int depth) {
1198 : OutputStaModuleVariable(cell_index, depth);
1199 1820 : return *this;
1200 : }
1201 :
1202 1716 : BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index,
1203 : int depth) {
1204 : OutputLdaModuleVariable(cell_index, depth);
1205 1716 : return *this;
1206 : }
1207 :
1208 19834 : BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
1209 : Register generator, SuspendFlags flags) {
1210 : OutputSuspendGenerator(generator,
1211 19834 : SuspendGeneratorBytecodeFlags::Encode(flags));
1212 19834 : return *this;
1213 : }
1214 :
1215 10820 : BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
1216 : Register generator) {
1217 : OutputResumeGenerator(generator);
1218 10820 : return *this;
1219 : }
1220 :
1221 176533 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
1222 : int handler_id, HandlerTable::CatchPrediction catch_prediction) {
1223 : BytecodeLabel handler;
1224 176533 : Bind(&handler);
1225 176533 : handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
1226 176533 : handler_table_builder()->SetPrediction(handler_id, catch_prediction);
1227 176533 : return *this;
1228 : }
1229 :
1230 176533 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
1231 : Register context) {
1232 : BytecodeLabel try_begin;
1233 176533 : Bind(&try_begin);
1234 176533 : handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
1235 176533 : handler_table_builder()->SetContextRegister(handler_id, context);
1236 176533 : return *this;
1237 : }
1238 :
1239 176533 : BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
1240 : BytecodeLabel try_end;
1241 176533 : Bind(&try_end);
1242 176533 : handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
1243 176533 : return *this;
1244 : }
1245 :
1246 1000243 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable,
1247 : RegisterList args,
1248 : int feedback_slot) {
1249 1000243 : if (args.register_count() == 1) {
1250 : OutputCallProperty0(callable, args[0], feedback_slot);
1251 708629 : } else if (args.register_count() == 2) {
1252 : OutputCallProperty1(callable, args[0], args[1], feedback_slot);
1253 208032 : } else if (args.register_count() == 3) {
1254 : OutputCallProperty2(callable, args[0], args[1], args[2], feedback_slot);
1255 : } else {
1256 : OutputCallProperty(callable, args, args.register_count(), feedback_slot);
1257 : }
1258 1000243 : return *this;
1259 : }
1260 :
1261 1426925 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallUndefinedReceiver(
1262 : Register callable, RegisterList args, int feedback_slot) {
1263 1426925 : if (args.register_count() == 0) {
1264 : OutputCallUndefinedReceiver0(callable, feedback_slot);
1265 1237775 : } else if (args.register_count() == 1) {
1266 : OutputCallUndefinedReceiver1(callable, args[0], feedback_slot);
1267 659253 : } else if (args.register_count() == 2) {
1268 : OutputCallUndefinedReceiver2(callable, args[0], args[1], feedback_slot);
1269 : } else {
1270 : OutputCallUndefinedReceiver(callable, args, args.register_count(),
1271 : feedback_slot);
1272 : }
1273 1426932 : return *this;
1274 : }
1275 :
1276 3188 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
1277 : RegisterList args,
1278 : int feedback_slot) {
1279 : OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot);
1280 3188 : return *this;
1281 : }
1282 :
1283 1173 : BytecodeArrayBuilder& BytecodeArrayBuilder::TailCall(Register callable,
1284 : RegisterList args,
1285 : int feedback_slot) {
1286 : OutputTailCall(callable, args, args.register_count(), feedback_slot);
1287 1173 : return *this;
1288 : }
1289 :
1290 1837 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
1291 : RegisterList args) {
1292 : OutputCallWithSpread(callable, args, args.register_count());
1293 1837 : return *this;
1294 : }
1295 :
1296 222230 : BytecodeArrayBuilder& BytecodeArrayBuilder::Construct(Register constructor,
1297 : RegisterList args,
1298 : int feedback_slot_id) {
1299 : OutputConstruct(constructor, args, args.register_count(), feedback_slot_id);
1300 222230 : return *this;
1301 : }
1302 :
1303 3208 : BytecodeArrayBuilder& BytecodeArrayBuilder::ConstructWithSpread(
1304 : Register constructor, RegisterList args) {
1305 : OutputConstructWithSpread(constructor, args, args.register_count());
1306 3208 : return *this;
1307 : }
1308 :
1309 1793555 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1310 : Runtime::FunctionId function_id, RegisterList args) {
1311 : DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
1312 : DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
1313 1793555 : if (IntrinsicsHelper::IsSupported(function_id)) {
1314 : IntrinsicsHelper::IntrinsicId intrinsic_id =
1315 328181 : IntrinsicsHelper::FromRuntimeId(function_id);
1316 : OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args,
1317 : args.register_count());
1318 : } else {
1319 : OutputCallRuntime(static_cast<int>(function_id), args,
1320 : args.register_count());
1321 : }
1322 1793555 : return *this;
1323 : }
1324 :
1325 544033 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1326 : Runtime::FunctionId function_id, Register arg) {
1327 544033 : return CallRuntime(function_id, RegisterList(arg.index(), 1));
1328 : }
1329 :
1330 88992 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
1331 : Runtime::FunctionId function_id) {
1332 88992 : return CallRuntime(function_id, RegisterList());
1333 : }
1334 :
1335 2763 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1336 : Runtime::FunctionId function_id, RegisterList args,
1337 : RegisterList return_pair) {
1338 : DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
1339 : DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
1340 : DCHECK_EQ(2, return_pair.register_count());
1341 : OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args,
1342 2763 : args.register_count(), return_pair);
1343 2763 : return *this;
1344 : }
1345 :
1346 2762 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
1347 : Runtime::FunctionId function_id, Register arg, RegisterList return_pair) {
1348 : return CallRuntimeForPair(function_id, RegisterList(arg.index(), 1),
1349 2762 : return_pair);
1350 : }
1351 :
1352 127360 : BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
1353 : RegisterList args) {
1354 : OutputCallJSRuntime(context_index, args, args.register_count());
1355 127360 : return *this;
1356 : }
1357 :
1358 9478 : BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
1359 : LanguageMode language_mode) {
1360 9478 : if (language_mode == SLOPPY) {
1361 : OutputDeletePropertySloppy(object);
1362 : } else {
1363 : DCHECK_EQ(language_mode, STRICT);
1364 : OutputDeletePropertyStrict(object);
1365 : }
1366 9478 : return *this;
1367 : }
1368 :
1369 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(
1370 : const AstRawString* raw_string) {
1371 11202966 : return constant_array_builder()->Insert(raw_string);
1372 : }
1373 :
1374 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(const AstValue* heap_number) {
1375 : DCHECK(heap_number->IsHeapNumber());
1376 758484 : return constant_array_builder()->Insert(heap_number);
1377 : }
1378 :
1379 0 : size_t BytecodeArrayBuilder::GetConstantPoolEntry(const Scope* scope) {
1380 184273 : return constant_array_builder()->Insert(scope);
1381 : }
1382 :
1383 : #define ENTRY_GETTER(NAME, ...) \
1384 : size_t BytecodeArrayBuilder::NAME##ConstantPoolEntry() { \
1385 : return constant_array_builder()->Insert##NAME(); \
1386 : }
1387 94262 : SINGLETON_CONSTANT_ENTRY_TYPES(ENTRY_GETTER)
1388 : #undef ENTRY_GETTER
1389 :
1390 3962136 : size_t BytecodeArrayBuilder::AllocateDeferredConstantPoolEntry() {
1391 3962136 : return constant_array_builder()->InsertDeferred();
1392 : }
1393 :
1394 3962142 : void BytecodeArrayBuilder::SetDeferredConstantPoolEntry(size_t entry,
1395 : Handle<Object> object) {
1396 3962142 : constant_array_builder()->SetDeferredAt(entry, object);
1397 3962142 : }
1398 :
1399 0 : void BytecodeArrayBuilder::SetReturnPosition() {
1400 2604077 : if (return_position_ == kNoSourcePosition) return;
1401 : latest_source_info_.MakeStatementPosition(return_position_);
1402 : }
1403 :
1404 0 : bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
1405 0 : if (!reg.is_valid()) {
1406 : return false;
1407 : }
1408 :
1409 0 : if (reg.is_current_context() || reg.is_function_closure() ||
1410 0 : reg.is_new_target()) {
1411 : return true;
1412 0 : } else if (reg.is_parameter()) {
1413 0 : int parameter_index = reg.ToParameterIndex(parameter_count());
1414 0 : return parameter_index >= 0 && parameter_index < parameter_count();
1415 0 : } else if (reg.index() < fixed_register_count()) {
1416 : return true;
1417 : } else {
1418 0 : return register_allocator()->RegisterIsLive(reg);
1419 : }
1420 : }
1421 :
1422 0 : bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const {
1423 0 : if (reg_list.register_count() == 0) {
1424 : return reg_list.first_register() == Register(0);
1425 : } else {
1426 : int first_reg_index = reg_list.first_register().index();
1427 0 : for (int i = 0; i < reg_list.register_count(); i++) {
1428 0 : if (!RegisterIsValid(Register(first_reg_index + i))) {
1429 : return false;
1430 : }
1431 : }
1432 : return true;
1433 : }
1434 : }
1435 :
1436 : template <Bytecode bytecode, AccumulatorUse accumulator_use>
1437 47564312 : void BytecodeArrayBuilder::PrepareToOutputBytecode() {
1438 47564312 : if (register_optimizer_)
1439 : register_optimizer_->PrepareForBytecode<bytecode, accumulator_use>();
1440 47564320 : }
1441 :
1442 15522384 : uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) {
1443 : DCHECK(RegisterIsValid(reg));
1444 15522384 : if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg);
1445 15522383 : return static_cast<uint32_t>(reg.ToOperand());
1446 : }
1447 :
1448 789715 : uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) {
1449 : DCHECK(RegisterIsValid(reg));
1450 789715 : if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg);
1451 789714 : return static_cast<uint32_t>(reg.ToOperand());
1452 : }
1453 :
1454 2381546 : uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand(
1455 : RegisterList reg_list) {
1456 : DCHECK(RegisterListIsValid(reg_list));
1457 2381546 : if (register_optimizer_)
1458 2380621 : reg_list = register_optimizer_->GetInputRegisterList(reg_list);
1459 2381548 : return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1460 : }
1461 :
1462 8536 : uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
1463 : RegisterList reg_list) {
1464 : DCHECK(RegisterListIsValid(reg_list));
1465 8536 : if (register_optimizer_)
1466 8536 : register_optimizer_->PrepareOutputRegisterList(reg_list);
1467 8536 : return static_cast<uint32_t>(reg_list.first_register().ToOperand());
1468 : }
1469 :
1470 0 : std::ostream& operator<<(std::ostream& os,
1471 : const BytecodeArrayBuilder::ToBooleanMode& mode) {
1472 0 : switch (mode) {
1473 : case BytecodeArrayBuilder::ToBooleanMode::kAlreadyBoolean:
1474 0 : return os << "AlreadyBoolean";
1475 : case BytecodeArrayBuilder::ToBooleanMode::kConvertToBoolean:
1476 0 : return os << "ConvertToBoolean";
1477 : }
1478 0 : UNREACHABLE();
1479 : return os;
1480 : }
1481 :
1482 : } // namespace interpreter
1483 : } // namespace internal
1484 : } // namespace v8
|