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