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/compiler/bytecode-graph-builder.h"
6 
7 #include "src/ast/ast.h"
8 #include "src/ast/scopes.h"
9 #include "src/compilation-info.h"
10 #include "src/compiler/bytecode-branch-analysis.h"
11 #include "src/compiler/compiler-source-position-table.h"
12 #include "src/compiler/linkage.h"
13 #include "src/compiler/operator-properties.h"
14 #include "src/interpreter/bytecodes.h"
15 #include "src/objects-inl.h"
16 
17 namespace v8 {
18 namespace internal {
19 namespace compiler {
20 
21 // The abstract execution environment simulates the content of the interpreter
22 // register file. The environment performs SSA-renaming of all tracked nodes at
23 // split and merge points in the control flow.
24 class BytecodeGraphBuilder::Environment : public ZoneObject {
25  public:
26   Environment(BytecodeGraphBuilder* builder, int register_count,
27               int parameter_count, Node* control_dependency, Node* context);
28 
29   // Specifies whether environment binding methods should attach frame state
30   // inputs to nodes representing the value being bound. This is done because
31   // the {OutputFrameStateCombine} is closely related to the binding method.
32   enum FrameStateAttachmentMode { kAttachFrameState, kDontAttachFrameState };
33 
parameter_count() const34   int parameter_count() const { return parameter_count_; }
register_count() const35   int register_count() const { return register_count_; }
36 
37   Node* LookupAccumulator() const;
38   Node* LookupRegister(interpreter::Register the_register) const;
39   void MarkAllRegistersLive();
40 
41   void BindAccumulator(Node* node,
42                        FrameStateAttachmentMode mode = kDontAttachFrameState);
43   void BindRegister(interpreter::Register the_register, Node* node,
44                     FrameStateAttachmentMode mode = kDontAttachFrameState);
45   void BindRegistersToProjections(
46       interpreter::Register first_reg, Node* node,
47       FrameStateAttachmentMode mode = kDontAttachFrameState);
48   void RecordAfterState(Node* node,
49                         FrameStateAttachmentMode mode = kDontAttachFrameState);
50 
51   // Effect dependency tracked by this environment.
GetEffectDependency()52   Node* GetEffectDependency() { return effect_dependency_; }
UpdateEffectDependency(Node * dependency)53   void UpdateEffectDependency(Node* dependency) {
54     effect_dependency_ = dependency;
55   }
56 
57   // Preserve a checkpoint of the environment for the IR graph. Any
58   // further mutation of the environment will not affect checkpoints.
59   Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine,
60                    bool owner_has_exception);
61 
62   // Control dependency tracked by this environment.
GetControlDependency() const63   Node* GetControlDependency() const { return control_dependency_; }
UpdateControlDependency(Node * dependency)64   void UpdateControlDependency(Node* dependency) {
65     control_dependency_ = dependency;
66   }
67 
Context() const68   Node* Context() const { return context_; }
SetContext(Node * new_context)69   void SetContext(Node* new_context) { context_ = new_context; }
70 
71   Environment* CopyForConditional();
72   Environment* CopyForLoop();
73   Environment* CopyForOsrEntry();
74   void Merge(Environment* other);
75   void PrepareForOsrEntry();
76 
77   void PrepareForLoopExit(Node* loop);
78 
79  private:
80   Environment(const Environment* copy, LivenessAnalyzerBlock* liveness_block);
81   void PrepareForLoop();
82 
83   bool StateValuesRequireUpdate(Node** state_values, int offset, int count);
84   void UpdateStateValues(Node** state_values, int offset, int count);
85 
86   int RegisterToValuesIndex(interpreter::Register the_register) const;
87 
88   bool IsLivenessBlockConsistent() const;
89 
zone() const90   Zone* zone() const { return builder_->local_zone(); }
graph() const91   Graph* graph() const { return builder_->graph(); }
common() const92   CommonOperatorBuilder* common() const { return builder_->common(); }
builder() const93   BytecodeGraphBuilder* builder() const { return builder_; }
liveness_block() const94   LivenessAnalyzerBlock* liveness_block() const { return liveness_block_; }
values() const95   const NodeVector* values() const { return &values_; }
values()96   NodeVector* values() { return &values_; }
register_base() const97   int register_base() const { return register_base_; }
accumulator_base() const98   int accumulator_base() const { return accumulator_base_; }
99 
100   BytecodeGraphBuilder* builder_;
101   int register_count_;
102   int parameter_count_;
103   LivenessAnalyzerBlock* liveness_block_;
104   Node* context_;
105   Node* control_dependency_;
106   Node* effect_dependency_;
107   NodeVector values_;
108   Node* parameters_state_values_;
109   Node* registers_state_values_;
110   Node* accumulator_state_values_;
111   int register_base_;
112   int accumulator_base_;
113 };
114 
115 
116 // Issues:
117 // - Scopes - intimately tied to AST. Need to eval what is needed.
118 // - Need to resolve closure parameter treatment.
Environment(BytecodeGraphBuilder * builder,int register_count,int parameter_count,Node * control_dependency,Node * context)119 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder,
120                                                int register_count,
121                                                int parameter_count,
122                                                Node* control_dependency,
123                                                Node* context)
124     : builder_(builder),
125       register_count_(register_count),
126       parameter_count_(parameter_count),
127       liveness_block_(builder->is_liveness_analysis_enabled_
128                           ? builder_->liveness_analyzer()->NewBlock()
129                           : nullptr),
130       context_(context),
131       control_dependency_(control_dependency),
132       effect_dependency_(control_dependency),
133       values_(builder->local_zone()),
134       parameters_state_values_(nullptr),
135       registers_state_values_(nullptr),
136       accumulator_state_values_(nullptr) {
137   // The layout of values_ is:
138   //
139   // [receiver] [parameters] [registers] [accumulator]
140   //
141   // parameter[0] is the receiver (this), parameters 1..N are the
142   // parameters supplied to the method (arg0..argN-1). The accumulator
143   // is stored separately.
144 
145   // Parameters including the receiver
146   for (int i = 0; i < parameter_count; i++) {
147     const char* debug_name = (i == 0) ? "%this" : nullptr;
148     const Operator* op = common()->Parameter(i, debug_name);
149     Node* parameter = builder->graph()->NewNode(op, graph()->start());
150     values()->push_back(parameter);
151   }
152 
153   // Registers
154   register_base_ = static_cast<int>(values()->size());
155   Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
156   values()->insert(values()->end(), register_count, undefined_constant);
157 
158   // Accumulator
159   accumulator_base_ = static_cast<int>(values()->size());
160   values()->push_back(undefined_constant);
161 }
162 
Environment(const BytecodeGraphBuilder::Environment * other,LivenessAnalyzerBlock * liveness_block)163 BytecodeGraphBuilder::Environment::Environment(
164     const BytecodeGraphBuilder::Environment* other,
165     LivenessAnalyzerBlock* liveness_block)
166     : builder_(other->builder_),
167       register_count_(other->register_count_),
168       parameter_count_(other->parameter_count_),
169       liveness_block_(liveness_block),
170       context_(other->context_),
171       control_dependency_(other->control_dependency_),
172       effect_dependency_(other->effect_dependency_),
173       values_(other->zone()),
174       parameters_state_values_(nullptr),
175       registers_state_values_(nullptr),
176       accumulator_state_values_(nullptr),
177       register_base_(other->register_base_),
178       accumulator_base_(other->accumulator_base_) {
179   values_ = other->values_;
180 }
181 
182 
RegisterToValuesIndex(interpreter::Register the_register) const183 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
184     interpreter::Register the_register) const {
185   if (the_register.is_parameter()) {
186     return the_register.ToParameterIndex(parameter_count());
187   } else {
188     return the_register.index() + register_base();
189   }
190 }
191 
IsLivenessBlockConsistent() const192 bool BytecodeGraphBuilder::Environment::IsLivenessBlockConsistent() const {
193   return !builder_->IsLivenessAnalysisEnabled() ==
194          (liveness_block() == nullptr);
195 }
196 
LookupAccumulator() const197 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
198   DCHECK(IsLivenessBlockConsistent());
199   if (liveness_block() != nullptr) {
200     liveness_block()->LookupAccumulator();
201   }
202   return values()->at(accumulator_base_);
203 }
204 
205 
LookupRegister(interpreter::Register the_register) const206 Node* BytecodeGraphBuilder::Environment::LookupRegister(
207     interpreter::Register the_register) const {
208   if (the_register.is_current_context()) {
209     return Context();
210   } else if (the_register.is_function_closure()) {
211     return builder()->GetFunctionClosure();
212   } else if (the_register.is_new_target()) {
213     return builder()->GetNewTarget();
214   } else {
215     int values_index = RegisterToValuesIndex(the_register);
216     if (liveness_block() != nullptr && !the_register.is_parameter()) {
217       DCHECK(IsLivenessBlockConsistent());
218       liveness_block()->Lookup(the_register.index());
219     }
220     return values()->at(values_index);
221   }
222 }
223 
MarkAllRegistersLive()224 void BytecodeGraphBuilder::Environment::MarkAllRegistersLive() {
225   DCHECK(IsLivenessBlockConsistent());
226   if (liveness_block() != nullptr) {
227     for (int i = 0; i < register_count(); ++i) {
228       liveness_block()->Lookup(i);
229     }
230   }
231 }
232 
BindAccumulator(Node * node,FrameStateAttachmentMode mode)233 void BytecodeGraphBuilder::Environment::BindAccumulator(
234     Node* node, FrameStateAttachmentMode mode) {
235   if (mode == FrameStateAttachmentMode::kAttachFrameState) {
236     builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0));
237   }
238   DCHECK(IsLivenessBlockConsistent());
239   if (liveness_block() != nullptr) {
240     liveness_block()->BindAccumulator();
241   }
242   values()->at(accumulator_base_) = node;
243 }
244 
BindRegister(interpreter::Register the_register,Node * node,FrameStateAttachmentMode mode)245 void BytecodeGraphBuilder::Environment::BindRegister(
246     interpreter::Register the_register, Node* node,
247     FrameStateAttachmentMode mode) {
248   int values_index = RegisterToValuesIndex(the_register);
249   if (mode == FrameStateAttachmentMode::kAttachFrameState) {
250     builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
251                                            accumulator_base_ - values_index));
252   }
253   values()->at(values_index) = node;
254   if (liveness_block() != nullptr && !the_register.is_parameter()) {
255     DCHECK(IsLivenessBlockConsistent());
256     liveness_block()->Bind(the_register.index());
257   }
258 }
259 
BindRegistersToProjections(interpreter::Register first_reg,Node * node,FrameStateAttachmentMode mode)260 void BytecodeGraphBuilder::Environment::BindRegistersToProjections(
261     interpreter::Register first_reg, Node* node,
262     FrameStateAttachmentMode mode) {
263   int values_index = RegisterToValuesIndex(first_reg);
264   if (mode == FrameStateAttachmentMode::kAttachFrameState) {
265     builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
266                                            accumulator_base_ - values_index));
267   }
268   for (int i = 0; i < node->op()->ValueOutputCount(); i++) {
269     values()->at(values_index + i) =
270         builder()->NewNode(common()->Projection(i), node);
271   }
272 }
273 
RecordAfterState(Node * node,FrameStateAttachmentMode mode)274 void BytecodeGraphBuilder::Environment::RecordAfterState(
275     Node* node, FrameStateAttachmentMode mode) {
276   if (mode == FrameStateAttachmentMode::kAttachFrameState) {
277     builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore());
278   }
279 }
280 
281 
282 BytecodeGraphBuilder::Environment*
CopyForLoop()283 BytecodeGraphBuilder::Environment::CopyForLoop() {
284   PrepareForLoop();
285   if (liveness_block() != nullptr) {
286     // Finish the current block before copying.
287     liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
288   }
289   return new (zone()) Environment(this, liveness_block());
290 }
291 
292 BytecodeGraphBuilder::Environment*
CopyForOsrEntry()293 BytecodeGraphBuilder::Environment::CopyForOsrEntry() {
294   return new (zone())
295       Environment(this, builder_->liveness_analyzer()->NewBlock());
296 }
297 
298 BytecodeGraphBuilder::Environment*
CopyForConditional()299 BytecodeGraphBuilder::Environment::CopyForConditional() {
300   LivenessAnalyzerBlock* copy_liveness_block = nullptr;
301   if (liveness_block() != nullptr) {
302     copy_liveness_block =
303         builder_->liveness_analyzer()->NewBlock(liveness_block());
304     liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
305   }
306   return new (zone()) Environment(this, copy_liveness_block);
307 }
308 
309 
Merge(BytecodeGraphBuilder::Environment * other)310 void BytecodeGraphBuilder::Environment::Merge(
311     BytecodeGraphBuilder::Environment* other) {
312   if (builder_->is_liveness_analysis_enabled_) {
313     if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
314       liveness_block_ =
315           builder()->liveness_analyzer()->NewBlock(liveness_block());
316     }
317     liveness_block()->AddPredecessor(other->liveness_block());
318   }
319 
320   // Create a merge of the control dependencies of both environments and update
321   // the current environment's control dependency accordingly.
322   Node* control = builder()->MergeControl(GetControlDependency(),
323                                           other->GetControlDependency());
324   UpdateControlDependency(control);
325 
326   // Create a merge of the effect dependencies of both environments and update
327   // the current environment's effect dependency accordingly.
328   Node* effect = builder()->MergeEffect(GetEffectDependency(),
329                                         other->GetEffectDependency(), control);
330   UpdateEffectDependency(effect);
331 
332   // Introduce Phi nodes for values that have differing input at merge points,
333   // potentially extending an existing Phi node if possible.
334   context_ = builder()->MergeValue(context_, other->context_, control);
335   for (size_t i = 0; i < values_.size(); i++) {
336     values_[i] = builder()->MergeValue(values_[i], other->values_[i], control);
337   }
338 }
339 
340 
PrepareForLoop()341 void BytecodeGraphBuilder::Environment::PrepareForLoop() {
342   // Create a control node for the loop header.
343   Node* control = builder()->NewLoop();
344 
345   // Create a Phi for external effects.
346   Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control);
347   UpdateEffectDependency(effect);
348 
349   // Assume everything in the loop is updated.
350   context_ = builder()->NewPhi(1, context_, control);
351   int size = static_cast<int>(values()->size());
352   for (int i = 0; i < size; i++) {
353     values()->at(i) = builder()->NewPhi(1, values()->at(i), control);
354   }
355 
356   // Connect to the loop end.
357   Node* terminate = builder()->graph()->NewNode(
358       builder()->common()->Terminate(), effect, control);
359   builder()->exit_controls_.push_back(terminate);
360 }
361 
PrepareForOsrEntry()362 void BytecodeGraphBuilder::Environment::PrepareForOsrEntry() {
363   DCHECK_EQ(IrOpcode::kLoop, GetControlDependency()->opcode());
364   DCHECK_EQ(1, GetControlDependency()->InputCount());
365 
366   Node* start = graph()->start();
367 
368   // Create a control node for the OSR entry point and update the current
369   // environment's dependencies accordingly.
370   Node* entry = graph()->NewNode(common()->OsrLoopEntry(), start, start);
371   UpdateControlDependency(entry);
372   UpdateEffectDependency(entry);
373 
374   // Create OSR values for each environment value.
375   SetContext(graph()->NewNode(
376       common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), entry));
377   int size = static_cast<int>(values()->size());
378   for (int i = 0; i < size; i++) {
379     int idx = i;  // Indexing scheme follows {StandardFrame}, adapt accordingly.
380     if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount;
381     if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex;
382     values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry);
383   }
384 
385   BailoutId loop_id(builder_->bytecode_iterator().current_offset());
386   Node* frame_state =
387       Checkpoint(loop_id, OutputFrameStateCombine::Ignore(), false);
388   Node* checkpoint =
389       graph()->NewNode(common()->Checkpoint(), frame_state, entry, entry);
390   UpdateEffectDependency(checkpoint);
391 
392   // Create the OSR guard nodes.
393   const Operator* guard_op = common()->OsrGuard(OsrGuardType::kUninitialized);
394   Node* effect = checkpoint;
395   for (int i = 0; i < size; i++) {
396     values()->at(i) = effect =
397         graph()->NewNode(guard_op, values()->at(i), effect, entry);
398   }
399   Node* context = effect = graph()->NewNode(guard_op, Context(), effect, entry);
400   SetContext(context);
401   UpdateEffectDependency(effect);
402 }
403 
StateValuesRequireUpdate(Node ** state_values,int offset,int count)404 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
405     Node** state_values, int offset, int count) {
406   if (*state_values == nullptr) {
407     return true;
408   }
409   DCHECK_EQ((*state_values)->InputCount(), count);
410   DCHECK_LE(static_cast<size_t>(offset + count), values()->size());
411   Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
412   for (int i = 0; i < count; i++) {
413     if ((*state_values)->InputAt(i) != env_values[i]) {
414       return true;
415     }
416   }
417   return false;
418 }
419 
PrepareForLoopExit(Node * loop)420 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) {
421   DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);
422 
423   Node* control = GetControlDependency();
424 
425   // Create the loop exit node.
426   Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop);
427   UpdateControlDependency(loop_exit);
428 
429   // Rename the effect.
430   Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
431                                          GetEffectDependency(), loop_exit);
432   UpdateEffectDependency(effect_rename);
433 
434   // TODO(jarin) We should also rename context here. However, uncoditional
435   // renaming confuses global object and native context specialization.
436   // We should only rename if the context is assigned in the loop.
437 
438   // Rename the environmnent values.
439   for (size_t i = 0; i < values_.size(); i++) {
440     Node* rename =
441         graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit);
442     values_[i] = rename;
443   }
444 }
445 
UpdateStateValues(Node ** state_values,int offset,int count)446 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
447                                                           int offset,
448                                                           int count) {
449   if (StateValuesRequireUpdate(state_values, offset, count)) {
450     const Operator* op = common()->StateValues(count);
451     (*state_values) = graph()->NewNode(op, count, &values()->at(offset));
452   }
453 }
454 
Checkpoint(BailoutId bailout_id,OutputFrameStateCombine combine,bool owner_has_exception)455 Node* BytecodeGraphBuilder::Environment::Checkpoint(
456     BailoutId bailout_id, OutputFrameStateCombine combine,
457     bool owner_has_exception) {
458   UpdateStateValues(&parameters_state_values_, 0, parameter_count());
459   UpdateStateValues(&registers_state_values_, register_base(),
460                     register_count());
461   UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1);
462 
463   const Operator* op = common()->FrameState(
464       bailout_id, combine, builder()->frame_state_function_info());
465   Node* result = graph()->NewNode(
466       op, parameters_state_values_, registers_state_values_,
467       accumulator_state_values_, Context(), builder()->GetFunctionClosure(),
468       builder()->graph()->start());
469 
470   if (liveness_block() != nullptr) {
471     // If the owning node has an exception, register the checkpoint to the
472     // predecessor so that the checkpoint is used for both the normal and the
473     // exceptional paths. Yes, this is a terrible hack and we might want
474     // to use an explicit frame state for the exceptional path.
475     if (owner_has_exception) {
476       liveness_block()->GetPredecessor()->Checkpoint(result);
477     } else {
478       liveness_block()->Checkpoint(result);
479     }
480   }
481 
482   return result;
483 }
484 
BytecodeGraphBuilder(Zone * local_zone,CompilationInfo * info,JSGraph * jsgraph,float invocation_frequency,SourcePositionTable * source_positions,int inlining_id)485 BytecodeGraphBuilder::BytecodeGraphBuilder(
486     Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
487     float invocation_frequency, SourcePositionTable* source_positions,
488     int inlining_id)
489     : local_zone_(local_zone),
490       jsgraph_(jsgraph),
491       invocation_frequency_(invocation_frequency),
492       bytecode_array_(handle(info->shared_info()->bytecode_array())),
493       exception_handler_table_(
494           handle(HandlerTable::cast(bytecode_array()->handler_table()))),
495       feedback_vector_(handle(info->closure()->feedback_vector())),
496       frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
497           FrameStateType::kInterpretedFunction,
498           bytecode_array()->parameter_count(),
499           bytecode_array()->register_count(), info->shared_info())),
500       osr_ast_id_(info->osr_ast_id()),
501       merge_environments_(local_zone),
502       exception_handlers_(local_zone),
503       current_exception_handler_(0),
504       input_buffer_size_(0),
505       input_buffer_(nullptr),
506       exit_controls_(local_zone),
507       is_liveness_analysis_enabled_(FLAG_analyze_environment_liveness &&
508                                     info->is_deoptimization_enabled()),
509       state_values_cache_(jsgraph),
510       liveness_analyzer_(
511           static_cast<size_t>(bytecode_array()->register_count()), true,
512           local_zone),
513       source_positions_(source_positions),
514       start_position_(info->shared_info()->start_position(), inlining_id) {}
515 
GetNewTarget()516 Node* BytecodeGraphBuilder::GetNewTarget() {
517   if (!new_target_.is_set()) {
518     int params = bytecode_array()->parameter_count();
519     int index = Linkage::GetJSCallNewTargetParamIndex(params);
520     const Operator* op = common()->Parameter(index, "%new.target");
521     Node* node = NewNode(op, graph()->start());
522     new_target_.set(node);
523   }
524   return new_target_.get();
525 }
526 
527 
GetFunctionContext()528 Node* BytecodeGraphBuilder::GetFunctionContext() {
529   if (!function_context_.is_set()) {
530     int params = bytecode_array()->parameter_count();
531     int index = Linkage::GetJSCallContextParamIndex(params);
532     const Operator* op = common()->Parameter(index, "%context");
533     Node* node = NewNode(op, graph()->start());
534     function_context_.set(node);
535   }
536   return function_context_.get();
537 }
538 
539 
GetFunctionClosure()540 Node* BytecodeGraphBuilder::GetFunctionClosure() {
541   if (!function_closure_.is_set()) {
542     int index = Linkage::kJSCallClosureParamIndex;
543     const Operator* op = common()->Parameter(index, "%closure");
544     Node* node = NewNode(op, graph()->start());
545     function_closure_.set(node);
546   }
547   return function_closure_.get();
548 }
549 
550 
BuildLoadNativeContextField(int index)551 Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
552   const Operator* op =
553       javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
554   Node* native_context = NewNode(op, environment()->Context());
555   return NewNode(javascript()->LoadContext(0, index, true), native_context);
556 }
557 
558 
CreateVectorSlotPair(int slot_id)559 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
560   FeedbackVectorSlot slot;
561   if (slot_id >= TypeFeedbackVector::kReservedIndexCount) {
562     slot = feedback_vector()->ToSlot(slot_id);
563   }
564   return VectorSlotPair(feedback_vector(), slot);
565 }
566 
CreateGraph(bool stack_check)567 bool BytecodeGraphBuilder::CreateGraph(bool stack_check) {
568   SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
569 
570   // Set up the basic structure of the graph. Outputs for {Start} are the formal
571   // parameters (including the receiver) plus new target, number of arguments,
572   // context and closure.
573   int actual_parameter_count = bytecode_array()->parameter_count() + 4;
574   graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
575 
576   Environment env(this, bytecode_array()->register_count(),
577                   bytecode_array()->parameter_count(), graph()->start(),
578                   GetFunctionContext());
579   set_environment(&env);
580 
581   VisitBytecodes(stack_check);
582 
583   // Finish the basic structure of the graph.
584   DCHECK_NE(0u, exit_controls_.size());
585   int const input_count = static_cast<int>(exit_controls_.size());
586   Node** const inputs = &exit_controls_.front();
587   Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
588   graph()->SetEnd(end);
589 
590   ClearNonLiveSlotsInFrameStates();
591 
592   return true;
593 }
594 
PrepareEagerCheckpoint()595 void BytecodeGraphBuilder::PrepareEagerCheckpoint() {
596   if (environment()->GetEffectDependency()->opcode() != IrOpcode::kCheckpoint) {
597     // Create an explicit checkpoint node for before the operation. This only
598     // needs to happen if we aren't effect-dominated by a {Checkpoint} already.
599     Node* node = NewNode(common()->Checkpoint());
600     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
601     DCHECK_EQ(IrOpcode::kDead,
602               NodeProperties::GetFrameStateInput(node)->opcode());
603     BailoutId bailout_id(bytecode_iterator().current_offset());
604     Node* frame_state_before = environment()->Checkpoint(
605         bailout_id, OutputFrameStateCombine::Ignore(), false);
606     NodeProperties::ReplaceFrameStateInput(node, frame_state_before);
607   }
608 }
609 
PrepareFrameState(Node * node,OutputFrameStateCombine combine)610 void BytecodeGraphBuilder::PrepareFrameState(Node* node,
611                                              OutputFrameStateCombine combine) {
612   if (OperatorProperties::HasFrameStateInput(node->op())) {
613     // Add the frame state for after the operation. The node in question has
614     // already been created and had a {Dead} frame state input up until now.
615     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
616     DCHECK_EQ(IrOpcode::kDead,
617               NodeProperties::GetFrameStateInput(node)->opcode());
618     BailoutId bailout_id(bytecode_iterator().current_offset());
619     bool has_exception = NodeProperties::IsExceptionalCall(node);
620     Node* frame_state_after =
621         environment()->Checkpoint(bailout_id, combine, has_exception);
622     NodeProperties::ReplaceFrameStateInput(node, frame_state_after);
623   }
624 }
625 
ClearNonLiveSlotsInFrameStates()626 void BytecodeGraphBuilder::ClearNonLiveSlotsInFrameStates() {
627   if (!IsLivenessAnalysisEnabled()) {
628     return;
629   }
630   NonLiveFrameStateSlotReplacer replacer(
631       &state_values_cache_, jsgraph()->OptimizedOutConstant(),
632       liveness_analyzer()->local_count(), true, local_zone());
633   liveness_analyzer()->Run(&replacer);
634   if (FLAG_trace_environment_liveness) {
635     OFStream os(stdout);
636     liveness_analyzer()->Print(os);
637   }
638 }
639 
VisitBytecodes(bool stack_check)640 void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) {
641   BytecodeBranchAnalysis analysis(bytecode_array(), local_zone());
642   BytecodeLoopAnalysis loop_analysis(bytecode_array(), &analysis, local_zone());
643   analysis.Analyze();
644   loop_analysis.Analyze();
645   set_branch_analysis(&analysis);
646   set_loop_analysis(&loop_analysis);
647 
648   interpreter::BytecodeArrayIterator iterator(bytecode_array());
649   set_bytecode_iterator(&iterator);
650   SourcePositionTableIterator source_position_iterator(
651       bytecode_array()->source_position_table());
652 
653   BuildOSRNormalEntryPoint();
654   for (; !iterator.done(); iterator.Advance()) {
655     int current_offset = iterator.current_offset();
656     UpdateCurrentSourcePosition(&source_position_iterator, current_offset);
657     EnterAndExitExceptionHandlers(current_offset);
658     SwitchToMergeEnvironment(current_offset);
659     if (environment() != nullptr) {
660       BuildLoopHeaderEnvironment(current_offset);
661       BuildOSRLoopEntryPoint(current_offset);
662 
663       // Skip the first stack check if stack_check is false
664       if (!stack_check &&
665           iterator.current_bytecode() == interpreter::Bytecode::kStackCheck) {
666         stack_check = true;
667         continue;
668       }
669 
670       switch (iterator.current_bytecode()) {
671 #define BYTECODE_CASE(name, ...)       \
672   case interpreter::Bytecode::k##name: \
673     Visit##name();                     \
674     break;
675         BYTECODE_LIST(BYTECODE_CASE)
676 #undef BYTECODE_CODE
677       }
678     }
679   }
680 
681   set_branch_analysis(nullptr);
682   set_bytecode_iterator(nullptr);
683   DCHECK(exception_handlers_.empty());
684 }
685 
VisitLdaZero()686 void BytecodeGraphBuilder::VisitLdaZero() {
687   Node* node = jsgraph()->ZeroConstant();
688   environment()->BindAccumulator(node);
689 }
690 
VisitLdaSmi()691 void BytecodeGraphBuilder::VisitLdaSmi() {
692   Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
693   environment()->BindAccumulator(node);
694 }
695 
VisitLdaConstant()696 void BytecodeGraphBuilder::VisitLdaConstant() {
697   Node* node =
698       jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
699   environment()->BindAccumulator(node);
700 }
701 
VisitLdaUndefined()702 void BytecodeGraphBuilder::VisitLdaUndefined() {
703   Node* node = jsgraph()->UndefinedConstant();
704   environment()->BindAccumulator(node);
705 }
706 
VisitLdaNull()707 void BytecodeGraphBuilder::VisitLdaNull() {
708   Node* node = jsgraph()->NullConstant();
709   environment()->BindAccumulator(node);
710 }
711 
VisitLdaTheHole()712 void BytecodeGraphBuilder::VisitLdaTheHole() {
713   Node* node = jsgraph()->TheHoleConstant();
714   environment()->BindAccumulator(node);
715 }
716 
VisitLdaTrue()717 void BytecodeGraphBuilder::VisitLdaTrue() {
718   Node* node = jsgraph()->TrueConstant();
719   environment()->BindAccumulator(node);
720 }
721 
VisitLdaFalse()722 void BytecodeGraphBuilder::VisitLdaFalse() {
723   Node* node = jsgraph()->FalseConstant();
724   environment()->BindAccumulator(node);
725 }
726 
VisitLdar()727 void BytecodeGraphBuilder::VisitLdar() {
728   Node* value =
729       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
730   environment()->BindAccumulator(value);
731 }
732 
VisitStar()733 void BytecodeGraphBuilder::VisitStar() {
734   Node* value = environment()->LookupAccumulator();
735   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value);
736 }
737 
VisitMov()738 void BytecodeGraphBuilder::VisitMov() {
739   Node* value =
740       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
741   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value);
742 }
743 
BuildLoadGlobal(uint32_t feedback_slot_index,TypeofMode typeof_mode)744 Node* BytecodeGraphBuilder::BuildLoadGlobal(uint32_t feedback_slot_index,
745                                             TypeofMode typeof_mode) {
746   VectorSlotPair feedback = CreateVectorSlotPair(feedback_slot_index);
747   DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
748             feedback_vector()->GetKind(feedback.slot()));
749   Handle<Name> name(feedback_vector()->GetName(feedback.slot()));
750   const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
751   return NewNode(op, GetFunctionClosure());
752 }
753 
VisitLdaGlobal()754 void BytecodeGraphBuilder::VisitLdaGlobal() {
755   PrepareEagerCheckpoint();
756   Node* node = BuildLoadGlobal(bytecode_iterator().GetIndexOperand(0),
757                                TypeofMode::NOT_INSIDE_TYPEOF);
758   environment()->BindAccumulator(node, Environment::kAttachFrameState);
759 }
760 
VisitLdaGlobalInsideTypeof()761 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() {
762   PrepareEagerCheckpoint();
763   Node* node = BuildLoadGlobal(bytecode_iterator().GetIndexOperand(0),
764                                TypeofMode::INSIDE_TYPEOF);
765   environment()->BindAccumulator(node, Environment::kAttachFrameState);
766 }
767 
BuildStoreGlobal(LanguageMode language_mode)768 void BytecodeGraphBuilder::BuildStoreGlobal(LanguageMode language_mode) {
769   PrepareEagerCheckpoint();
770   Handle<Name> name =
771       Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
772   VectorSlotPair feedback =
773       CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
774   Node* value = environment()->LookupAccumulator();
775 
776   const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback);
777   Node* node = NewNode(op, value, GetFunctionClosure());
778   environment()->RecordAfterState(node, Environment::kAttachFrameState);
779 }
780 
VisitStaGlobalSloppy()781 void BytecodeGraphBuilder::VisitStaGlobalSloppy() {
782   BuildStoreGlobal(LanguageMode::SLOPPY);
783 }
784 
VisitStaGlobalStrict()785 void BytecodeGraphBuilder::VisitStaGlobalStrict() {
786   BuildStoreGlobal(LanguageMode::STRICT);
787 }
788 
VisitLdaContextSlot()789 void BytecodeGraphBuilder::VisitLdaContextSlot() {
790   // TODO(mythria): immutable flag is also set to false. This information is not
791   // available in bytecode array. update this code when the implementation
792   // changes.
793   const Operator* op = javascript()->LoadContext(
794       bytecode_iterator().GetUnsignedImmediateOperand(2),
795       bytecode_iterator().GetIndexOperand(1), false);
796   Node* context =
797       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
798   Node* node = NewNode(op, context);
799   environment()->BindAccumulator(node);
800 }
801 
VisitLdaCurrentContextSlot()802 void BytecodeGraphBuilder::VisitLdaCurrentContextSlot() {
803   // TODO(mythria): immutable flag is also set to false. This information is not
804   // available in bytecode array. update this code when the implementation
805   // changes.
806   const Operator* op = javascript()->LoadContext(
807       0, bytecode_iterator().GetIndexOperand(0), false);
808   Node* context = environment()->Context();
809   Node* node = NewNode(op, context);
810   environment()->BindAccumulator(node);
811 }
812 
VisitStaContextSlot()813 void BytecodeGraphBuilder::VisitStaContextSlot() {
814   const Operator* op = javascript()->StoreContext(
815       bytecode_iterator().GetUnsignedImmediateOperand(2),
816       bytecode_iterator().GetIndexOperand(1));
817   Node* context =
818       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
819   Node* value = environment()->LookupAccumulator();
820   NewNode(op, context, value);
821 }
822 
VisitStaCurrentContextSlot()823 void BytecodeGraphBuilder::VisitStaCurrentContextSlot() {
824   const Operator* op =
825       javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(0));
826   Node* context = environment()->Context();
827   Node* value = environment()->LookupAccumulator();
828   NewNode(op, context, value);
829 }
830 
BuildLdaLookupSlot(TypeofMode typeof_mode)831 void BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) {
832   PrepareEagerCheckpoint();
833   Node* name =
834       jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
835   const Operator* op =
836       javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
837                                     ? Runtime::kLoadLookupSlot
838                                     : Runtime::kLoadLookupSlotInsideTypeof);
839   Node* value = NewNode(op, name);
840   environment()->BindAccumulator(value, Environment::kAttachFrameState);
841 }
842 
VisitLdaLookupSlot()843 void BytecodeGraphBuilder::VisitLdaLookupSlot() {
844   BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF);
845 }
846 
VisitLdaLookupSlotInsideTypeof()847 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
848   BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF);
849 }
850 
CheckContextExtensions(uint32_t depth)851 BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions(
852     uint32_t depth) {
853   // Output environment where the context has an extension
854   Environment* slow_environment = nullptr;
855 
856   // We only need to check up to the last-but-one depth, because the an eval in
857   // the same scope as the variable itself has no way of shadowing it.
858   for (uint32_t d = 0; d < depth; d++) {
859     Node* extension_slot =
860         NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false),
861                 environment()->Context());
862 
863     Node* check_no_extension =
864         NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
865                 extension_slot, jsgraph()->TheHoleConstant());
866 
867     NewBranch(check_no_extension);
868     Environment* true_environment = environment()->CopyForConditional();
869 
870     {
871       NewIfFalse();
872       // If there is an extension, merge into the slow path.
873       if (slow_environment == nullptr) {
874         slow_environment = environment();
875         NewMerge();
876       } else {
877         slow_environment->Merge(environment());
878       }
879     }
880 
881     {
882       set_environment(true_environment);
883       NewIfTrue();
884       // Do nothing on if there is no extension, eventually falling through to
885       // the fast path.
886     }
887   }
888 
889   // The depth can be zero, in which case no slow-path checks are built, and the
890   // slow path environment can be null.
891   DCHECK(depth == 0 || slow_environment != nullptr);
892 
893   return slow_environment;
894 }
895 
BuildLdaLookupContextSlot(TypeofMode typeof_mode)896 void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) {
897   uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
898 
899   // Check if any context in the depth has an extension.
900   Environment* slow_environment = CheckContextExtensions(depth);
901 
902   // Fast path, do a context load.
903   {
904     uint32_t slot_index = bytecode_iterator().GetIndexOperand(1);
905 
906     const Operator* op = javascript()->LoadContext(depth, slot_index, false);
907     Node* context = environment()->Context();
908     environment()->BindAccumulator(NewNode(op, context));
909   }
910 
911   // Only build the slow path if there were any slow-path checks.
912   if (slow_environment != nullptr) {
913     // Add a merge to the fast environment.
914     NewMerge();
915     Environment* fast_environment = environment();
916 
917     // Slow path, do a runtime load lookup.
918     set_environment(slow_environment);
919     {
920       Node* name = jsgraph()->Constant(
921           bytecode_iterator().GetConstantForIndexOperand(0));
922 
923       const Operator* op =
924           javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
925                                         ? Runtime::kLoadLookupSlot
926                                         : Runtime::kLoadLookupSlotInsideTypeof);
927       Node* value = NewNode(op, name);
928       environment()->BindAccumulator(value, Environment::kAttachFrameState);
929     }
930 
931     fast_environment->Merge(environment());
932     set_environment(fast_environment);
933   }
934 }
935 
VisitLdaLookupContextSlot()936 void BytecodeGraphBuilder::VisitLdaLookupContextSlot() {
937   BuildLdaLookupContextSlot(TypeofMode::NOT_INSIDE_TYPEOF);
938 }
939 
VisitLdaLookupContextSlotInsideTypeof()940 void BytecodeGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() {
941   BuildLdaLookupContextSlot(TypeofMode::INSIDE_TYPEOF);
942 }
943 
BuildLdaLookupGlobalSlot(TypeofMode typeof_mode)944 void BytecodeGraphBuilder::BuildLdaLookupGlobalSlot(TypeofMode typeof_mode) {
945   uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
946 
947   // Check if any context in the depth has an extension.
948   Environment* slow_environment = CheckContextExtensions(depth);
949 
950   // Fast path, do a global load.
951   {
952     PrepareEagerCheckpoint();
953     Node* node =
954         BuildLoadGlobal(bytecode_iterator().GetIndexOperand(1), typeof_mode);
955     environment()->BindAccumulator(node, Environment::kAttachFrameState);
956   }
957 
958   // Only build the slow path if there were any slow-path checks.
959   if (slow_environment != nullptr) {
960     // Add a merge to the fast environment.
961     NewMerge();
962     Environment* fast_environment = environment();
963 
964     // Slow path, do a runtime load lookup.
965     set_environment(slow_environment);
966     {
967       Node* name = jsgraph()->Constant(
968           bytecode_iterator().GetConstantForIndexOperand(0));
969 
970       const Operator* op =
971           javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
972                                         ? Runtime::kLoadLookupSlot
973                                         : Runtime::kLoadLookupSlotInsideTypeof);
974       Node* value = NewNode(op, name);
975       environment()->BindAccumulator(value, Environment::kAttachFrameState);
976     }
977 
978     fast_environment->Merge(environment());
979     set_environment(fast_environment);
980   }
981 }
982 
VisitLdaLookupGlobalSlot()983 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlot() {
984   BuildLdaLookupGlobalSlot(TypeofMode::NOT_INSIDE_TYPEOF);
985 }
986 
VisitLdaLookupGlobalSlotInsideTypeof()987 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() {
988   BuildLdaLookupGlobalSlot(TypeofMode::INSIDE_TYPEOF);
989 }
990 
BuildStaLookupSlot(LanguageMode language_mode)991 void BytecodeGraphBuilder::BuildStaLookupSlot(LanguageMode language_mode) {
992   PrepareEagerCheckpoint();
993   Node* value = environment()->LookupAccumulator();
994   Node* name =
995       jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
996   const Operator* op = javascript()->CallRuntime(
997       is_strict(language_mode) ? Runtime::kStoreLookupSlot_Strict
998                                : Runtime::kStoreLookupSlot_Sloppy);
999   Node* store = NewNode(op, name, value);
1000   environment()->BindAccumulator(store, Environment::kAttachFrameState);
1001 }
1002 
VisitStaLookupSlotSloppy()1003 void BytecodeGraphBuilder::VisitStaLookupSlotSloppy() {
1004   BuildStaLookupSlot(LanguageMode::SLOPPY);
1005 }
1006 
VisitStaLookupSlotStrict()1007 void BytecodeGraphBuilder::VisitStaLookupSlotStrict() {
1008   BuildStaLookupSlot(LanguageMode::STRICT);
1009 }
1010 
VisitLdaNamedProperty()1011 void BytecodeGraphBuilder::VisitLdaNamedProperty() {
1012   PrepareEagerCheckpoint();
1013   Node* object =
1014       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1015   Handle<Name> name =
1016       Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
1017   VectorSlotPair feedback =
1018       CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1019 
1020   const Operator* op = javascript()->LoadNamed(name, feedback);
1021   Node* node = NewNode(op, object, GetFunctionClosure());
1022   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1023 }
1024 
VisitLdaKeyedProperty()1025 void BytecodeGraphBuilder::VisitLdaKeyedProperty() {
1026   PrepareEagerCheckpoint();
1027   Node* key = environment()->LookupAccumulator();
1028   Node* object =
1029       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1030   VectorSlotPair feedback =
1031       CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
1032 
1033   const Operator* op = javascript()->LoadProperty(feedback);
1034   Node* node = NewNode(op, object, key, GetFunctionClosure());
1035   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1036 }
1037 
BuildNamedStore(LanguageMode language_mode)1038 void BytecodeGraphBuilder::BuildNamedStore(LanguageMode language_mode) {
1039   PrepareEagerCheckpoint();
1040   Node* value = environment()->LookupAccumulator();
1041   Node* object =
1042       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1043   Handle<Name> name =
1044       Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
1045   VectorSlotPair feedback =
1046       CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1047 
1048   const Operator* op = javascript()->StoreNamed(language_mode, name, feedback);
1049   Node* node = NewNode(op, object, value, GetFunctionClosure());
1050   environment()->RecordAfterState(node, Environment::kAttachFrameState);
1051 }
1052 
VisitStaNamedPropertySloppy()1053 void BytecodeGraphBuilder::VisitStaNamedPropertySloppy() {
1054   BuildNamedStore(LanguageMode::SLOPPY);
1055 }
1056 
VisitStaNamedPropertyStrict()1057 void BytecodeGraphBuilder::VisitStaNamedPropertyStrict() {
1058   BuildNamedStore(LanguageMode::STRICT);
1059 }
1060 
BuildKeyedStore(LanguageMode language_mode)1061 void BytecodeGraphBuilder::BuildKeyedStore(LanguageMode language_mode) {
1062   PrepareEagerCheckpoint();
1063   Node* value = environment()->LookupAccumulator();
1064   Node* object =
1065       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1066   Node* key =
1067       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1068   VectorSlotPair feedback =
1069       CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1070 
1071   const Operator* op = javascript()->StoreProperty(language_mode, feedback);
1072   Node* node = NewNode(op, object, key, value, GetFunctionClosure());
1073   environment()->RecordAfterState(node, Environment::kAttachFrameState);
1074 }
1075 
VisitStaKeyedPropertySloppy()1076 void BytecodeGraphBuilder::VisitStaKeyedPropertySloppy() {
1077   BuildKeyedStore(LanguageMode::SLOPPY);
1078 }
1079 
VisitStaKeyedPropertyStrict()1080 void BytecodeGraphBuilder::VisitStaKeyedPropertyStrict() {
1081   BuildKeyedStore(LanguageMode::STRICT);
1082 }
1083 
VisitLdaModuleVariable()1084 void BytecodeGraphBuilder::VisitLdaModuleVariable() {
1085   int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
1086   uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
1087   Node* module =
1088       NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
1089               environment()->Context());
1090   Node* value = NewNode(javascript()->LoadModule(cell_index), module);
1091   environment()->BindAccumulator(value);
1092 }
1093 
VisitStaModuleVariable()1094 void BytecodeGraphBuilder::VisitStaModuleVariable() {
1095   int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
1096   uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
1097   Node* module =
1098       NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
1099               environment()->Context());
1100   Node* value = environment()->LookupAccumulator();
1101   NewNode(javascript()->StoreModule(cell_index), module, value);
1102 }
1103 
VisitPushContext()1104 void BytecodeGraphBuilder::VisitPushContext() {
1105   Node* new_context = environment()->LookupAccumulator();
1106   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0),
1107                               environment()->Context());
1108   environment()->SetContext(new_context);
1109 }
1110 
VisitPopContext()1111 void BytecodeGraphBuilder::VisitPopContext() {
1112   Node* context =
1113       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1114   environment()->SetContext(context);
1115 }
1116 
VisitCreateClosure()1117 void BytecodeGraphBuilder::VisitCreateClosure() {
1118   Handle<SharedFunctionInfo> shared_info = Handle<SharedFunctionInfo>::cast(
1119       bytecode_iterator().GetConstantForIndexOperand(0));
1120   PretenureFlag tenured =
1121       interpreter::CreateClosureFlags::PretenuredBit::decode(
1122           bytecode_iterator().GetFlagOperand(1))
1123           ? TENURED
1124           : NOT_TENURED;
1125   const Operator* op = javascript()->CreateClosure(shared_info, tenured);
1126   Node* closure = NewNode(op);
1127   environment()->BindAccumulator(closure);
1128 }
1129 
VisitCreateBlockContext()1130 void BytecodeGraphBuilder::VisitCreateBlockContext() {
1131   Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(
1132       bytecode_iterator().GetConstantForIndexOperand(0));
1133 
1134   const Operator* op = javascript()->CreateBlockContext(scope_info);
1135   Node* context = NewNode(op, environment()->LookupAccumulator());
1136   environment()->BindAccumulator(context);
1137 }
1138 
VisitCreateFunctionContext()1139 void BytecodeGraphBuilder::VisitCreateFunctionContext() {
1140   uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(0);
1141   const Operator* op = javascript()->CreateFunctionContext(slots);
1142   Node* context = NewNode(op, GetFunctionClosure());
1143   environment()->BindAccumulator(context);
1144 }
1145 
VisitCreateCatchContext()1146 void BytecodeGraphBuilder::VisitCreateCatchContext() {
1147   interpreter::Register reg = bytecode_iterator().GetRegisterOperand(0);
1148   Node* exception = environment()->LookupRegister(reg);
1149   Handle<String> name =
1150       Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
1151   Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(
1152       bytecode_iterator().GetConstantForIndexOperand(2));
1153   Node* closure = environment()->LookupAccumulator();
1154 
1155   const Operator* op = javascript()->CreateCatchContext(name, scope_info);
1156   Node* context = NewNode(op, exception, closure);
1157   environment()->BindAccumulator(context);
1158 }
1159 
VisitCreateWithContext()1160 void BytecodeGraphBuilder::VisitCreateWithContext() {
1161   Node* object =
1162       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1163   Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(
1164       bytecode_iterator().GetConstantForIndexOperand(1));
1165 
1166   const Operator* op = javascript()->CreateWithContext(scope_info);
1167   Node* context = NewNode(op, object, environment()->LookupAccumulator());
1168   environment()->BindAccumulator(context);
1169 }
1170 
BuildCreateArguments(CreateArgumentsType type)1171 void BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) {
1172   const Operator* op = javascript()->CreateArguments(type);
1173   Node* object = NewNode(op, GetFunctionClosure());
1174   environment()->BindAccumulator(object, Environment::kAttachFrameState);
1175 }
1176 
VisitCreateMappedArguments()1177 void BytecodeGraphBuilder::VisitCreateMappedArguments() {
1178   BuildCreateArguments(CreateArgumentsType::kMappedArguments);
1179 }
1180 
VisitCreateUnmappedArguments()1181 void BytecodeGraphBuilder::VisitCreateUnmappedArguments() {
1182   BuildCreateArguments(CreateArgumentsType::kUnmappedArguments);
1183 }
1184 
VisitCreateRestParameter()1185 void BytecodeGraphBuilder::VisitCreateRestParameter() {
1186   BuildCreateArguments(CreateArgumentsType::kRestParameter);
1187 }
1188 
VisitCreateRegExpLiteral()1189 void BytecodeGraphBuilder::VisitCreateRegExpLiteral() {
1190   Handle<String> constant_pattern =
1191       Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
1192   int literal_index = bytecode_iterator().GetIndexOperand(1);
1193   int literal_flags = bytecode_iterator().GetFlagOperand(2);
1194   Node* literal = NewNode(javascript()->CreateLiteralRegExp(
1195                               constant_pattern, literal_flags, literal_index),
1196                           GetFunctionClosure());
1197   environment()->BindAccumulator(literal, Environment::kAttachFrameState);
1198 }
1199 
VisitCreateArrayLiteral()1200 void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
1201   Handle<FixedArray> constant_elements = Handle<FixedArray>::cast(
1202       bytecode_iterator().GetConstantForIndexOperand(0));
1203   int literal_index = bytecode_iterator().GetIndexOperand(1);
1204   int literal_flags = bytecode_iterator().GetFlagOperand(2);
1205   // Disable allocation site mementos. Only unoptimized code will collect
1206   // feedback about allocation site. Once the code is optimized we expect the
1207   // data to converge. So, we disable allocation site mementos in optimized
1208   // code. We can revisit this when we have data to the contrary.
1209   literal_flags |= ArrayLiteral::kDisableMementos;
1210   int number_of_elements = constant_elements->length();
1211   Node* literal = NewNode(
1212       javascript()->CreateLiteralArray(constant_elements, literal_flags,
1213                                        literal_index, number_of_elements),
1214       GetFunctionClosure());
1215   environment()->BindAccumulator(literal, Environment::kAttachFrameState);
1216 }
1217 
VisitCreateObjectLiteral()1218 void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
1219   PrepareEagerCheckpoint();
1220   Handle<FixedArray> constant_properties = Handle<FixedArray>::cast(
1221       bytecode_iterator().GetConstantForIndexOperand(0));
1222   int literal_index = bytecode_iterator().GetIndexOperand(1);
1223   int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
1224   int literal_flags =
1225       interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
1226   // TODO(mstarzinger): Thread through number of properties.
1227   int number_of_properties = constant_properties->length() / 2;
1228   Node* literal = NewNode(
1229       javascript()->CreateLiteralObject(constant_properties, literal_flags,
1230                                         literal_index, number_of_properties),
1231       GetFunctionClosure());
1232   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(3),
1233                               literal, Environment::kAttachFrameState);
1234 }
1235 
ProcessCallArguments(const Operator * call_op,Node * callee,interpreter::Register receiver,size_t arity)1236 Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
1237                                                  Node* callee,
1238                                                  interpreter::Register receiver,
1239                                                  size_t arity) {
1240   Node** all = local_zone()->NewArray<Node*>(static_cast<int>(arity));
1241   all[0] = callee;
1242   all[1] = environment()->LookupRegister(receiver);
1243   int receiver_index = receiver.index();
1244   for (int i = 2; i < static_cast<int>(arity); ++i) {
1245     all[i] = environment()->LookupRegister(
1246         interpreter::Register(receiver_index + i - 1));
1247   }
1248   Node* value = MakeNode(call_op, static_cast<int>(arity), all, false);
1249   return value;
1250 }
1251 
BuildCall(TailCallMode tail_call_mode,ConvertReceiverMode receiver_hint)1252 void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode,
1253                                      ConvertReceiverMode receiver_hint) {
1254   PrepareEagerCheckpoint();
1255 
1256   Node* callee =
1257       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1258   interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1259   size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
1260 
1261   // Slot index of 0 is used indicate no feedback slot is available. Assert
1262   // the assumption that slot index 0 is never a valid feedback slot.
1263   STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0);
1264   int const slot_id = bytecode_iterator().GetIndexOperand(3);
1265   VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1266 
1267   float const frequency = ComputeCallFrequency(slot_id);
1268   const Operator* call = javascript()->CallFunction(
1269       arg_count + 1, frequency, feedback, receiver_hint, tail_call_mode);
1270   Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1);
1271   environment()->BindAccumulator(value, Environment::kAttachFrameState);
1272 }
1273 
VisitCall()1274 void BytecodeGraphBuilder::VisitCall() {
1275   BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kAny);
1276 }
1277 
VisitCallProperty()1278 void BytecodeGraphBuilder::VisitCallProperty() {
1279   BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNotNullOrUndefined);
1280 }
1281 
VisitTailCall()1282 void BytecodeGraphBuilder::VisitTailCall() {
1283   TailCallMode tail_call_mode =
1284       bytecode_array_->GetIsolate()->is_tail_call_elimination_enabled()
1285           ? TailCallMode::kAllow
1286           : TailCallMode::kDisallow;
1287   BuildCall(tail_call_mode, ConvertReceiverMode::kAny);
1288 }
1289 
VisitCallJSRuntime()1290 void BytecodeGraphBuilder::VisitCallJSRuntime() {
1291   PrepareEagerCheckpoint();
1292   Node* callee =
1293       BuildLoadNativeContextField(bytecode_iterator().GetIndexOperand(0));
1294   interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1295   size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
1296 
1297   // Create node to perform the JS runtime call.
1298   const Operator* call = javascript()->CallFunction(arg_count + 1);
1299   Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1);
1300   environment()->BindAccumulator(value, Environment::kAttachFrameState);
1301 }
1302 
ProcessCallRuntimeArguments(const Operator * call_runtime_op,interpreter::Register first_arg,size_t arity)1303 Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
1304     const Operator* call_runtime_op, interpreter::Register first_arg,
1305     size_t arity) {
1306   Node** all = local_zone()->NewArray<Node*>(arity);
1307   int first_arg_index = first_arg.index();
1308   for (int i = 0; i < static_cast<int>(arity); ++i) {
1309     all[i] = environment()->LookupRegister(
1310         interpreter::Register(first_arg_index + i));
1311   }
1312   Node* value = MakeNode(call_runtime_op, static_cast<int>(arity), all, false);
1313   return value;
1314 }
1315 
VisitCallRuntime()1316 void BytecodeGraphBuilder::VisitCallRuntime() {
1317   PrepareEagerCheckpoint();
1318   Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
1319   interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
1320   size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
1321 
1322   // Create node to perform the runtime call.
1323   const Operator* call = javascript()->CallRuntime(functionId, arg_count);
1324   Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count);
1325   environment()->BindAccumulator(value, Environment::kAttachFrameState);
1326 }
1327 
VisitCallRuntimeForPair()1328 void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
1329   PrepareEagerCheckpoint();
1330   Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
1331   interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
1332   size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
1333   interpreter::Register first_return =
1334       bytecode_iterator().GetRegisterOperand(3);
1335 
1336   // Create node to perform the runtime call.
1337   const Operator* call = javascript()->CallRuntime(functionId, arg_count);
1338   Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count);
1339   environment()->BindRegistersToProjections(first_return, return_pair,
1340                                             Environment::kAttachFrameState);
1341 }
1342 
VisitInvokeIntrinsic()1343 void BytecodeGraphBuilder::VisitInvokeIntrinsic() {
1344   PrepareEagerCheckpoint();
1345   Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0);
1346   interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
1347   size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
1348 
1349   // Create node to perform the runtime call. Turbofan will take care of the
1350   // lowering.
1351   const Operator* call = javascript()->CallRuntime(functionId, arg_count);
1352   Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count);
1353   environment()->BindAccumulator(value, Environment::kAttachFrameState);
1354 }
1355 
ProcessCallNewArguments(const Operator * call_new_op,Node * callee,Node * new_target,interpreter::Register first_arg,size_t arity)1356 Node* BytecodeGraphBuilder::ProcessCallNewArguments(
1357     const Operator* call_new_op, Node* callee, Node* new_target,
1358     interpreter::Register first_arg, size_t arity) {
1359   Node** all = local_zone()->NewArray<Node*>(arity);
1360   all[0] = callee;
1361   int first_arg_index = first_arg.index();
1362   for (int i = 1; i < static_cast<int>(arity) - 1; ++i) {
1363     all[i] = environment()->LookupRegister(
1364         interpreter::Register(first_arg_index + i - 1));
1365   }
1366   all[arity - 1] = new_target;
1367   Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false);
1368   return value;
1369 }
1370 
VisitNew()1371 void BytecodeGraphBuilder::VisitNew() {
1372   PrepareEagerCheckpoint();
1373   interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
1374   interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
1375   size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
1376   // Slot index of 0 is used indicate no feedback slot is available. Assert
1377   // the assumption that slot index 0 is never a valid feedback slot.
1378   STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0);
1379   int const slot_id = bytecode_iterator().GetIndexOperand(3);
1380   VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1381 
1382   Node* new_target = environment()->LookupAccumulator();
1383   Node* callee = environment()->LookupRegister(callee_reg);
1384 
1385   float const frequency = ComputeCallFrequency(slot_id);
1386   const Operator* call = javascript()->CallConstruct(
1387       static_cast<int>(arg_count) + 2, frequency, feedback);
1388   Node* value = ProcessCallNewArguments(call, callee, new_target, first_arg,
1389                                         arg_count + 2);
1390   environment()->BindAccumulator(value, Environment::kAttachFrameState);
1391 }
1392 
BuildThrow()1393 void BytecodeGraphBuilder::BuildThrow() {
1394   PrepareEagerCheckpoint();
1395   Node* value = environment()->LookupAccumulator();
1396   Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value);
1397   environment()->BindAccumulator(call, Environment::kAttachFrameState);
1398 }
1399 
VisitThrow()1400 void BytecodeGraphBuilder::VisitThrow() {
1401   BuildLoopExitsForFunctionExit();
1402   BuildThrow();
1403   Node* call = environment()->LookupAccumulator();
1404   Node* control = NewNode(common()->Throw(), call);
1405   MergeControlToLeaveFunction(control);
1406 }
1407 
VisitReThrow()1408 void BytecodeGraphBuilder::VisitReThrow() {
1409   BuildLoopExitsForFunctionExit();
1410   Node* value = environment()->LookupAccumulator();
1411   Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value);
1412   Node* control = NewNode(common()->Throw(), call);
1413   MergeControlToLeaveFunction(control);
1414 }
1415 
BuildBinaryOp(const Operator * js_op)1416 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) {
1417   PrepareEagerCheckpoint();
1418   Node* left =
1419       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1420   Node* right = environment()->LookupAccumulator();
1421   Node* node = NewNode(js_op, left, right);
1422   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1423 }
1424 
1425 // Helper function to create binary operation hint from the recorded type
1426 // feedback.
GetBinaryOperationHint(int operand_index)1427 BinaryOperationHint BytecodeGraphBuilder::GetBinaryOperationHint(
1428     int operand_index) {
1429   FeedbackVectorSlot slot = feedback_vector()->ToSlot(
1430       bytecode_iterator().GetIndexOperand(operand_index));
1431   DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC,
1432             feedback_vector()->GetKind(slot));
1433   BinaryOpICNexus nexus(feedback_vector(), slot);
1434   return nexus.GetBinaryOperationFeedback();
1435 }
1436 
1437 // Helper function to create compare operation hint from the recorded type
1438 // feedback.
GetCompareOperationHint()1439 CompareOperationHint BytecodeGraphBuilder::GetCompareOperationHint() {
1440   int slot_index = bytecode_iterator().GetIndexOperand(1);
1441   if (slot_index == 0) {
1442     return CompareOperationHint::kAny;
1443   }
1444   FeedbackVectorSlot slot =
1445       feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(1));
1446   DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC,
1447             feedback_vector()->GetKind(slot));
1448   CompareICNexus nexus(feedback_vector(), slot);
1449   return nexus.GetCompareOperationFeedback();
1450 }
1451 
ComputeCallFrequency(int slot_id) const1452 float BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const {
1453   CallICNexus nexus(feedback_vector(), feedback_vector()->ToSlot(slot_id));
1454   return nexus.ComputeCallFrequency() * invocation_frequency_;
1455 }
1456 
VisitAdd()1457 void BytecodeGraphBuilder::VisitAdd() {
1458   BuildBinaryOp(
1459       javascript()->Add(GetBinaryOperationHint(kBinaryOperationHintIndex)));
1460 }
1461 
VisitSub()1462 void BytecodeGraphBuilder::VisitSub() {
1463   BuildBinaryOp(javascript()->Subtract(
1464       GetBinaryOperationHint(kBinaryOperationHintIndex)));
1465 }
1466 
VisitMul()1467 void BytecodeGraphBuilder::VisitMul() {
1468   BuildBinaryOp(javascript()->Multiply(
1469       GetBinaryOperationHint(kBinaryOperationHintIndex)));
1470 }
1471 
VisitDiv()1472 void BytecodeGraphBuilder::VisitDiv() {
1473   BuildBinaryOp(
1474       javascript()->Divide(GetBinaryOperationHint(kBinaryOperationHintIndex)));
1475 }
1476 
VisitMod()1477 void BytecodeGraphBuilder::VisitMod() {
1478   BuildBinaryOp(
1479       javascript()->Modulus(GetBinaryOperationHint(kBinaryOperationHintIndex)));
1480 }
1481 
VisitBitwiseOr()1482 void BytecodeGraphBuilder::VisitBitwiseOr() {
1483   BuildBinaryOp(javascript()->BitwiseOr(
1484       GetBinaryOperationHint(kBinaryOperationHintIndex)));
1485 }
1486 
VisitBitwiseXor()1487 void BytecodeGraphBuilder::VisitBitwiseXor() {
1488   BuildBinaryOp(javascript()->BitwiseXor(
1489       GetBinaryOperationHint(kBinaryOperationHintIndex)));
1490 }
1491 
VisitBitwiseAnd()1492 void BytecodeGraphBuilder::VisitBitwiseAnd() {
1493   BuildBinaryOp(javascript()->BitwiseAnd(
1494       GetBinaryOperationHint(kBinaryOperationHintIndex)));
1495 }
1496 
VisitShiftLeft()1497 void BytecodeGraphBuilder::VisitShiftLeft() {
1498   BuildBinaryOp(javascript()->ShiftLeft(
1499       GetBinaryOperationHint(kBinaryOperationHintIndex)));
1500 }
1501 
VisitShiftRight()1502 void BytecodeGraphBuilder::VisitShiftRight() {
1503   BuildBinaryOp(javascript()->ShiftRight(
1504       GetBinaryOperationHint(kBinaryOperationHintIndex)));
1505 }
1506 
VisitShiftRightLogical()1507 void BytecodeGraphBuilder::VisitShiftRightLogical() {
1508   BuildBinaryOp(javascript()->ShiftRightLogical(
1509       GetBinaryOperationHint(kBinaryOperationHintIndex)));
1510 }
1511 
BuildBinaryOpWithImmediate(const Operator * js_op)1512 void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* js_op) {
1513   PrepareEagerCheckpoint();
1514   Node* left =
1515       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1516   Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
1517   Node* node = NewNode(js_op, left, right);
1518   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1519 }
1520 
VisitAddSmi()1521 void BytecodeGraphBuilder::VisitAddSmi() {
1522   BuildBinaryOpWithImmediate(
1523       javascript()->Add(GetBinaryOperationHint(kBinaryOperationSmiHintIndex)));
1524 }
1525 
VisitSubSmi()1526 void BytecodeGraphBuilder::VisitSubSmi() {
1527   BuildBinaryOpWithImmediate(javascript()->Subtract(
1528       GetBinaryOperationHint(kBinaryOperationSmiHintIndex)));
1529 }
1530 
VisitBitwiseOrSmi()1531 void BytecodeGraphBuilder::VisitBitwiseOrSmi() {
1532   BuildBinaryOpWithImmediate(javascript()->BitwiseOr(
1533       GetBinaryOperationHint(kBinaryOperationSmiHintIndex)));
1534 }
1535 
VisitBitwiseAndSmi()1536 void BytecodeGraphBuilder::VisitBitwiseAndSmi() {
1537   BuildBinaryOpWithImmediate(javascript()->BitwiseAnd(
1538       GetBinaryOperationHint(kBinaryOperationSmiHintIndex)));
1539 }
1540 
VisitShiftLeftSmi()1541 void BytecodeGraphBuilder::VisitShiftLeftSmi() {
1542   BuildBinaryOpWithImmediate(javascript()->ShiftLeft(
1543       GetBinaryOperationHint(kBinaryOperationSmiHintIndex)));
1544 }
1545 
VisitShiftRightSmi()1546 void BytecodeGraphBuilder::VisitShiftRightSmi() {
1547   BuildBinaryOpWithImmediate(javascript()->ShiftRight(
1548       GetBinaryOperationHint(kBinaryOperationSmiHintIndex)));
1549 }
1550 
VisitInc()1551 void BytecodeGraphBuilder::VisitInc() {
1552   PrepareEagerCheckpoint();
1553   // Note: Use subtract -1 here instead of add 1 to ensure we always convert to
1554   // a number, not a string.
1555   const Operator* js_op =
1556       javascript()->Subtract(GetBinaryOperationHint(kCountOperationHintIndex));
1557   Node* node = NewNode(js_op, environment()->LookupAccumulator(),
1558                        jsgraph()->Constant(-1));
1559   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1560 }
1561 
VisitDec()1562 void BytecodeGraphBuilder::VisitDec() {
1563   PrepareEagerCheckpoint();
1564   const Operator* js_op =
1565       javascript()->Subtract(GetBinaryOperationHint(kCountOperationHintIndex));
1566   Node* node = NewNode(js_op, environment()->LookupAccumulator(),
1567                        jsgraph()->OneConstant());
1568   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1569 }
1570 
VisitLogicalNot()1571 void BytecodeGraphBuilder::VisitLogicalNot() {
1572   Node* value = environment()->LookupAccumulator();
1573   Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value,
1574                        jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
1575   environment()->BindAccumulator(node);
1576 }
1577 
VisitToBooleanLogicalNot()1578 void BytecodeGraphBuilder::VisitToBooleanLogicalNot() {
1579   Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
1580                         environment()->LookupAccumulator());
1581   Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value,
1582                        jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
1583   environment()->BindAccumulator(node);
1584 }
1585 
VisitTypeOf()1586 void BytecodeGraphBuilder::VisitTypeOf() {
1587   Node* node =
1588       NewNode(javascript()->TypeOf(), environment()->LookupAccumulator());
1589   environment()->BindAccumulator(node);
1590 }
1591 
BuildDelete(LanguageMode language_mode)1592 void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) {
1593   PrepareEagerCheckpoint();
1594   Node* key = environment()->LookupAccumulator();
1595   Node* object =
1596       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1597   Node* node =
1598       NewNode(javascript()->DeleteProperty(language_mode), object, key);
1599   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1600 }
1601 
VisitDeletePropertyStrict()1602 void BytecodeGraphBuilder::VisitDeletePropertyStrict() {
1603   BuildDelete(LanguageMode::STRICT);
1604 }
1605 
VisitDeletePropertySloppy()1606 void BytecodeGraphBuilder::VisitDeletePropertySloppy() {
1607   BuildDelete(LanguageMode::SLOPPY);
1608 }
1609 
BuildCompareOp(const Operator * js_op)1610 void BytecodeGraphBuilder::BuildCompareOp(const Operator* js_op) {
1611   PrepareEagerCheckpoint();
1612   Node* left =
1613       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1614   Node* right = environment()->LookupAccumulator();
1615   Node* node = NewNode(js_op, left, right);
1616   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1617 }
1618 
VisitTestEqual()1619 void BytecodeGraphBuilder::VisitTestEqual() {
1620   BuildCompareOp(javascript()->Equal(GetCompareOperationHint()));
1621 }
1622 
VisitTestNotEqual()1623 void BytecodeGraphBuilder::VisitTestNotEqual() {
1624   BuildCompareOp(javascript()->NotEqual(GetCompareOperationHint()));
1625 }
1626 
VisitTestEqualStrict()1627 void BytecodeGraphBuilder::VisitTestEqualStrict() {
1628   BuildCompareOp(javascript()->StrictEqual(GetCompareOperationHint()));
1629 }
1630 
VisitTestLessThan()1631 void BytecodeGraphBuilder::VisitTestLessThan() {
1632   BuildCompareOp(javascript()->LessThan(GetCompareOperationHint()));
1633 }
1634 
VisitTestGreaterThan()1635 void BytecodeGraphBuilder::VisitTestGreaterThan() {
1636   BuildCompareOp(javascript()->GreaterThan(GetCompareOperationHint()));
1637 }
1638 
VisitTestLessThanOrEqual()1639 void BytecodeGraphBuilder::VisitTestLessThanOrEqual() {
1640   BuildCompareOp(javascript()->LessThanOrEqual(GetCompareOperationHint()));
1641 }
1642 
VisitTestGreaterThanOrEqual()1643 void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() {
1644   BuildCompareOp(javascript()->GreaterThanOrEqual(GetCompareOperationHint()));
1645 }
1646 
VisitTestIn()1647 void BytecodeGraphBuilder::VisitTestIn() {
1648   BuildCompareOp(javascript()->HasProperty());
1649 }
1650 
VisitTestInstanceOf()1651 void BytecodeGraphBuilder::VisitTestInstanceOf() {
1652   BuildCompareOp(javascript()->InstanceOf());
1653 }
1654 
BuildCastOperator(const Operator * js_op)1655 void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) {
1656   PrepareEagerCheckpoint();
1657   Node* value = NewNode(js_op, environment()->LookupAccumulator());
1658   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value,
1659                               Environment::kAttachFrameState);
1660 }
1661 
VisitToName()1662 void BytecodeGraphBuilder::VisitToName() {
1663   BuildCastOperator(javascript()->ToName());
1664 }
1665 
VisitToObject()1666 void BytecodeGraphBuilder::VisitToObject() {
1667   BuildCastOperator(javascript()->ToObject());
1668 }
1669 
VisitToNumber()1670 void BytecodeGraphBuilder::VisitToNumber() {
1671   BuildCastOperator(javascript()->ToNumber());
1672 }
1673 
VisitJump()1674 void BytecodeGraphBuilder::VisitJump() { BuildJump(); }
1675 
VisitJumpConstant()1676 void BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); }
1677 
VisitJumpIfTrue()1678 void BytecodeGraphBuilder::VisitJumpIfTrue() { BuildJumpIfTrue(); }
1679 
VisitJumpIfTrueConstant()1680 void BytecodeGraphBuilder::VisitJumpIfTrueConstant() { BuildJumpIfTrue(); }
1681 
VisitJumpIfFalse()1682 void BytecodeGraphBuilder::VisitJumpIfFalse() { BuildJumpIfFalse(); }
1683 
VisitJumpIfFalseConstant()1684 void BytecodeGraphBuilder::VisitJumpIfFalseConstant() { BuildJumpIfFalse(); }
1685 
VisitJumpIfToBooleanTrue()1686 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() {
1687   BuildJumpIfToBooleanTrue();
1688 }
1689 
VisitJumpIfToBooleanTrueConstant()1690 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() {
1691   BuildJumpIfToBooleanTrue();
1692 }
1693 
VisitJumpIfToBooleanFalse()1694 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() {
1695   BuildJumpIfToBooleanFalse();
1696 }
1697 
VisitJumpIfToBooleanFalseConstant()1698 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() {
1699   BuildJumpIfToBooleanFalse();
1700 }
1701 
VisitJumpIfNotHole()1702 void BytecodeGraphBuilder::VisitJumpIfNotHole() { BuildJumpIfNotHole(); }
1703 
VisitJumpIfNotHoleConstant()1704 void BytecodeGraphBuilder::VisitJumpIfNotHoleConstant() {
1705   BuildJumpIfNotHole();
1706 }
1707 
VisitJumpIfNull()1708 void BytecodeGraphBuilder::VisitJumpIfNull() {
1709   BuildJumpIfEqual(jsgraph()->NullConstant());
1710 }
1711 
VisitJumpIfNullConstant()1712 void BytecodeGraphBuilder::VisitJumpIfNullConstant() {
1713   BuildJumpIfEqual(jsgraph()->NullConstant());
1714 }
1715 
VisitJumpIfUndefined()1716 void BytecodeGraphBuilder::VisitJumpIfUndefined() {
1717   BuildJumpIfEqual(jsgraph()->UndefinedConstant());
1718 }
1719 
VisitJumpIfUndefinedConstant()1720 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() {
1721   BuildJumpIfEqual(jsgraph()->UndefinedConstant());
1722 }
1723 
VisitJumpLoop()1724 void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); }
1725 
VisitStackCheck()1726 void BytecodeGraphBuilder::VisitStackCheck() {
1727   PrepareEagerCheckpoint();
1728   Node* node = NewNode(javascript()->StackCheck());
1729   environment()->RecordAfterState(node, Environment::kAttachFrameState);
1730 }
1731 
VisitReturn()1732 void BytecodeGraphBuilder::VisitReturn() {
1733   BuildLoopExitsForFunctionExit();
1734   Node* pop_node = jsgraph()->ZeroConstant();
1735   Node* control =
1736       NewNode(common()->Return(), pop_node, environment()->LookupAccumulator());
1737   MergeControlToLeaveFunction(control);
1738 }
1739 
VisitDebugger()1740 void BytecodeGraphBuilder::VisitDebugger() {
1741   PrepareEagerCheckpoint();
1742   Node* call =
1743       NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
1744   environment()->BindAccumulator(call, Environment::kAttachFrameState);
1745   environment()->MarkAllRegistersLive();
1746 }
1747 
1748 // We cannot create a graph from the debugger copy of the bytecode array.
1749 #define DEBUG_BREAK(Name, ...) \
1750   void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); }
1751 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
1752 #undef DEBUG_BREAK
1753 
BuildForInPrepare()1754 void BytecodeGraphBuilder::BuildForInPrepare() {
1755   PrepareEagerCheckpoint();
1756   Node* receiver =
1757       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1758   Node* prepare = NewNode(javascript()->ForInPrepare(), receiver);
1759   environment()->BindRegistersToProjections(
1760       bytecode_iterator().GetRegisterOperand(1), prepare,
1761       Environment::kAttachFrameState);
1762 }
1763 
VisitForInPrepare()1764 void BytecodeGraphBuilder::VisitForInPrepare() { BuildForInPrepare(); }
1765 
VisitForInContinue()1766 void BytecodeGraphBuilder::VisitForInContinue() {
1767   PrepareEagerCheckpoint();
1768   Node* index =
1769       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1770   Node* cache_length =
1771       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1772   Node* exit_cond =
1773       NewNode(javascript()->LessThan(CompareOperationHint::kSignedSmall), index,
1774               cache_length);
1775   environment()->BindAccumulator(exit_cond, Environment::kAttachFrameState);
1776 }
1777 
BuildForInNext()1778 void BytecodeGraphBuilder::BuildForInNext() {
1779   PrepareEagerCheckpoint();
1780   Node* receiver =
1781       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1782   Node* index =
1783       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1784   int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index();
1785   Node* cache_type = environment()->LookupRegister(
1786       interpreter::Register(catch_reg_pair_index));
1787   Node* cache_array = environment()->LookupRegister(
1788       interpreter::Register(catch_reg_pair_index + 1));
1789 
1790   Node* value = NewNode(javascript()->ForInNext(), receiver, cache_array,
1791                         cache_type, index);
1792   environment()->BindAccumulator(value, Environment::kAttachFrameState);
1793 }
1794 
VisitForInNext()1795 void BytecodeGraphBuilder::VisitForInNext() { BuildForInNext(); }
1796 
VisitForInStep()1797 void BytecodeGraphBuilder::VisitForInStep() {
1798   PrepareEagerCheckpoint();
1799   Node* index =
1800       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1801   index = NewNode(javascript()->Add(BinaryOperationHint::kSignedSmall), index,
1802                   jsgraph()->OneConstant());
1803   environment()->BindAccumulator(index, Environment::kAttachFrameState);
1804 }
1805 
VisitSuspendGenerator()1806 void BytecodeGraphBuilder::VisitSuspendGenerator() {
1807   Node* state = environment()->LookupAccumulator();
1808   Node* generator = environment()->LookupRegister(
1809       bytecode_iterator().GetRegisterOperand(0));
1810   // The offsets used by the bytecode iterator are relative to a different base
1811   // than what is used in the interpreter, hence the addition.
1812   Node* offset =
1813       jsgraph()->Constant(bytecode_iterator().current_offset() +
1814                           (BytecodeArray::kHeaderSize - kHeapObjectTag));
1815 
1816   int register_count = environment()->register_count();
1817   int value_input_count = 3 + register_count;
1818 
1819   Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count);
1820   value_inputs[0] = generator;
1821   value_inputs[1] = state;
1822   value_inputs[2] = offset;
1823   for (int i = 0; i < register_count; ++i) {
1824     value_inputs[3 + i] =
1825         environment()->LookupRegister(interpreter::Register(i));
1826   }
1827 
1828   MakeNode(javascript()->GeneratorStore(register_count), value_input_count,
1829            value_inputs, false);
1830 }
1831 
VisitResumeGenerator()1832 void BytecodeGraphBuilder::VisitResumeGenerator() {
1833   PrepareEagerCheckpoint();
1834 
1835   Node* generator = environment()->LookupRegister(
1836       bytecode_iterator().GetRegisterOperand(0));
1837 
1838   // Bijection between registers and array indices must match that used in
1839   // InterpreterAssembler::ExportRegisterFile.
1840   for (int i = 0; i < environment()->register_count(); ++i) {
1841     Node* value = NewNode(javascript()->GeneratorRestoreRegister(i), generator);
1842     environment()->BindRegister(interpreter::Register(i), value);
1843   }
1844 
1845   Node* state =
1846       NewNode(javascript()->GeneratorRestoreContinuation(), generator);
1847 
1848   environment()->BindAccumulator(state, Environment::kAttachFrameState);
1849 }
1850 
VisitWide()1851 void BytecodeGraphBuilder::VisitWide() {
1852   // Consumed by the BytecodeArrayIterator.
1853   UNREACHABLE();
1854 }
1855 
VisitExtraWide()1856 void BytecodeGraphBuilder::VisitExtraWide() {
1857   // Consumed by the BytecodeArrayIterator.
1858   UNREACHABLE();
1859 }
1860 
VisitIllegal()1861 void BytecodeGraphBuilder::VisitIllegal() {
1862   // Not emitted in valid bytecode.
1863   UNREACHABLE();
1864 }
1865 
VisitNop()1866 void BytecodeGraphBuilder::VisitNop() {}
1867 
SwitchToMergeEnvironment(int current_offset)1868 void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) {
1869   if (merge_environments_[current_offset] != nullptr) {
1870     if (environment() != nullptr) {
1871       merge_environments_[current_offset]->Merge(environment());
1872     }
1873     set_environment(merge_environments_[current_offset]);
1874   }
1875 }
1876 
BuildLoopHeaderEnvironment(int current_offset)1877 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) {
1878   if (branch_analysis()->backward_branches_target(current_offset)) {
1879     // Add loop header and store a copy so we can connect merged back
1880     // edge inputs to the loop header.
1881     merge_environments_[current_offset] = environment()->CopyForLoop();
1882   }
1883 }
1884 
MergeIntoSuccessorEnvironment(int target_offset)1885 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) {
1886   BuildLoopExitsForBranch(target_offset);
1887   if (merge_environments_[target_offset] == nullptr) {
1888     // Append merge nodes to the environment. We may merge here with another
1889     // environment. So add a place holder for merge nodes. We may add redundant
1890     // but will be eliminated in a later pass.
1891     // TODO(mstarzinger): Be smarter about this!
1892     NewMerge();
1893     merge_environments_[target_offset] = environment();
1894   } else {
1895     merge_environments_[target_offset]->Merge(environment());
1896   }
1897   set_environment(nullptr);
1898 }
1899 
MergeControlToLeaveFunction(Node * exit)1900 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) {
1901   exit_controls_.push_back(exit);
1902   set_environment(nullptr);
1903 }
1904 
BuildOSRLoopEntryPoint(int current_offset)1905 void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) {
1906   if (!osr_ast_id_.IsNone() && osr_ast_id_.ToInt() == current_offset) {
1907     // For OSR add a special {OsrLoopEntry} node into the current loop header.
1908     // It will be turned into a usable entry by the OSR deconstruction.
1909     Environment* loop_env = merge_environments_[current_offset];
1910     Environment* osr_env = loop_env->CopyForOsrEntry();
1911     osr_env->PrepareForOsrEntry();
1912     loop_env->Merge(osr_env);
1913   }
1914 }
1915 
BuildOSRNormalEntryPoint()1916 void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() {
1917   if (!osr_ast_id_.IsNone()) {
1918     // For OSR add an {OsrNormalEntry} as the the top-level environment start.
1919     // It will be replaced with {Dead} by the OSR deconstruction.
1920     NewNode(common()->OsrNormalEntry());
1921     // Note that the requested OSR entry point must be the target of a backward
1922     // branch, otherwise there will not be a proper loop header available.
1923     DCHECK(branch_analysis()->backward_branches_target(osr_ast_id_.ToInt()));
1924   }
1925 }
1926 
BuildLoopExitsForBranch(int target_offset)1927 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) {
1928   int origin_offset = bytecode_iterator().current_offset();
1929   // Only build loop exits for forward edges.
1930   if (target_offset > origin_offset) {
1931     BuildLoopExitsUntilLoop(loop_analysis()->GetLoopOffsetFor(target_offset));
1932   }
1933 }
1934 
BuildLoopExitsUntilLoop(int loop_offset)1935 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) {
1936   int origin_offset = bytecode_iterator().current_offset();
1937   int current_loop = loop_analysis()->GetLoopOffsetFor(origin_offset);
1938   while (loop_offset < current_loop) {
1939     Node* loop_node = merge_environments_[current_loop]->GetControlDependency();
1940     environment()->PrepareForLoopExit(loop_node);
1941     current_loop = loop_analysis()->GetParentLoopFor(current_loop);
1942   }
1943 }
1944 
BuildLoopExitsForFunctionExit()1945 void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit() {
1946   BuildLoopExitsUntilLoop(-1);
1947 }
1948 
BuildJump()1949 void BytecodeGraphBuilder::BuildJump() {
1950   MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
1951 }
1952 
BuildJumpIf(Node * condition)1953 void BytecodeGraphBuilder::BuildJumpIf(Node* condition) {
1954   NewBranch(condition);
1955   Environment* if_false_environment = environment()->CopyForConditional();
1956   NewIfTrue();
1957   MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
1958   set_environment(if_false_environment);
1959   NewIfFalse();
1960 }
1961 
BuildJumpIfNot(Node * condition)1962 void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) {
1963   NewBranch(condition);
1964   Environment* if_true_environment = environment()->CopyForConditional();
1965   NewIfFalse();
1966   MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
1967   set_environment(if_true_environment);
1968   NewIfTrue();
1969 }
1970 
BuildJumpIfEqual(Node * comperand)1971 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
1972   Node* accumulator = environment()->LookupAccumulator();
1973   Node* condition =
1974       NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
1975               accumulator, comperand);
1976   BuildJumpIf(condition);
1977 }
1978 
BuildJumpIfFalse()1979 void BytecodeGraphBuilder::BuildJumpIfFalse() {
1980   BuildJumpIfNot(environment()->LookupAccumulator());
1981 }
1982 
BuildJumpIfTrue()1983 void BytecodeGraphBuilder::BuildJumpIfTrue() {
1984   BuildJumpIf(environment()->LookupAccumulator());
1985 }
1986 
BuildJumpIfToBooleanTrue()1987 void BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() {
1988   Node* accumulator = environment()->LookupAccumulator();
1989   Node* condition =
1990       NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator);
1991   BuildJumpIf(condition);
1992 }
1993 
BuildJumpIfToBooleanFalse()1994 void BytecodeGraphBuilder::BuildJumpIfToBooleanFalse() {
1995   Node* accumulator = environment()->LookupAccumulator();
1996   Node* condition =
1997       NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator);
1998   BuildJumpIfNot(condition);
1999 }
2000 
BuildJumpIfNotHole()2001 void BytecodeGraphBuilder::BuildJumpIfNotHole() {
2002   Node* accumulator = environment()->LookupAccumulator();
2003   Node* condition =
2004       NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
2005               accumulator, jsgraph()->TheHoleConstant());
2006   BuildJumpIfNot(condition);
2007 }
2008 
EnsureInputBufferSize(int size)2009 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
2010   if (size > input_buffer_size_) {
2011     size = size + kInputBufferSizeIncrement + input_buffer_size_;
2012     input_buffer_ = local_zone()->NewArray<Node*>(size);
2013     input_buffer_size_ = size;
2014   }
2015   return input_buffer_;
2016 }
2017 
EnterAndExitExceptionHandlers(int current_offset)2018 void BytecodeGraphBuilder::EnterAndExitExceptionHandlers(int current_offset) {
2019   Handle<HandlerTable> table = exception_handler_table();
2020   int num_entries = table->NumberOfRangeEntries();
2021 
2022   // Potentially exit exception handlers.
2023   while (!exception_handlers_.empty()) {
2024     int current_end = exception_handlers_.top().end_offset_;
2025     if (current_offset < current_end) break;  // Still covered by range.
2026     exception_handlers_.pop();
2027   }
2028 
2029   // Potentially enter exception handlers.
2030   while (current_exception_handler_ < num_entries) {
2031     int next_start = table->GetRangeStart(current_exception_handler_);
2032     if (current_offset < next_start) break;  // Not yet covered by range.
2033     int next_end = table->GetRangeEnd(current_exception_handler_);
2034     int next_handler = table->GetRangeHandler(current_exception_handler_);
2035     int context_register = table->GetRangeData(current_exception_handler_);
2036     exception_handlers_.push(
2037         {next_start, next_end, next_handler, context_register});
2038     current_exception_handler_++;
2039   }
2040 }
2041 
MakeNode(const Operator * op,int value_input_count,Node ** value_inputs,bool incomplete)2042 Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
2043                                      Node** value_inputs, bool incomplete) {
2044   DCHECK_EQ(op->ValueInputCount(), value_input_count);
2045 
2046   bool has_context = OperatorProperties::HasContextInput(op);
2047   bool has_frame_state = OperatorProperties::HasFrameStateInput(op);
2048   bool has_control = op->ControlInputCount() == 1;
2049   bool has_effect = op->EffectInputCount() == 1;
2050 
2051   DCHECK_LT(op->ControlInputCount(), 2);
2052   DCHECK_LT(op->EffectInputCount(), 2);
2053 
2054   Node* result = nullptr;
2055   if (!has_context && !has_frame_state && !has_control && !has_effect) {
2056     result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
2057   } else {
2058     bool inside_handler = !exception_handlers_.empty();
2059     int input_count_with_deps = value_input_count;
2060     if (has_context) ++input_count_with_deps;
2061     if (has_frame_state) ++input_count_with_deps;
2062     if (has_control) ++input_count_with_deps;
2063     if (has_effect) ++input_count_with_deps;
2064     Node** buffer = EnsureInputBufferSize(input_count_with_deps);
2065     memcpy(buffer, value_inputs, kPointerSize * value_input_count);
2066     Node** current_input = buffer + value_input_count;
2067     if (has_context) {
2068       *current_input++ = environment()->Context();
2069     }
2070     if (has_frame_state) {
2071       // The frame state will be inserted later. Here we misuse the {Dead} node
2072       // as a sentinel to be later overwritten with the real frame state by the
2073       // calls to {PrepareFrameState} within individual visitor methods.
2074       *current_input++ = jsgraph()->Dead();
2075     }
2076     if (has_effect) {
2077       *current_input++ = environment()->GetEffectDependency();
2078     }
2079     if (has_control) {
2080       *current_input++ = environment()->GetControlDependency();
2081     }
2082     result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
2083     // Update the current control dependency for control-producing nodes.
2084     if (NodeProperties::IsControl(result)) {
2085       environment()->UpdateControlDependency(result);
2086     }
2087     // Update the current effect dependency for effect-producing nodes.
2088     if (result->op()->EffectOutputCount() > 0) {
2089       environment()->UpdateEffectDependency(result);
2090     }
2091     // Add implicit exception continuation for throwing nodes.
2092     if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
2093       int handler_offset = exception_handlers_.top().handler_offset_;
2094       int context_index = exception_handlers_.top().context_register_;
2095       interpreter::Register context_register(context_index);
2096       Environment* success_env = environment()->CopyForConditional();
2097       const Operator* op = common()->IfException();
2098       Node* effect = environment()->GetEffectDependency();
2099       Node* on_exception = graph()->NewNode(op, effect, result);
2100       Node* context = environment()->LookupRegister(context_register);
2101       environment()->UpdateControlDependency(on_exception);
2102       environment()->UpdateEffectDependency(on_exception);
2103       environment()->BindAccumulator(on_exception);
2104       environment()->SetContext(context);
2105       MergeIntoSuccessorEnvironment(handler_offset);
2106       set_environment(success_env);
2107     }
2108     // Add implicit success continuation for throwing nodes.
2109     if (!result->op()->HasProperty(Operator::kNoThrow)) {
2110       const Operator* if_success = common()->IfSuccess();
2111       Node* on_success = graph()->NewNode(if_success, result);
2112       environment()->UpdateControlDependency(on_success);
2113     }
2114   }
2115 
2116   return result;
2117 }
2118 
2119 
NewPhi(int count,Node * input,Node * control)2120 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) {
2121   const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
2122   Node** buffer = EnsureInputBufferSize(count + 1);
2123   MemsetPointer(buffer, input, count);
2124   buffer[count] = control;
2125   return graph()->NewNode(phi_op, count + 1, buffer, true);
2126 }
2127 
2128 
NewEffectPhi(int count,Node * input,Node * control)2129 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input,
2130                                          Node* control) {
2131   const Operator* phi_op = common()->EffectPhi(count);
2132   Node** buffer = EnsureInputBufferSize(count + 1);
2133   MemsetPointer(buffer, input, count);
2134   buffer[count] = control;
2135   return graph()->NewNode(phi_op, count + 1, buffer, true);
2136 }
2137 
2138 
MergeControl(Node * control,Node * other)2139 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
2140   int inputs = control->op()->ControlInputCount() + 1;
2141   if (control->opcode() == IrOpcode::kLoop) {
2142     // Control node for loop exists, add input.
2143     const Operator* op = common()->Loop(inputs);
2144     control->AppendInput(graph_zone(), other);
2145     NodeProperties::ChangeOp(control, op);
2146   } else if (control->opcode() == IrOpcode::kMerge) {
2147     // Control node for merge exists, add input.
2148     const Operator* op = common()->Merge(inputs);
2149     control->AppendInput(graph_zone(), other);
2150     NodeProperties::ChangeOp(control, op);
2151   } else {
2152     // Control node is a singleton, introduce a merge.
2153     const Operator* op = common()->Merge(inputs);
2154     Node* merge_inputs[] = {control, other};
2155     control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true);
2156   }
2157   return control;
2158 }
2159 
2160 
MergeEffect(Node * value,Node * other,Node * control)2161 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
2162                                         Node* control) {
2163   int inputs = control->op()->ControlInputCount();
2164   if (value->opcode() == IrOpcode::kEffectPhi &&
2165       NodeProperties::GetControlInput(value) == control) {
2166     // Phi already exists, add input.
2167     value->InsertInput(graph_zone(), inputs - 1, other);
2168     NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
2169   } else if (value != other) {
2170     // Phi does not exist yet, introduce one.
2171     value = NewEffectPhi(inputs, value, control);
2172     value->ReplaceInput(inputs - 1, other);
2173   }
2174   return value;
2175 }
2176 
2177 
MergeValue(Node * value,Node * other,Node * control)2178 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
2179                                        Node* control) {
2180   int inputs = control->op()->ControlInputCount();
2181   if (value->opcode() == IrOpcode::kPhi &&
2182       NodeProperties::GetControlInput(value) == control) {
2183     // Phi already exists, add input.
2184     value->InsertInput(graph_zone(), inputs - 1, other);
2185     NodeProperties::ChangeOp(
2186         value, common()->Phi(MachineRepresentation::kTagged, inputs));
2187   } else if (value != other) {
2188     // Phi does not exist yet, introduce one.
2189     value = NewPhi(inputs, value, control);
2190     value->ReplaceInput(inputs - 1, other);
2191   }
2192   return value;
2193 }
2194 
UpdateCurrentSourcePosition(SourcePositionTableIterator * it,int offset)2195 void BytecodeGraphBuilder::UpdateCurrentSourcePosition(
2196     SourcePositionTableIterator* it, int offset) {
2197   if (it->done()) return;
2198 
2199   if (it->code_offset() == offset) {
2200     source_positions_->SetCurrentPosition(SourcePosition(
2201         it->source_position().ScriptOffset(), start_position_.InliningId()));
2202     it->Advance();
2203   } else {
2204     DCHECK_GT(it->code_offset(), offset);
2205   }
2206 }
2207 
2208 }  // namespace compiler
2209 }  // namespace internal
2210 }  // namespace v8
2211