blob: cf0b6ab43810bd8e03d384c231afb053ea419afa [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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/compiler/bytecode-graph-builder.h"
6
7#include "src/compiler/bytecode-branch-analysis.h"
8#include "src/compiler/linkage.h"
9#include "src/compiler/operator-properties.h"
10#include "src/interpreter/bytecodes.h"
11
12namespace v8 {
13namespace internal {
14namespace compiler {
15
16// Helper for generating frame states for before and after a bytecode.
17class BytecodeGraphBuilder::FrameStateBeforeAndAfter {
18 public:
19 FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder,
20 const interpreter::BytecodeArrayIterator& iterator)
21 : builder_(builder),
22 id_after_(BailoutId::None()),
23 added_to_node_(false),
24 output_poke_offset_(0),
25 output_poke_count_(0) {
26 BailoutId id_before(iterator.current_offset());
27 frame_state_before_ = builder_->environment()->Checkpoint(
28 id_before, OutputFrameStateCombine::Ignore());
29 id_after_ = BailoutId(id_before.ToInt() + iterator.current_bytecode_size());
30 }
31
32 ~FrameStateBeforeAndAfter() {
33 DCHECK(added_to_node_);
34 DCHECK(builder_->environment()->StateValuesAreUpToDate(output_poke_offset_,
35 output_poke_count_));
36 }
37
38 private:
39 friend class Environment;
40
41 void AddToNode(Node* node, OutputFrameStateCombine combine) {
42 DCHECK(!added_to_node_);
43 int count = OperatorProperties::GetFrameStateInputCount(node->op());
44 DCHECK_LE(count, 2);
45 if (count >= 1) {
46 // Add the frame state for after the operation.
47 DCHECK_EQ(IrOpcode::kDead,
48 NodeProperties::GetFrameStateInput(node, 0)->opcode());
49 Node* frame_state_after =
50 builder_->environment()->Checkpoint(id_after_, combine);
51 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after);
52 }
53
54 if (count >= 2) {
55 // Add the frame state for before the operation.
56 DCHECK_EQ(IrOpcode::kDead,
57 NodeProperties::GetFrameStateInput(node, 1)->opcode());
58 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
59 }
60
61 if (!combine.IsOutputIgnored()) {
62 output_poke_offset_ = static_cast<int>(combine.GetOffsetToPokeAt());
63 output_poke_count_ = node->op()->ValueOutputCount();
64 }
65 added_to_node_ = true;
66 }
67
68 BytecodeGraphBuilder* builder_;
69 Node* frame_state_before_;
70 BailoutId id_after_;
71
72 bool added_to_node_;
73 int output_poke_offset_;
74 int output_poke_count_;
75};
76
77
78// Issues:
79// - Scopes - intimately tied to AST. Need to eval what is needed.
80// - Need to resolve closure parameter treatment.
81BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder,
82 int register_count,
83 int parameter_count,
84 Node* control_dependency,
85 Node* context)
86 : builder_(builder),
87 register_count_(register_count),
88 parameter_count_(parameter_count),
89 context_(context),
90 control_dependency_(control_dependency),
91 effect_dependency_(control_dependency),
92 values_(builder->local_zone()),
93 parameters_state_values_(nullptr),
94 registers_state_values_(nullptr),
95 accumulator_state_values_(nullptr) {
96 // The layout of values_ is:
97 //
98 // [receiver] [parameters] [registers] [accumulator]
99 //
100 // parameter[0] is the receiver (this), parameters 1..N are the
101 // parameters supplied to the method (arg0..argN-1). The accumulator
102 // is stored separately.
103
104 // Parameters including the receiver
105 for (int i = 0; i < parameter_count; i++) {
106 const char* debug_name = (i == 0) ? "%this" : nullptr;
107 const Operator* op = common()->Parameter(i, debug_name);
108 Node* parameter = builder->graph()->NewNode(op, graph()->start());
109 values()->push_back(parameter);
110 }
111
112 // Registers
113 register_base_ = static_cast<int>(values()->size());
114 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
115 values()->insert(values()->end(), register_count, undefined_constant);
116
117 // Accumulator
118 accumulator_base_ = static_cast<int>(values()->size());
119 values()->push_back(undefined_constant);
120}
121
122
123BytecodeGraphBuilder::Environment::Environment(
124 const BytecodeGraphBuilder::Environment* other)
125 : builder_(other->builder_),
126 register_count_(other->register_count_),
127 parameter_count_(other->parameter_count_),
128 context_(other->context_),
129 control_dependency_(other->control_dependency_),
130 effect_dependency_(other->effect_dependency_),
131 values_(other->zone()),
132 parameters_state_values_(nullptr),
133 registers_state_values_(nullptr),
134 accumulator_state_values_(nullptr),
135 register_base_(other->register_base_),
136 accumulator_base_(other->accumulator_base_) {
137 values_ = other->values_;
138}
139
140
141int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
142 interpreter::Register the_register) const {
143 if (the_register.is_parameter()) {
144 return the_register.ToParameterIndex(parameter_count());
145 } else {
146 return the_register.index() + register_base();
147 }
148}
149
150
151Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
152 return values()->at(accumulator_base_);
153}
154
155
156Node* BytecodeGraphBuilder::Environment::LookupRegister(
157 interpreter::Register the_register) const {
158 if (the_register.is_function_context()) {
159 return builder()->GetFunctionContext();
160 } else if (the_register.is_function_closure()) {
161 return builder()->GetFunctionClosure();
162 } else if (the_register.is_new_target()) {
163 return builder()->GetNewTarget();
164 } else {
165 int values_index = RegisterToValuesIndex(the_register);
166 return values()->at(values_index);
167 }
168}
169
170
171void BytecodeGraphBuilder::Environment::ExchangeRegisters(
172 interpreter::Register reg0, interpreter::Register reg1) {
173 int reg0_index = RegisterToValuesIndex(reg0);
174 int reg1_index = RegisterToValuesIndex(reg1);
175 Node* saved_reg0_value = values()->at(reg0_index);
176 values()->at(reg0_index) = values()->at(reg1_index);
177 values()->at(reg1_index) = saved_reg0_value;
178}
179
180
181void BytecodeGraphBuilder::Environment::BindAccumulator(
182 Node* node, FrameStateBeforeAndAfter* states) {
183 if (states) {
184 states->AddToNode(node, OutputFrameStateCombine::PokeAt(0));
185 }
186 values()->at(accumulator_base_) = node;
187}
188
189
190void BytecodeGraphBuilder::Environment::BindRegister(
191 interpreter::Register the_register, Node* node,
192 FrameStateBeforeAndAfter* states) {
193 int values_index = RegisterToValuesIndex(the_register);
194 if (states) {
195 states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ -
196 values_index));
197 }
198 values()->at(values_index) = node;
199}
200
201
202void BytecodeGraphBuilder::Environment::BindRegistersToProjections(
203 interpreter::Register first_reg, Node* node,
204 FrameStateBeforeAndAfter* states) {
205 int values_index = RegisterToValuesIndex(first_reg);
206 if (states) {
207 states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ -
208 values_index));
209 }
210 for (int i = 0; i < node->op()->ValueOutputCount(); i++) {
211 values()->at(values_index + i) =
212 builder()->NewNode(common()->Projection(i), node);
213 }
214}
215
216
217void BytecodeGraphBuilder::Environment::RecordAfterState(
218 Node* node, FrameStateBeforeAndAfter* states) {
219 states->AddToNode(node, OutputFrameStateCombine::Ignore());
220}
221
222
223bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const {
224 return GetControlDependency()->opcode() == IrOpcode::kDead;
225}
226
227
228void BytecodeGraphBuilder::Environment::MarkAsUnreachable() {
229 UpdateControlDependency(builder()->jsgraph()->Dead());
230}
231
232
233BytecodeGraphBuilder::Environment*
234BytecodeGraphBuilder::Environment::CopyForLoop() {
235 PrepareForLoop();
236 return new (zone()) Environment(this);
237}
238
239
240BytecodeGraphBuilder::Environment*
241BytecodeGraphBuilder::Environment::CopyForConditional() const {
242 return new (zone()) Environment(this);
243}
244
245
246void BytecodeGraphBuilder::Environment::Merge(
247 BytecodeGraphBuilder::Environment* other) {
248 // Nothing to do if the other environment is dead.
249 if (other->IsMarkedAsUnreachable()) {
250 return;
251 }
252
253 // Create a merge of the control dependencies of both environments and update
254 // the current environment's control dependency accordingly.
255 Node* control = builder()->MergeControl(GetControlDependency(),
256 other->GetControlDependency());
257 UpdateControlDependency(control);
258
259 // Create a merge of the effect dependencies of both environments and update
260 // the current environment's effect dependency accordingly.
261 Node* effect = builder()->MergeEffect(GetEffectDependency(),
262 other->GetEffectDependency(), control);
263 UpdateEffectDependency(effect);
264
265 // Introduce Phi nodes for values that have differing input at merge points,
266 // potentially extending an existing Phi node if possible.
267 context_ = builder()->MergeValue(context_, other->context_, control);
268 for (size_t i = 0; i < values_.size(); i++) {
269 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control);
270 }
271}
272
273
274void BytecodeGraphBuilder::Environment::PrepareForLoop() {
275 // Create a control node for the loop header.
276 Node* control = builder()->NewLoop();
277
278 // Create a Phi for external effects.
279 Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control);
280 UpdateEffectDependency(effect);
281
282 // Assume everything in the loop is updated.
283 context_ = builder()->NewPhi(1, context_, control);
284 int size = static_cast<int>(values()->size());
285 for (int i = 0; i < size; i++) {
286 values()->at(i) = builder()->NewPhi(1, values()->at(i), control);
287 }
288
289 // Connect to the loop end.
290 Node* terminate = builder()->graph()->NewNode(
291 builder()->common()->Terminate(), effect, control);
292 builder()->exit_controls_.push_back(terminate);
293}
294
295
296bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
297 Node** state_values, int offset, int count) {
298 if (!builder()->info()->is_deoptimization_enabled()) {
299 return false;
300 }
301 if (*state_values == nullptr) {
302 return true;
303 }
304 DCHECK_EQ((*state_values)->InputCount(), count);
305 DCHECK_LE(static_cast<size_t>(offset + count), values()->size());
306 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
307 for (int i = 0; i < count; i++) {
308 if ((*state_values)->InputAt(i) != env_values[i]) {
309 return true;
310 }
311 }
312 return false;
313}
314
315
316void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
317 int offset,
318 int count) {
319 if (StateValuesRequireUpdate(state_values, offset, count)) {
320 const Operator* op = common()->StateValues(count);
321 (*state_values) = graph()->NewNode(op, count, &values()->at(offset));
322 }
323}
324
325
326Node* BytecodeGraphBuilder::Environment::Checkpoint(
327 BailoutId bailout_id, OutputFrameStateCombine combine) {
328 if (!builder()->info()->is_deoptimization_enabled()) {
329 return builder()->jsgraph()->EmptyFrameState();
330 }
331
332 // TODO(rmcilroy): Consider using StateValuesCache for some state values.
333 UpdateStateValues(&parameters_state_values_, 0, parameter_count());
334 UpdateStateValues(&registers_state_values_, register_base(),
335 register_count());
336 UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1);
337
338 const Operator* op = common()->FrameState(
339 bailout_id, combine, builder()->frame_state_function_info());
340 Node* result = graph()->NewNode(
341 op, parameters_state_values_, registers_state_values_,
342 accumulator_state_values_, Context(), builder()->GetFunctionClosure(),
343 builder()->graph()->start());
344
345 return result;
346}
347
348
349bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate(
350 Node** state_values, int offset, int count, int output_poke_start,
351 int output_poke_end) {
352 DCHECK_LE(static_cast<size_t>(offset + count), values()->size());
353 for (int i = 0; i < count; i++, offset++) {
354 if (offset < output_poke_start || offset >= output_poke_end) {
355 if ((*state_values)->InputAt(i) != values()->at(offset)) {
356 return false;
357 }
358 }
359 }
360 return true;
361}
362
363
364bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate(
365 int output_poke_offset, int output_poke_count) {
366 // Poke offset is relative to the top of the stack (i.e., the accumulator).
367 int output_poke_start = accumulator_base() - output_poke_offset;
368 int output_poke_end = output_poke_start + output_poke_count;
369 return StateValuesAreUpToDate(&parameters_state_values_, 0, parameter_count(),
370 output_poke_start, output_poke_end) &&
371 StateValuesAreUpToDate(&registers_state_values_, register_base(),
372 register_count(), output_poke_start,
373 output_poke_end) &&
374 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(),
375 1, output_poke_start, output_poke_end);
376}
377
378
379BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
380 CompilationInfo* compilation_info,
381 JSGraph* jsgraph)
382 : local_zone_(local_zone),
383 info_(compilation_info),
384 jsgraph_(jsgraph),
385 bytecode_array_(handle(info()->shared_info()->bytecode_array())),
386 frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
387 FrameStateType::kInterpretedFunction,
388 bytecode_array()->parameter_count(),
389 bytecode_array()->register_count(), info()->shared_info(),
390 CALL_MAINTAINS_NATIVE_CONTEXT)),
391 merge_environments_(local_zone),
392 loop_header_environments_(local_zone),
393 input_buffer_size_(0),
394 input_buffer_(nullptr),
395 exit_controls_(local_zone) {}
396
397
398Node* BytecodeGraphBuilder::GetNewTarget() {
399 if (!new_target_.is_set()) {
400 int params = bytecode_array()->parameter_count();
401 int index = Linkage::GetJSCallNewTargetParamIndex(params);
402 const Operator* op = common()->Parameter(index, "%new.target");
403 Node* node = NewNode(op, graph()->start());
404 new_target_.set(node);
405 }
406 return new_target_.get();
407}
408
409
410Node* BytecodeGraphBuilder::GetFunctionContext() {
411 if (!function_context_.is_set()) {
412 int params = bytecode_array()->parameter_count();
413 int index = Linkage::GetJSCallContextParamIndex(params);
414 const Operator* op = common()->Parameter(index, "%context");
415 Node* node = NewNode(op, graph()->start());
416 function_context_.set(node);
417 }
418 return function_context_.get();
419}
420
421
422Node* BytecodeGraphBuilder::GetFunctionClosure() {
423 if (!function_closure_.is_set()) {
424 int index = Linkage::kJSCallClosureParamIndex;
425 const Operator* op = common()->Parameter(index, "%closure");
426 Node* node = NewNode(op, graph()->start());
427 function_closure_.set(node);
428 }
429 return function_closure_.get();
430}
431
432
433Node* BytecodeGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
434 return NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()), object,
435 jsgraph()->IntPtrConstant(offset - kHeapObjectTag));
436}
437
438
439Node* BytecodeGraphBuilder::BuildLoadImmutableObjectField(Node* object,
440 int offset) {
441 return graph()->NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()),
442 object,
443 jsgraph()->IntPtrConstant(offset - kHeapObjectTag),
444 graph()->start(), graph()->start());
445}
446
447
448Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
449 const Operator* op =
450 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
451 Node* native_context = NewNode(op, environment()->Context());
452 return NewNode(javascript()->LoadContext(0, index, true), native_context);
453}
454
455
456Node* BytecodeGraphBuilder::BuildLoadFeedbackVector() {
457 if (!feedback_vector_.is_set()) {
458 Node* closure = GetFunctionClosure();
459 Node* shared = BuildLoadImmutableObjectField(
460 closure, JSFunction::kSharedFunctionInfoOffset);
461 Node* vector = BuildLoadImmutableObjectField(
462 shared, SharedFunctionInfo::kFeedbackVectorOffset);
463 feedback_vector_.set(vector);
464 }
465 return feedback_vector_.get();
466}
467
468
469VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
470 Handle<TypeFeedbackVector> feedback_vector = info()->feedback_vector();
471 FeedbackVectorSlot slot;
472 if (slot_id >= TypeFeedbackVector::kReservedIndexCount) {
473 slot = feedback_vector->ToSlot(slot_id);
474 }
475 return VectorSlotPair(feedback_vector, slot);
476}
477
478
479bool BytecodeGraphBuilder::CreateGraph(bool stack_check) {
480 // Set up the basic structure of the graph. Outputs for {Start} are
481 // the formal parameters (including the receiver) plus context and
482 // closure.
483
484 // Set up the basic structure of the graph. Outputs for {Start} are the formal
485 // parameters (including the receiver) plus new target, number of arguments,
486 // context and closure.
487 int actual_parameter_count = bytecode_array()->parameter_count() + 4;
488 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
489
490 Environment env(this, bytecode_array()->register_count(),
491 bytecode_array()->parameter_count(), graph()->start(),
492 GetFunctionContext());
493 set_environment(&env);
494
495 CreateGraphBody(stack_check);
496
497 // Finish the basic structure of the graph.
498 DCHECK_NE(0u, exit_controls_.size());
499 int const input_count = static_cast<int>(exit_controls_.size());
500 Node** const inputs = &exit_controls_.front();
501 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
502 graph()->SetEnd(end);
503
504 return true;
505}
506
507
508void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) {
509 // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments
510 // object setup, this function variable if used, tracing hooks.
511
512 if (stack_check) {
513 Node* node = NewNode(javascript()->StackCheck());
514 PrepareEntryFrameState(node);
515 }
516
517 VisitBytecodes();
518}
519
520
521void BytecodeGraphBuilder::VisitBytecodes() {
522 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone());
523 analysis.Analyze();
524 set_branch_analysis(&analysis);
525 interpreter::BytecodeArrayIterator iterator(bytecode_array());
526 set_bytecode_iterator(&iterator);
527 while (!iterator.done()) {
528 int current_offset = iterator.current_offset();
529 if (analysis.is_reachable(current_offset)) {
530 MergeEnvironmentsOfForwardBranches(current_offset);
531 BuildLoopHeaderForBackwardBranches(current_offset);
532
533 switch (iterator.current_bytecode()) {
534#define BYTECODE_CASE(name, ...) \
535 case interpreter::Bytecode::k##name: \
536 Visit##name(iterator); \
537 break;
538 BYTECODE_LIST(BYTECODE_CASE)
539#undef BYTECODE_CODE
540 }
541 }
542 iterator.Advance();
543 }
544 set_branch_analysis(nullptr);
545 set_bytecode_iterator(nullptr);
546}
547
548
549void BytecodeGraphBuilder::VisitLdaZero(
550 const interpreter::BytecodeArrayIterator& iterator) {
551 Node* node = jsgraph()->ZeroConstant();
552 environment()->BindAccumulator(node);
553}
554
555
556void BytecodeGraphBuilder::VisitLdaSmi8(
557 const interpreter::BytecodeArrayIterator& iterator) {
558 Node* node = jsgraph()->Constant(iterator.GetImmediateOperand(0));
559 environment()->BindAccumulator(node);
560}
561
562
563void BytecodeGraphBuilder::VisitLdaConstantWide(
564 const interpreter::BytecodeArrayIterator& iterator) {
565 Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0));
566 environment()->BindAccumulator(node);
567}
568
569
570void BytecodeGraphBuilder::VisitLdaConstant(
571 const interpreter::BytecodeArrayIterator& iterator) {
572 Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0));
573 environment()->BindAccumulator(node);
574}
575
576
577void BytecodeGraphBuilder::VisitLdaUndefined(
578 const interpreter::BytecodeArrayIterator& iterator) {
579 Node* node = jsgraph()->UndefinedConstant();
580 environment()->BindAccumulator(node);
581}
582
583
584void BytecodeGraphBuilder::VisitLdaNull(
585 const interpreter::BytecodeArrayIterator& iterator) {
586 Node* node = jsgraph()->NullConstant();
587 environment()->BindAccumulator(node);
588}
589
590
591void BytecodeGraphBuilder::VisitLdaTheHole(
592 const interpreter::BytecodeArrayIterator& iterator) {
593 Node* node = jsgraph()->TheHoleConstant();
594 environment()->BindAccumulator(node);
595}
596
597
598void BytecodeGraphBuilder::VisitLdaTrue(
599 const interpreter::BytecodeArrayIterator& iterator) {
600 Node* node = jsgraph()->TrueConstant();
601 environment()->BindAccumulator(node);
602}
603
604
605void BytecodeGraphBuilder::VisitLdaFalse(
606 const interpreter::BytecodeArrayIterator& iterator) {
607 Node* node = jsgraph()->FalseConstant();
608 environment()->BindAccumulator(node);
609}
610
611
612void BytecodeGraphBuilder::VisitLdar(
613 const interpreter::BytecodeArrayIterator& iterator) {
614 Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0));
615 environment()->BindAccumulator(value);
616}
617
618
619void BytecodeGraphBuilder::VisitStar(
620 const interpreter::BytecodeArrayIterator& iterator) {
621 Node* value = environment()->LookupAccumulator();
622 environment()->BindRegister(iterator.GetRegisterOperand(0), value);
623}
624
625
626void BytecodeGraphBuilder::VisitMov(
627 const interpreter::BytecodeArrayIterator& iterator) {
628 Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0));
629 environment()->BindRegister(iterator.GetRegisterOperand(1), value);
630}
631
632
633void BytecodeGraphBuilder::VisitExchange(
634 const interpreter::BytecodeArrayIterator& iterator) {
635 environment()->ExchangeRegisters(iterator.GetRegisterOperand(0),
636 iterator.GetRegisterOperand(1));
637}
638
639
640void BytecodeGraphBuilder::VisitExchangeWide(
641 const interpreter::BytecodeArrayIterator& iterator) {
642 environment()->ExchangeRegisters(iterator.GetRegisterOperand(0),
643 iterator.GetRegisterOperand(1));
644}
645
646
647void BytecodeGraphBuilder::BuildLoadGlobal(
648 const interpreter::BytecodeArrayIterator& iterator,
649 TypeofMode typeof_mode) {
650 FrameStateBeforeAndAfter states(this, iterator);
651 Handle<Name> name =
652 Handle<Name>::cast(iterator.GetConstantForIndexOperand(0));
653 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));
654
655 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
656 Node* node = NewNode(op, BuildLoadFeedbackVector());
657 environment()->BindAccumulator(node, &states);
658}
659
660
661void BytecodeGraphBuilder::VisitLdaGlobalSloppy(
662 const interpreter::BytecodeArrayIterator& iterator) {
663 DCHECK(is_sloppy(language_mode()));
664 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
665}
666
667
668void BytecodeGraphBuilder::VisitLdaGlobalStrict(
669 const interpreter::BytecodeArrayIterator& iterator) {
670 DCHECK(is_strict(language_mode()));
671 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
672}
673
674
675void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppy(
676 const interpreter::BytecodeArrayIterator& iterator) {
677 DCHECK(is_sloppy(language_mode()));
678 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
679}
680
681
682void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrict(
683 const interpreter::BytecodeArrayIterator& iterator) {
684 DCHECK(is_strict(language_mode()));
685 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
686}
687
688
689void BytecodeGraphBuilder::VisitLdaGlobalSloppyWide(
690 const interpreter::BytecodeArrayIterator& iterator) {
691 DCHECK(is_sloppy(language_mode()));
692 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
693}
694
695
696void BytecodeGraphBuilder::VisitLdaGlobalStrictWide(
697 const interpreter::BytecodeArrayIterator& iterator) {
698 DCHECK(is_strict(language_mode()));
699 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
700}
701
702
703void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppyWide(
704 const interpreter::BytecodeArrayIterator& iterator) {
705 DCHECK(is_sloppy(language_mode()));
706 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
707}
708
709
710void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrictWide(
711 const interpreter::BytecodeArrayIterator& iterator) {
712 DCHECK(is_strict(language_mode()));
713 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
714}
715
716
717void BytecodeGraphBuilder::BuildStoreGlobal(
718 const interpreter::BytecodeArrayIterator& iterator) {
719 FrameStateBeforeAndAfter states(this, iterator);
720 Handle<Name> name =
721 Handle<Name>::cast(iterator.GetConstantForIndexOperand(0));
722 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));
723 Node* value = environment()->LookupAccumulator();
724
725 const Operator* op =
726 javascript()->StoreGlobal(language_mode(), name, feedback);
727 Node* node = NewNode(op, value, BuildLoadFeedbackVector());
728 environment()->RecordAfterState(node, &states);
729}
730
731
732void BytecodeGraphBuilder::VisitStaGlobalSloppy(
733 const interpreter::BytecodeArrayIterator& iterator) {
734 DCHECK(is_sloppy(language_mode()));
735 BuildStoreGlobal(iterator);
736}
737
738
739void BytecodeGraphBuilder::VisitStaGlobalStrict(
740 const interpreter::BytecodeArrayIterator& iterator) {
741 DCHECK(is_strict(language_mode()));
742 BuildStoreGlobal(iterator);
743}
744
745void BytecodeGraphBuilder::VisitStaGlobalSloppyWide(
746 const interpreter::BytecodeArrayIterator& iterator) {
747 DCHECK(is_sloppy(language_mode()));
748 BuildStoreGlobal(iterator);
749}
750
751
752void BytecodeGraphBuilder::VisitStaGlobalStrictWide(
753 const interpreter::BytecodeArrayIterator& iterator) {
754 DCHECK(is_strict(language_mode()));
755 BuildStoreGlobal(iterator);
756}
757
758
759void BytecodeGraphBuilder::VisitLdaContextSlot(
760 const interpreter::BytecodeArrayIterator& iterator) {
761 // TODO(mythria): LoadContextSlots are unrolled by the required depth when
762 // generating bytecode. Hence the value of depth is always 0. Update this
763 // code, when the implementation changes.
764 // TODO(mythria): immutable flag is also set to false. This information is not
765 // available in bytecode array. update this code when the implementation
766 // changes.
767 const Operator* op =
768 javascript()->LoadContext(0, iterator.GetIndexOperand(1), false);
769 Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0));
770 Node* node = NewNode(op, context);
771 environment()->BindAccumulator(node);
772}
773
774
775void BytecodeGraphBuilder::VisitLdaContextSlotWide(
776 const interpreter::BytecodeArrayIterator& iterator) {
777 VisitLdaContextSlot(iterator);
778}
779
780
781void BytecodeGraphBuilder::VisitStaContextSlot(
782 const interpreter::BytecodeArrayIterator& iterator) {
783 // TODO(mythria): LoadContextSlots are unrolled by the required depth when
784 // generating bytecode. Hence the value of depth is always 0. Update this
785 // code, when the implementation changes.
786 const Operator* op =
787 javascript()->StoreContext(0, iterator.GetIndexOperand(1));
788 Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0));
789 Node* value = environment()->LookupAccumulator();
790 NewNode(op, context, value);
791}
792
793
794void BytecodeGraphBuilder::VisitStaContextSlotWide(
795 const interpreter::BytecodeArrayIterator& iterator) {
796 VisitStaContextSlot(iterator);
797}
798
799
800void BytecodeGraphBuilder::BuildLdaLookupSlot(
801 TypeofMode typeof_mode,
802 const interpreter::BytecodeArrayIterator& iterator) {
803 FrameStateBeforeAndAfter states(this, iterator);
804 Handle<String> name =
805 Handle<String>::cast(iterator.GetConstantForIndexOperand(0));
806 const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
807 Node* value =
808 NewNode(op, BuildLoadFeedbackVector(), environment()->Context());
809 environment()->BindAccumulator(value, &states);
810}
811
812
813void BytecodeGraphBuilder::VisitLdaLookupSlot(
814 const interpreter::BytecodeArrayIterator& iterator) {
815 BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF, iterator);
816}
817
818
819void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof(
820 const interpreter::BytecodeArrayIterator& iterator) {
821 BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF, iterator);
822}
823
824
825void BytecodeGraphBuilder::BuildStaLookupSlot(
826 LanguageMode language_mode,
827 const interpreter::BytecodeArrayIterator& iterator) {
828 FrameStateBeforeAndAfter states(this, iterator);
829 Node* value = environment()->LookupAccumulator();
830 Node* name = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0));
831 Node* language = jsgraph()->Constant(language_mode);
832 const Operator* op = javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4);
833 Node* store = NewNode(op, value, environment()->Context(), name, language);
834 environment()->BindAccumulator(store, &states);
835}
836
837
838void BytecodeGraphBuilder::VisitLdaLookupSlotWide(
839 const interpreter::BytecodeArrayIterator& iterator) {
840 VisitLdaLookupSlot(iterator);
841}
842
843
844void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeofWide(
845 const interpreter::BytecodeArrayIterator& iterator) {
846 VisitLdaLookupSlotInsideTypeof(iterator);
847}
848
849
850void BytecodeGraphBuilder::VisitStaLookupSlotSloppy(
851 const interpreter::BytecodeArrayIterator& iterator) {
852 BuildStaLookupSlot(LanguageMode::SLOPPY, iterator);
853}
854
855
856void BytecodeGraphBuilder::VisitStaLookupSlotStrict(
857 const interpreter::BytecodeArrayIterator& iterator) {
858 BuildStaLookupSlot(LanguageMode::STRICT, iterator);
859}
860
861
862void BytecodeGraphBuilder::VisitStaLookupSlotSloppyWide(
863 const interpreter::BytecodeArrayIterator& iterator) {
864 VisitStaLookupSlotSloppy(iterator);
865}
866
867
868void BytecodeGraphBuilder::VisitStaLookupSlotStrictWide(
869 const interpreter::BytecodeArrayIterator& iterator) {
870 VisitStaLookupSlotStrict(iterator);
871}
872
873
874void BytecodeGraphBuilder::BuildNamedLoad(
875 const interpreter::BytecodeArrayIterator& iterator) {
876 FrameStateBeforeAndAfter states(this, iterator);
877 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
878 Handle<Name> name =
879 Handle<Name>::cast(iterator.GetConstantForIndexOperand(1));
880 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2));
881
882 const Operator* op = javascript()->LoadNamed(language_mode(), name, feedback);
883 Node* node = NewNode(op, object, BuildLoadFeedbackVector());
884 environment()->BindAccumulator(node, &states);
885}
886
887
888void BytecodeGraphBuilder::VisitLoadICSloppy(
889 const interpreter::BytecodeArrayIterator& iterator) {
890 DCHECK(is_sloppy(language_mode()));
891 BuildNamedLoad(iterator);
892}
893
894
895void BytecodeGraphBuilder::VisitLoadICStrict(
896 const interpreter::BytecodeArrayIterator& iterator) {
897 DCHECK(is_strict(language_mode()));
898 BuildNamedLoad(iterator);
899}
900
901
902void BytecodeGraphBuilder::VisitLoadICSloppyWide(
903 const interpreter::BytecodeArrayIterator& iterator) {
904 DCHECK(is_sloppy(language_mode()));
905 BuildNamedLoad(iterator);
906}
907
908
909void BytecodeGraphBuilder::VisitLoadICStrictWide(
910 const interpreter::BytecodeArrayIterator& iterator) {
911 DCHECK(is_strict(language_mode()));
912 BuildNamedLoad(iterator);
913}
914
915
916void BytecodeGraphBuilder::BuildKeyedLoad(
917 const interpreter::BytecodeArrayIterator& iterator) {
918 FrameStateBeforeAndAfter states(this, iterator);
919 Node* key = environment()->LookupAccumulator();
920 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
921 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));
922
923 const Operator* op = javascript()->LoadProperty(language_mode(), feedback);
924 Node* node = NewNode(op, object, key, BuildLoadFeedbackVector());
925 environment()->BindAccumulator(node, &states);
926}
927
928
929void BytecodeGraphBuilder::VisitKeyedLoadICSloppy(
930 const interpreter::BytecodeArrayIterator& iterator) {
931 DCHECK(is_sloppy(language_mode()));
932 BuildKeyedLoad(iterator);
933}
934
935
936void BytecodeGraphBuilder::VisitKeyedLoadICStrict(
937 const interpreter::BytecodeArrayIterator& iterator) {
938 DCHECK(is_strict(language_mode()));
939 BuildKeyedLoad(iterator);
940}
941
942
943void BytecodeGraphBuilder::VisitKeyedLoadICSloppyWide(
944 const interpreter::BytecodeArrayIterator& iterator) {
945 DCHECK(is_sloppy(language_mode()));
946 BuildKeyedLoad(iterator);
947}
948
949
950void BytecodeGraphBuilder::VisitKeyedLoadICStrictWide(
951 const interpreter::BytecodeArrayIterator& iterator) {
952 DCHECK(is_strict(language_mode()));
953 BuildKeyedLoad(iterator);
954}
955
956
957void BytecodeGraphBuilder::BuildNamedStore(
958 const interpreter::BytecodeArrayIterator& iterator) {
959 FrameStateBeforeAndAfter states(this, iterator);
960 Node* value = environment()->LookupAccumulator();
961 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
962 Handle<Name> name =
963 Handle<Name>::cast(iterator.GetConstantForIndexOperand(1));
964 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2));
965
966 const Operator* op =
967 javascript()->StoreNamed(language_mode(), name, feedback);
968 Node* node = NewNode(op, object, value, BuildLoadFeedbackVector());
969 environment()->RecordAfterState(node, &states);
970}
971
972
973void BytecodeGraphBuilder::VisitStoreICSloppy(
974 const interpreter::BytecodeArrayIterator& iterator) {
975 DCHECK(is_sloppy(language_mode()));
976 BuildNamedStore(iterator);
977}
978
979
980void BytecodeGraphBuilder::VisitStoreICStrict(
981 const interpreter::BytecodeArrayIterator& iterator) {
982 DCHECK(is_strict(language_mode()));
983 BuildNamedStore(iterator);
984}
985
986
987void BytecodeGraphBuilder::VisitStoreICSloppyWide(
988 const interpreter::BytecodeArrayIterator& iterator) {
989 DCHECK(is_sloppy(language_mode()));
990 BuildNamedStore(iterator);
991}
992
993
994void BytecodeGraphBuilder::VisitStoreICStrictWide(
995 const interpreter::BytecodeArrayIterator& iterator) {
996 DCHECK(is_strict(language_mode()));
997 BuildNamedStore(iterator);
998}
999
1000
1001void BytecodeGraphBuilder::BuildKeyedStore(
1002 const interpreter::BytecodeArrayIterator& iterator) {
1003 FrameStateBeforeAndAfter states(this, iterator);
1004 Node* value = environment()->LookupAccumulator();
1005 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1006 Node* key = environment()->LookupRegister(iterator.GetRegisterOperand(1));
1007 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2));
1008
1009 const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
1010 Node* node = NewNode(op, object, key, value, BuildLoadFeedbackVector());
1011 environment()->RecordAfterState(node, &states);
1012}
1013
1014
1015void BytecodeGraphBuilder::VisitKeyedStoreICSloppy(
1016 const interpreter::BytecodeArrayIterator& iterator) {
1017 DCHECK(is_sloppy(language_mode()));
1018 BuildKeyedStore(iterator);
1019}
1020
1021
1022void BytecodeGraphBuilder::VisitKeyedStoreICStrict(
1023 const interpreter::BytecodeArrayIterator& iterator) {
1024 DCHECK(is_strict(language_mode()));
1025 BuildKeyedStore(iterator);
1026}
1027
1028
1029void BytecodeGraphBuilder::VisitKeyedStoreICSloppyWide(
1030 const interpreter::BytecodeArrayIterator& iterator) {
1031 DCHECK(is_sloppy(language_mode()));
1032 BuildKeyedStore(iterator);
1033}
1034
1035
1036void BytecodeGraphBuilder::VisitKeyedStoreICStrictWide(
1037 const interpreter::BytecodeArrayIterator& iterator) {
1038 DCHECK(is_strict(language_mode()));
1039 BuildKeyedStore(iterator);
1040}
1041
1042
1043void BytecodeGraphBuilder::VisitPushContext(
1044 const interpreter::BytecodeArrayIterator& iterator) {
1045 Node* context = environment()->LookupAccumulator();
1046 environment()->BindRegister(iterator.GetRegisterOperand(0), context);
1047 environment()->SetContext(context);
1048}
1049
1050
1051void BytecodeGraphBuilder::VisitPopContext(
1052 const interpreter::BytecodeArrayIterator& iterator) {
1053 Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1054 environment()->SetContext(context);
1055}
1056
1057
1058void BytecodeGraphBuilder::VisitCreateClosure(
1059 const interpreter::BytecodeArrayIterator& iterator) {
1060 Handle<SharedFunctionInfo> shared_info =
1061 Handle<SharedFunctionInfo>::cast(iterator.GetConstantForIndexOperand(0));
1062 PretenureFlag tenured =
1063 iterator.GetImmediateOperand(1) ? TENURED : NOT_TENURED;
1064 const Operator* op = javascript()->CreateClosure(shared_info, tenured);
1065 Node* closure = NewNode(op);
1066 environment()->BindAccumulator(closure);
1067}
1068
1069
1070void BytecodeGraphBuilder::VisitCreateClosureWide(
1071 const interpreter::BytecodeArrayIterator& iterator) {
1072 VisitCreateClosure(iterator);
1073}
1074
1075
1076void BytecodeGraphBuilder::BuildCreateArguments(
1077 CreateArgumentsParameters::Type type,
1078 const interpreter::BytecodeArrayIterator& iterator) {
1079 FrameStateBeforeAndAfter states(this, iterator);
1080 const Operator* op = javascript()->CreateArguments(type, 0);
1081 Node* object = NewNode(op, GetFunctionClosure());
1082 environment()->BindAccumulator(object, &states);
1083}
1084
1085
1086void BytecodeGraphBuilder::VisitCreateMappedArguments(
1087 const interpreter::BytecodeArrayIterator& iterator) {
1088 BuildCreateArguments(CreateArgumentsParameters::kMappedArguments, iterator);
1089}
1090
1091
1092void BytecodeGraphBuilder::VisitCreateUnmappedArguments(
1093 const interpreter::BytecodeArrayIterator& iterator) {
1094 BuildCreateArguments(CreateArgumentsParameters::kUnmappedArguments, iterator);
1095}
1096
1097
1098void BytecodeGraphBuilder::BuildCreateLiteral(
1099 const Operator* op, const interpreter::BytecodeArrayIterator& iterator) {
1100 FrameStateBeforeAndAfter states(this, iterator);
1101 Node* literal = NewNode(op, GetFunctionClosure());
1102 environment()->BindAccumulator(literal, &states);
1103}
1104
1105
1106void BytecodeGraphBuilder::BuildCreateRegExpLiteral(
1107 const interpreter::BytecodeArrayIterator& iterator) {
1108 Handle<String> constant_pattern =
1109 Handle<String>::cast(iterator.GetConstantForIndexOperand(0));
1110 int literal_index = iterator.GetIndexOperand(1);
1111 int literal_flags = iterator.GetImmediateOperand(2);
1112 const Operator* op = javascript()->CreateLiteralRegExp(
1113 constant_pattern, literal_flags, literal_index);
1114 BuildCreateLiteral(op, iterator);
1115}
1116
1117
1118void BytecodeGraphBuilder::VisitCreateRegExpLiteral(
1119 const interpreter::BytecodeArrayIterator& iterator) {
1120 BuildCreateRegExpLiteral(iterator);
1121}
1122
1123
1124void BytecodeGraphBuilder::VisitCreateRegExpLiteralWide(
1125 const interpreter::BytecodeArrayIterator& iterator) {
1126 BuildCreateRegExpLiteral(iterator);
1127}
1128
1129
1130void BytecodeGraphBuilder::BuildCreateArrayLiteral(
1131 const interpreter::BytecodeArrayIterator& iterator) {
1132 Handle<FixedArray> constant_elements =
1133 Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0));
1134 int literal_index = iterator.GetIndexOperand(1);
1135 int literal_flags = iterator.GetImmediateOperand(2);
1136 const Operator* op = javascript()->CreateLiteralArray(
1137 constant_elements, literal_flags, literal_index);
1138 BuildCreateLiteral(op, iterator);
1139}
1140
1141
1142void BytecodeGraphBuilder::VisitCreateArrayLiteral(
1143 const interpreter::BytecodeArrayIterator& iterator) {
1144 BuildCreateArrayLiteral(iterator);
1145}
1146
1147
1148void BytecodeGraphBuilder::VisitCreateArrayLiteralWide(
1149 const interpreter::BytecodeArrayIterator& iterator) {
1150 BuildCreateArrayLiteral(iterator);
1151}
1152
1153
1154void BytecodeGraphBuilder::BuildCreateObjectLiteral(
1155 const interpreter::BytecodeArrayIterator& iterator) {
1156 Handle<FixedArray> constant_properties =
1157 Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0));
1158 int literal_index = iterator.GetIndexOperand(1);
1159 int literal_flags = iterator.GetImmediateOperand(2);
1160 const Operator* op = javascript()->CreateLiteralObject(
1161 constant_properties, literal_flags, literal_index);
1162 BuildCreateLiteral(op, iterator);
1163}
1164
1165
1166void BytecodeGraphBuilder::VisitCreateObjectLiteral(
1167 const interpreter::BytecodeArrayIterator& iterator) {
1168 BuildCreateObjectLiteral(iterator);
1169}
1170
1171
1172void BytecodeGraphBuilder::VisitCreateObjectLiteralWide(
1173 const interpreter::BytecodeArrayIterator& iterator) {
1174 BuildCreateObjectLiteral(iterator);
1175}
1176
1177
1178Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
1179 Node* callee,
1180 interpreter::Register receiver,
1181 size_t arity) {
1182 Node** all = info()->zone()->NewArray<Node*>(static_cast<int>(arity));
1183 all[0] = callee;
1184 all[1] = environment()->LookupRegister(receiver);
1185 int receiver_index = receiver.index();
1186 for (int i = 2; i < static_cast<int>(arity); ++i) {
1187 all[i] = environment()->LookupRegister(
1188 interpreter::Register(receiver_index + i - 1));
1189 }
1190 Node* value = MakeNode(call_op, static_cast<int>(arity), all, false);
1191 return value;
1192}
1193
1194
1195void BytecodeGraphBuilder::BuildCall(
1196 const interpreter::BytecodeArrayIterator& iterator) {
1197 FrameStateBeforeAndAfter states(this, iterator);
1198 // TODO(rmcilroy): Set receiver_hint correctly based on whether the receiver
1199 // register has been loaded with null / undefined explicitly or we are sure it
1200 // is not null / undefined.
1201 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
1202 Node* callee = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1203 interpreter::Register receiver = iterator.GetRegisterOperand(1);
1204 size_t arg_count = iterator.GetCountOperand(2);
1205 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(3));
1206
1207 const Operator* call = javascript()->CallFunction(
1208 arg_count + 2, language_mode(), feedback, receiver_hint);
1209 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2);
1210 environment()->BindAccumulator(value, &states);
1211}
1212
1213
1214void BytecodeGraphBuilder::VisitCall(
1215 const interpreter::BytecodeArrayIterator& iterator) {
1216 BuildCall(iterator);
1217}
1218
1219
1220void BytecodeGraphBuilder::VisitCallWide(
1221 const interpreter::BytecodeArrayIterator& iterator) {
1222 BuildCall(iterator);
1223}
1224
1225
1226void BytecodeGraphBuilder::VisitCallJSRuntime(
1227 const interpreter::BytecodeArrayIterator& iterator) {
1228 FrameStateBeforeAndAfter states(this, iterator);
1229 Node* callee = BuildLoadNativeContextField(iterator.GetIndexOperand(0));
1230 interpreter::Register receiver = iterator.GetRegisterOperand(1);
1231 size_t arg_count = iterator.GetCountOperand(2);
1232
1233 // Create node to perform the JS runtime call.
1234 const Operator* call =
1235 javascript()->CallFunction(arg_count + 2, language_mode());
1236 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2);
1237 environment()->BindAccumulator(value, &states);
1238}
1239
1240
1241Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
1242 const Operator* call_runtime_op, interpreter::Register first_arg,
1243 size_t arity) {
1244 Node** all = info()->zone()->NewArray<Node*>(arity);
1245 int first_arg_index = first_arg.index();
1246 for (int i = 0; i < static_cast<int>(arity); ++i) {
1247 all[i] = environment()->LookupRegister(
1248 interpreter::Register(first_arg_index + i));
1249 }
1250 Node* value = MakeNode(call_runtime_op, static_cast<int>(arity), all, false);
1251 return value;
1252}
1253
1254
1255void BytecodeGraphBuilder::VisitCallRuntime(
1256 const interpreter::BytecodeArrayIterator& iterator) {
1257 FrameStateBeforeAndAfter states(this, iterator);
1258 Runtime::FunctionId functionId =
1259 static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0));
1260 interpreter::Register first_arg = iterator.GetRegisterOperand(1);
1261 size_t arg_count = iterator.GetCountOperand(2);
1262
1263 // Create node to perform the runtime call.
1264 const Operator* call = javascript()->CallRuntime(functionId, arg_count);
1265 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count);
1266 environment()->BindAccumulator(value, &states);
1267}
1268
1269
1270void BytecodeGraphBuilder::VisitCallRuntimeForPair(
1271 const interpreter::BytecodeArrayIterator& iterator) {
1272 FrameStateBeforeAndAfter states(this, iterator);
1273 Runtime::FunctionId functionId =
1274 static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0));
1275 interpreter::Register first_arg = iterator.GetRegisterOperand(1);
1276 size_t arg_count = iterator.GetCountOperand(2);
1277 interpreter::Register first_return = iterator.GetRegisterOperand(3);
1278
1279 // Create node to perform the runtime call.
1280 const Operator* call = javascript()->CallRuntime(functionId, arg_count);
1281 Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count);
1282 environment()->BindRegistersToProjections(first_return, return_pair, &states);
1283}
1284
1285
1286Node* BytecodeGraphBuilder::ProcessCallNewArguments(
1287 const Operator* call_new_op, interpreter::Register callee,
1288 interpreter::Register first_arg, size_t arity) {
1289 Node** all = info()->zone()->NewArray<Node*>(arity);
1290 all[0] = environment()->LookupRegister(callee);
1291 int first_arg_index = first_arg.index();
1292 for (int i = 1; i < static_cast<int>(arity) - 1; ++i) {
1293 all[i] = environment()->LookupRegister(
1294 interpreter::Register(first_arg_index + i - 1));
1295 }
1296 // Original constructor is the same as the callee.
1297 all[arity - 1] = environment()->LookupRegister(callee);
1298 Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false);
1299 return value;
1300}
1301
1302
1303void BytecodeGraphBuilder::VisitNew(
1304 const interpreter::BytecodeArrayIterator& iterator) {
1305 FrameStateBeforeAndAfter states(this, iterator);
1306 interpreter::Register callee = iterator.GetRegisterOperand(0);
1307 interpreter::Register first_arg = iterator.GetRegisterOperand(1);
1308 size_t arg_count = iterator.GetCountOperand(2);
1309
1310 // TODO(turbofan): Pass the feedback here.
1311 const Operator* call = javascript()->CallConstruct(
1312 static_cast<int>(arg_count) + 2, VectorSlotPair());
1313 Node* value = ProcessCallNewArguments(call, callee, first_arg, arg_count + 2);
1314 environment()->BindAccumulator(value, &states);
1315}
1316
1317
1318void BytecodeGraphBuilder::VisitThrow(
1319 const interpreter::BytecodeArrayIterator& iterator) {
1320 FrameStateBeforeAndAfter states(this, iterator);
1321 Node* value = environment()->LookupAccumulator();
1322 // TODO(mythria): Change to Runtime::kThrow when we have deoptimization
1323 // information support in the interpreter.
1324 NewNode(javascript()->CallRuntime(Runtime::kReThrow, 1), value);
1325 Node* control = NewNode(common()->Throw(), value);
1326 environment()->RecordAfterState(control, &states);
1327 UpdateControlDependencyToLeaveFunction(control);
1328}
1329
1330
1331void BytecodeGraphBuilder::BuildBinaryOp(
1332 const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
1333 FrameStateBeforeAndAfter states(this, iterator);
1334 Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1335 Node* right = environment()->LookupAccumulator();
1336 Node* node = NewNode(js_op, left, right);
1337 environment()->BindAccumulator(node, &states);
1338}
1339
1340
1341void BytecodeGraphBuilder::VisitAdd(
1342 const interpreter::BytecodeArrayIterator& iterator) {
1343 BinaryOperationHints hints = BinaryOperationHints::Any();
1344 BuildBinaryOp(javascript()->Add(language_mode(), hints), iterator);
1345}
1346
1347
1348void BytecodeGraphBuilder::VisitSub(
1349 const interpreter::BytecodeArrayIterator& iterator) {
1350 BinaryOperationHints hints = BinaryOperationHints::Any();
1351 BuildBinaryOp(javascript()->Subtract(language_mode(), hints), iterator);
1352}
1353
1354
1355void BytecodeGraphBuilder::VisitMul(
1356 const interpreter::BytecodeArrayIterator& iterator) {
1357 BinaryOperationHints hints = BinaryOperationHints::Any();
1358 BuildBinaryOp(javascript()->Multiply(language_mode(), hints), iterator);
1359}
1360
1361
1362void BytecodeGraphBuilder::VisitDiv(
1363 const interpreter::BytecodeArrayIterator& iterator) {
1364 BinaryOperationHints hints = BinaryOperationHints::Any();
1365 BuildBinaryOp(javascript()->Divide(language_mode(), hints), iterator);
1366}
1367
1368
1369void BytecodeGraphBuilder::VisitMod(
1370 const interpreter::BytecodeArrayIterator& iterator) {
1371 BinaryOperationHints hints = BinaryOperationHints::Any();
1372 BuildBinaryOp(javascript()->Modulus(language_mode(), hints), iterator);
1373}
1374
1375
1376void BytecodeGraphBuilder::VisitBitwiseOr(
1377 const interpreter::BytecodeArrayIterator& iterator) {
1378 BinaryOperationHints hints = BinaryOperationHints::Any();
1379 BuildBinaryOp(javascript()->BitwiseOr(language_mode(), hints), iterator);
1380}
1381
1382
1383void BytecodeGraphBuilder::VisitBitwiseXor(
1384 const interpreter::BytecodeArrayIterator& iterator) {
1385 BinaryOperationHints hints = BinaryOperationHints::Any();
1386 BuildBinaryOp(javascript()->BitwiseXor(language_mode(), hints), iterator);
1387}
1388
1389
1390void BytecodeGraphBuilder::VisitBitwiseAnd(
1391 const interpreter::BytecodeArrayIterator& iterator) {
1392 BinaryOperationHints hints = BinaryOperationHints::Any();
1393 BuildBinaryOp(javascript()->BitwiseAnd(language_mode(), hints), iterator);
1394}
1395
1396
1397void BytecodeGraphBuilder::VisitShiftLeft(
1398 const interpreter::BytecodeArrayIterator& iterator) {
1399 BinaryOperationHints hints = BinaryOperationHints::Any();
1400 BuildBinaryOp(javascript()->ShiftLeft(language_mode(), hints), iterator);
1401}
1402
1403
1404void BytecodeGraphBuilder::VisitShiftRight(
1405 const interpreter::BytecodeArrayIterator& iterator) {
1406 BinaryOperationHints hints = BinaryOperationHints::Any();
1407 BuildBinaryOp(javascript()->ShiftRight(language_mode(), hints), iterator);
1408}
1409
1410
1411void BytecodeGraphBuilder::VisitShiftRightLogical(
1412 const interpreter::BytecodeArrayIterator& iterator) {
1413 BinaryOperationHints hints = BinaryOperationHints::Any();
1414 BuildBinaryOp(javascript()->ShiftRightLogical(language_mode(), hints),
1415 iterator);
1416}
1417
1418
1419void BytecodeGraphBuilder::VisitInc(
1420 const interpreter::BytecodeArrayIterator& iterator) {
1421 FrameStateBeforeAndAfter states(this, iterator);
1422 const Operator* js_op =
1423 javascript()->Add(language_mode(), BinaryOperationHints::Any());
1424 Node* node = NewNode(js_op, environment()->LookupAccumulator(),
1425 jsgraph()->OneConstant());
1426 environment()->BindAccumulator(node, &states);
1427}
1428
1429
1430void BytecodeGraphBuilder::VisitDec(
1431 const interpreter::BytecodeArrayIterator& iterator) {
1432 FrameStateBeforeAndAfter states(this, iterator);
1433 const Operator* js_op =
1434 javascript()->Subtract(language_mode(), BinaryOperationHints::Any());
1435 Node* node = NewNode(js_op, environment()->LookupAccumulator(),
1436 jsgraph()->OneConstant());
1437 environment()->BindAccumulator(node, &states);
1438}
1439
1440
1441void BytecodeGraphBuilder::VisitLogicalNot(
1442 const interpreter::BytecodeArrayIterator& iterator) {
1443 Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
1444 environment()->LookupAccumulator());
1445 Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value,
1446 jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
1447 environment()->BindAccumulator(node);
1448}
1449
1450
1451void BytecodeGraphBuilder::VisitTypeOf(
1452 const interpreter::BytecodeArrayIterator& iterator) {
1453 Node* node =
1454 NewNode(javascript()->TypeOf(), environment()->LookupAccumulator());
1455 environment()->BindAccumulator(node);
1456}
1457
1458
1459void BytecodeGraphBuilder::BuildDelete(
1460 const interpreter::BytecodeArrayIterator& iterator) {
1461 FrameStateBeforeAndAfter states(this, iterator);
1462 Node* key = environment()->LookupAccumulator();
1463 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1464 Node* node =
1465 NewNode(javascript()->DeleteProperty(language_mode()), object, key);
1466 environment()->BindAccumulator(node, &states);
1467}
1468
1469
1470void BytecodeGraphBuilder::VisitDeletePropertyStrict(
1471 const interpreter::BytecodeArrayIterator& iterator) {
1472 DCHECK(is_strict(language_mode()));
1473 BuildDelete(iterator);
1474}
1475
1476
1477void BytecodeGraphBuilder::VisitDeletePropertySloppy(
1478 const interpreter::BytecodeArrayIterator& iterator) {
1479 DCHECK(is_sloppy(language_mode()));
1480 BuildDelete(iterator);
1481}
1482
1483
1484void BytecodeGraphBuilder::VisitDeleteLookupSlot(
1485 const interpreter::BytecodeArrayIterator& iterator) {
1486 FrameStateBeforeAndAfter states(this, iterator);
1487 Node* name = environment()->LookupAccumulator();
1488 const Operator* op = javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2);
1489 Node* result = NewNode(op, environment()->Context(), name);
1490 environment()->BindAccumulator(result, &states);
1491}
1492
1493
1494void BytecodeGraphBuilder::BuildCompareOp(
1495 const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
1496 FrameStateBeforeAndAfter states(this, iterator);
1497 Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1498 Node* right = environment()->LookupAccumulator();
1499 Node* node = NewNode(js_op, left, right);
1500 environment()->BindAccumulator(node, &states);
1501}
1502
1503
1504void BytecodeGraphBuilder::VisitTestEqual(
1505 const interpreter::BytecodeArrayIterator& iterator) {
1506 BuildCompareOp(javascript()->Equal(), iterator);
1507}
1508
1509
1510void BytecodeGraphBuilder::VisitTestNotEqual(
1511 const interpreter::BytecodeArrayIterator& iterator) {
1512 BuildCompareOp(javascript()->NotEqual(), iterator);
1513}
1514
1515
1516void BytecodeGraphBuilder::VisitTestEqualStrict(
1517 const interpreter::BytecodeArrayIterator& iterator) {
1518 BuildCompareOp(javascript()->StrictEqual(), iterator);
1519}
1520
1521
1522void BytecodeGraphBuilder::VisitTestNotEqualStrict(
1523 const interpreter::BytecodeArrayIterator& iterator) {
1524 BuildCompareOp(javascript()->StrictNotEqual(), iterator);
1525}
1526
1527
1528void BytecodeGraphBuilder::VisitTestLessThan(
1529 const interpreter::BytecodeArrayIterator& iterator) {
1530 BuildCompareOp(javascript()->LessThan(language_mode()), iterator);
1531}
1532
1533
1534void BytecodeGraphBuilder::VisitTestGreaterThan(
1535 const interpreter::BytecodeArrayIterator& iterator) {
1536 BuildCompareOp(javascript()->GreaterThan(language_mode()), iterator);
1537}
1538
1539
1540void BytecodeGraphBuilder::VisitTestLessThanOrEqual(
1541 const interpreter::BytecodeArrayIterator& iterator) {
1542 BuildCompareOp(javascript()->LessThanOrEqual(language_mode()), iterator);
1543}
1544
1545
1546void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual(
1547 const interpreter::BytecodeArrayIterator& iterator) {
1548 BuildCompareOp(javascript()->GreaterThanOrEqual(language_mode()), iterator);
1549}
1550
1551
1552void BytecodeGraphBuilder::VisitTestIn(
1553 const interpreter::BytecodeArrayIterator& iterator) {
1554 BuildCompareOp(javascript()->HasProperty(), iterator);
1555}
1556
1557
1558void BytecodeGraphBuilder::VisitTestInstanceOf(
1559 const interpreter::BytecodeArrayIterator& iterator) {
1560 BuildCompareOp(javascript()->InstanceOf(), iterator);
1561}
1562
1563
1564void BytecodeGraphBuilder::BuildCastOperator(
1565 const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
1566 FrameStateBeforeAndAfter states(this, iterator);
1567 Node* node = NewNode(js_op, environment()->LookupAccumulator());
1568 environment()->BindAccumulator(node, &states);
1569}
1570
1571
1572void BytecodeGraphBuilder::VisitToName(
1573 const interpreter::BytecodeArrayIterator& iterator) {
1574 BuildCastOperator(javascript()->ToName(), iterator);
1575}
1576
1577
1578void BytecodeGraphBuilder::VisitToObject(
1579 const interpreter::BytecodeArrayIterator& iterator) {
1580 BuildCastOperator(javascript()->ToObject(), iterator);
1581}
1582
1583
1584void BytecodeGraphBuilder::VisitToNumber(
1585 const interpreter::BytecodeArrayIterator& iterator) {
1586 BuildCastOperator(javascript()->ToNumber(), iterator);
1587}
1588
1589
1590void BytecodeGraphBuilder::VisitJump(
1591 const interpreter::BytecodeArrayIterator& iterator) {
1592 BuildJump();
1593}
1594
1595
1596void BytecodeGraphBuilder::VisitJumpConstant(
1597 const interpreter::BytecodeArrayIterator& iterator) {
1598 BuildJump();
1599}
1600
1601
1602void BytecodeGraphBuilder::VisitJumpConstantWide(
1603 const interpreter::BytecodeArrayIterator& iterator) {
1604 BuildJump();
1605}
1606
1607
1608void BytecodeGraphBuilder::VisitJumpIfTrue(
1609 const interpreter::BytecodeArrayIterator& iterator) {
1610 BuildJumpIfEqual(jsgraph()->TrueConstant());
1611}
1612
1613
1614void BytecodeGraphBuilder::VisitJumpIfTrueConstant(
1615 const interpreter::BytecodeArrayIterator& iterator) {
1616 BuildJumpIfEqual(jsgraph()->TrueConstant());
1617}
1618
1619
1620void BytecodeGraphBuilder::VisitJumpIfTrueConstantWide(
1621 const interpreter::BytecodeArrayIterator& iterator) {
1622 BuildJumpIfEqual(jsgraph()->TrueConstant());
1623}
1624
1625
1626void BytecodeGraphBuilder::VisitJumpIfFalse(
1627 const interpreter::BytecodeArrayIterator& iterator) {
1628 BuildJumpIfEqual(jsgraph()->FalseConstant());
1629}
1630
1631
1632void BytecodeGraphBuilder::VisitJumpIfFalseConstant(
1633 const interpreter::BytecodeArrayIterator& iterator) {
1634 BuildJumpIfEqual(jsgraph()->FalseConstant());
1635}
1636
1637
1638void BytecodeGraphBuilder::VisitJumpIfFalseConstantWide(
1639 const interpreter::BytecodeArrayIterator& iterator) {
1640 BuildJumpIfEqual(jsgraph()->FalseConstant());
1641}
1642
1643
1644void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue(
1645 const interpreter::BytecodeArrayIterator& iterator) {
1646 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant());
1647}
1648
1649
1650void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant(
1651 const interpreter::BytecodeArrayIterator& iterator) {
1652 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant());
1653}
1654
1655
1656void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstantWide(
1657 const interpreter::BytecodeArrayIterator& iterator) {
1658 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant());
1659}
1660
1661
1662void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse(
1663 const interpreter::BytecodeArrayIterator& iterator) {
1664 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant());
1665}
1666
1667
1668void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant(
1669 const interpreter::BytecodeArrayIterator& iterator) {
1670 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant());
1671}
1672
1673
1674void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstantWide(
1675 const interpreter::BytecodeArrayIterator& iterator) {
1676 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant());
1677}
1678
1679
1680void BytecodeGraphBuilder::VisitJumpIfNull(
1681 const interpreter::BytecodeArrayIterator& iterator) {
1682 BuildJumpIfEqual(jsgraph()->NullConstant());
1683}
1684
1685
1686void BytecodeGraphBuilder::VisitJumpIfNullConstant(
1687 const interpreter::BytecodeArrayIterator& iterator) {
1688 BuildJumpIfEqual(jsgraph()->NullConstant());
1689}
1690
1691
1692void BytecodeGraphBuilder::VisitJumpIfNullConstantWide(
1693 const interpreter::BytecodeArrayIterator& iterator) {
1694 BuildJumpIfEqual(jsgraph()->NullConstant());
1695}
1696
1697
1698void BytecodeGraphBuilder::VisitJumpIfUndefined(
1699 const interpreter::BytecodeArrayIterator& iterator) {
1700 BuildJumpIfEqual(jsgraph()->UndefinedConstant());
1701}
1702
1703
1704void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant(
1705 const interpreter::BytecodeArrayIterator& iterator) {
1706 BuildJumpIfEqual(jsgraph()->UndefinedConstant());
1707}
1708
1709
1710void BytecodeGraphBuilder::VisitJumpIfUndefinedConstantWide(
1711 const interpreter::BytecodeArrayIterator& iterator) {
1712 BuildJumpIfEqual(jsgraph()->UndefinedConstant());
1713}
1714
1715
1716void BytecodeGraphBuilder::VisitReturn(
1717 const interpreter::BytecodeArrayIterator& iterator) {
1718 Node* control =
1719 NewNode(common()->Return(), environment()->LookupAccumulator());
1720 UpdateControlDependencyToLeaveFunction(control);
1721 set_environment(nullptr);
1722}
1723
1724
1725void BytecodeGraphBuilder::VisitForInPrepare(
1726 const interpreter::BytecodeArrayIterator& iterator) {
1727 Node* prepare = nullptr;
1728 {
1729 FrameStateBeforeAndAfter states(this, iterator);
1730 Node* receiver = environment()->LookupAccumulator();
1731 prepare = NewNode(javascript()->ForInPrepare(), receiver);
1732 environment()->RecordAfterState(prepare, &states);
1733 }
1734 // Project cache_type, cache_array, cache_length into register
1735 // operands 1, 2, 3.
1736 for (int i = 0; i < 3; i++) {
1737 environment()->BindRegister(iterator.GetRegisterOperand(i),
1738 NewNode(common()->Projection(i), prepare));
1739 }
1740}
1741
1742
1743void BytecodeGraphBuilder::VisitForInDone(
1744 const interpreter::BytecodeArrayIterator& iterator) {
1745 FrameStateBeforeAndAfter states(this, iterator);
1746 Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1747 Node* cache_length =
1748 environment()->LookupRegister(iterator.GetRegisterOperand(1));
1749 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1750 environment()->BindAccumulator(exit_cond, &states);
1751}
1752
1753
1754void BytecodeGraphBuilder::VisitForInNext(
1755 const interpreter::BytecodeArrayIterator& iterator) {
1756 FrameStateBeforeAndAfter states(this, iterator);
1757 Node* receiver =
1758 environment()->LookupRegister(iterator.GetRegisterOperand(0));
1759 Node* cache_type =
1760 environment()->LookupRegister(iterator.GetRegisterOperand(1));
1761 Node* cache_array =
1762 environment()->LookupRegister(iterator.GetRegisterOperand(2));
1763 Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(3));
1764 Node* value = NewNode(javascript()->ForInNext(), receiver, cache_array,
1765 cache_type, index);
1766 environment()->BindAccumulator(value, &states);
1767}
1768
1769
1770void BytecodeGraphBuilder::VisitForInStep(
1771 const interpreter::BytecodeArrayIterator& iterator) {
1772 FrameStateBeforeAndAfter states(this, iterator);
1773 Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1774 index = NewNode(javascript()->ForInStep(), index);
1775 environment()->BindAccumulator(index, &states);
1776}
1777
1778
1779void BytecodeGraphBuilder::MergeEnvironmentsOfBackwardBranches(
1780 int source_offset, int target_offset) {
1781 DCHECK_GE(source_offset, target_offset);
1782 const ZoneVector<int>* branch_sites =
1783 branch_analysis()->BackwardBranchesTargetting(target_offset);
1784 if (branch_sites->back() == source_offset) {
1785 // The set of back branches is complete, merge them.
1786 DCHECK_GE(branch_sites->at(0), target_offset);
1787 Environment* merged = merge_environments_[branch_sites->at(0)];
1788 for (size_t i = 1; i < branch_sites->size(); i++) {
1789 DCHECK_GE(branch_sites->at(i), target_offset);
1790 merged->Merge(merge_environments_[branch_sites->at(i)]);
1791 }
1792 // And now merge with loop header environment created when loop
1793 // header was visited.
1794 loop_header_environments_[target_offset]->Merge(merged);
1795 }
1796}
1797
1798
1799void BytecodeGraphBuilder::MergeEnvironmentsOfForwardBranches(
1800 int source_offset) {
1801 if (branch_analysis()->forward_branches_target(source_offset)) {
1802 // Merge environments of branches that reach this bytecode.
1803 auto branch_sites =
1804 branch_analysis()->ForwardBranchesTargetting(source_offset);
1805 DCHECK_LT(branch_sites->at(0), source_offset);
1806 Environment* merged = merge_environments_[branch_sites->at(0)];
1807 for (size_t i = 1; i < branch_sites->size(); i++) {
1808 DCHECK_LT(branch_sites->at(i), source_offset);
1809 merged->Merge(merge_environments_[branch_sites->at(i)]);
1810 }
1811 if (environment()) {
1812 merged->Merge(environment());
1813 }
1814 set_environment(merged);
1815 }
1816}
1817
1818
1819void BytecodeGraphBuilder::BuildLoopHeaderForBackwardBranches(
1820 int source_offset) {
1821 if (branch_analysis()->backward_branches_target(source_offset)) {
1822 // Add loop header and store a copy so we can connect merged back
1823 // edge inputs to the loop header.
1824 loop_header_environments_[source_offset] = environment()->CopyForLoop();
1825 }
1826}
1827
1828
1829void BytecodeGraphBuilder::BuildJump(int source_offset, int target_offset) {
1830 DCHECK_NULL(merge_environments_[source_offset]);
1831 merge_environments_[source_offset] = environment();
1832 if (source_offset >= target_offset) {
1833 MergeEnvironmentsOfBackwardBranches(source_offset, target_offset);
1834 }
1835 set_environment(nullptr);
1836}
1837
1838
1839void BytecodeGraphBuilder::BuildJump() {
1840 int source_offset = bytecode_iterator()->current_offset();
1841 int target_offset = bytecode_iterator()->GetJumpTargetOffset();
1842 BuildJump(source_offset, target_offset);
1843}
1844
1845
1846void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) {
1847 int source_offset = bytecode_iterator()->current_offset();
1848 NewBranch(condition);
1849 Environment* if_false_environment = environment()->CopyForConditional();
1850 NewIfTrue();
1851 BuildJump(source_offset, bytecode_iterator()->GetJumpTargetOffset());
1852 set_environment(if_false_environment);
1853 NewIfFalse();
1854}
1855
1856
1857void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
1858 Node* accumulator = environment()->LookupAccumulator();
1859 Node* condition =
1860 NewNode(javascript()->StrictEqual(), accumulator, comperand);
1861 BuildConditionalJump(condition);
1862}
1863
1864
1865void BytecodeGraphBuilder::BuildJumpIfToBooleanEqual(Node* comperand) {
1866 Node* accumulator = environment()->LookupAccumulator();
1867 Node* to_boolean =
1868 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator);
1869 Node* condition = NewNode(javascript()->StrictEqual(), to_boolean, comperand);
1870 BuildConditionalJump(condition);
1871}
1872
1873
1874Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
1875 if (size > input_buffer_size_) {
1876 size = size + kInputBufferSizeIncrement + input_buffer_size_;
1877 input_buffer_ = local_zone()->NewArray<Node*>(size);
1878 input_buffer_size_ = size;
1879 }
1880 return input_buffer_;
1881}
1882
1883
1884void BytecodeGraphBuilder::PrepareEntryFrameState(Node* node) {
1885 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
1886 DCHECK_EQ(IrOpcode::kDead,
1887 NodeProperties::GetFrameStateInput(node, 0)->opcode());
1888 NodeProperties::ReplaceFrameStateInput(
1889 node, 0, environment()->Checkpoint(BailoutId(0),
1890 OutputFrameStateCombine::Ignore()));
1891}
1892
1893
1894Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
1895 Node** value_inputs, bool incomplete) {
1896 DCHECK_EQ(op->ValueInputCount(), value_input_count);
1897
1898 bool has_context = OperatorProperties::HasContextInput(op);
1899 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
1900 bool has_control = op->ControlInputCount() == 1;
1901 bool has_effect = op->EffectInputCount() == 1;
1902
1903 DCHECK_LT(op->ControlInputCount(), 2);
1904 DCHECK_LT(op->EffectInputCount(), 2);
1905
1906 Node* result = nullptr;
1907 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
1908 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
1909 } else {
1910 int input_count_with_deps = value_input_count;
1911 if (has_context) ++input_count_with_deps;
1912 input_count_with_deps += frame_state_count;
1913 if (has_control) ++input_count_with_deps;
1914 if (has_effect) ++input_count_with_deps;
1915 Node** buffer = EnsureInputBufferSize(input_count_with_deps);
1916 memcpy(buffer, value_inputs, kPointerSize * value_input_count);
1917 Node** current_input = buffer + value_input_count;
1918 if (has_context) {
1919 *current_input++ = environment()->Context();
1920 }
1921 for (int i = 0; i < frame_state_count; i++) {
1922 // The frame state will be inserted later. Here we misuse
1923 // the {Dead} node as a sentinel to be later overwritten
1924 // with the real frame state.
1925 *current_input++ = jsgraph()->Dead();
1926 }
1927 if (has_effect) {
1928 *current_input++ = environment()->GetEffectDependency();
1929 }
1930 if (has_control) {
1931 *current_input++ = environment()->GetControlDependency();
1932 }
1933 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
1934 if (!environment()->IsMarkedAsUnreachable()) {
1935 // Update the current control dependency for control-producing nodes.
1936 if (NodeProperties::IsControl(result)) {
1937 environment()->UpdateControlDependency(result);
1938 }
1939 // Update the current effect dependency for effect-producing nodes.
1940 if (result->op()->EffectOutputCount() > 0) {
1941 environment()->UpdateEffectDependency(result);
1942 }
1943 // Add implicit success continuation for throwing nodes.
1944 if (!result->op()->HasProperty(Operator::kNoThrow)) {
1945 const Operator* if_success = common()->IfSuccess();
1946 Node* on_success = graph()->NewNode(if_success, result);
1947 environment_->UpdateControlDependency(on_success);
1948 }
1949 }
1950 }
1951
1952 return result;
1953}
1954
1955
1956Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) {
1957 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
1958 Node** buffer = EnsureInputBufferSize(count + 1);
1959 MemsetPointer(buffer, input, count);
1960 buffer[count] = control;
1961 return graph()->NewNode(phi_op, count + 1, buffer, true);
1962}
1963
1964
1965Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input,
1966 Node* control) {
1967 const Operator* phi_op = common()->EffectPhi(count);
1968 Node** buffer = EnsureInputBufferSize(count + 1);
1969 MemsetPointer(buffer, input, count);
1970 buffer[count] = control;
1971 return graph()->NewNode(phi_op, count + 1, buffer, true);
1972}
1973
1974
1975Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
1976 int inputs = control->op()->ControlInputCount() + 1;
1977 if (control->opcode() == IrOpcode::kLoop) {
1978 // Control node for loop exists, add input.
1979 const Operator* op = common()->Loop(inputs);
1980 control->AppendInput(graph_zone(), other);
1981 NodeProperties::ChangeOp(control, op);
1982 } else if (control->opcode() == IrOpcode::kMerge) {
1983 // Control node for merge exists, add input.
1984 const Operator* op = common()->Merge(inputs);
1985 control->AppendInput(graph_zone(), other);
1986 NodeProperties::ChangeOp(control, op);
1987 } else {
1988 // Control node is a singleton, introduce a merge.
1989 const Operator* op = common()->Merge(inputs);
1990 Node* merge_inputs[] = {control, other};
1991 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true);
1992 }
1993 return control;
1994}
1995
1996
1997Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
1998 Node* control) {
1999 int inputs = control->op()->ControlInputCount();
2000 if (value->opcode() == IrOpcode::kEffectPhi &&
2001 NodeProperties::GetControlInput(value) == control) {
2002 // Phi already exists, add input.
2003 value->InsertInput(graph_zone(), inputs - 1, other);
2004 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
2005 } else if (value != other) {
2006 // Phi does not exist yet, introduce one.
2007 value = NewEffectPhi(inputs, value, control);
2008 value->ReplaceInput(inputs - 1, other);
2009 }
2010 return value;
2011}
2012
2013
2014Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
2015 Node* control) {
2016 int inputs = control->op()->ControlInputCount();
2017 if (value->opcode() == IrOpcode::kPhi &&
2018 NodeProperties::GetControlInput(value) == control) {
2019 // Phi already exists, add input.
2020 value->InsertInput(graph_zone(), inputs - 1, other);
2021 NodeProperties::ChangeOp(
2022 value, common()->Phi(MachineRepresentation::kTagged, inputs));
2023 } else if (value != other) {
2024 // Phi does not exist yet, introduce one.
2025 value = NewPhi(inputs, value, control);
2026 value->ReplaceInput(inputs - 1, other);
2027 }
2028 return value;
2029}
2030
2031
2032void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
2033 if (environment()->IsMarkedAsUnreachable()) return;
2034 environment()->MarkAsUnreachable();
2035 exit_controls_.push_back(exit);
2036}
2037
2038} // namespace compiler
2039} // namespace internal
2040} // namespace v8