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/base/platform/wrappers.h"
9 #include "src/codegen/source-position-table.h"
10 #include "src/codegen/tick-counter.h"
11 #include "src/common/assert-scope.h"
12 #include "src/compiler/access-builder.h"
13 #include "src/compiler/bytecode-analysis.h"
14 #include "src/compiler/common-operator.h"
15 #include "src/compiler/compiler-source-position-table.h"
16 #include "src/compiler/js-heap-broker.h"
17 #include "src/compiler/linkage.h"
18 #include "src/compiler/node-matchers.h"
19 #include "src/compiler/node-observer.h"
20 #include "src/compiler/operator-properties.h"
21 #include "src/compiler/simplified-operator.h"
22 #include "src/compiler/state-values-utils.h"
23 #include "src/interpreter/bytecode-array-iterator.h"
24 #include "src/interpreter/bytecode-flags.h"
25 #include "src/interpreter/bytecodes.h"
26 #include "src/objects/js-array-inl.h"
27 #include "src/objects/js-generator.h"
28 #include "src/objects/literal-objects-inl.h"
29 #include "src/objects/objects-inl.h"
30 #include "src/objects/smi.h"
31 #include "src/objects/template-objects-inl.h"
32 
33 namespace v8 {
34 namespace internal {
35 namespace compiler {
36 
37 class BytecodeGraphBuilder {
38  public:
39   BytecodeGraphBuilder(JSHeapBroker* broker, Zone* local_zone,
40                        NativeContextRef const& native_context,
41                        SharedFunctionInfoRef const& shared_info,
42                        FeedbackCellRef const& feedback_cell,
43                        BytecodeOffset osr_offset, JSGraph* jsgraph,
44                        CallFrequency const& invocation_frequency,
45                        SourcePositionTable* source_positions, int inlining_id,
46                        CodeKind code_kind, BytecodeGraphBuilderFlags flags,
47                        TickCounter* tick_counter,
48                        ObserveNodeInfo const& observe_node_info);
49 
50   BytecodeGraphBuilder(const BytecodeGraphBuilder&) = delete;
51   BytecodeGraphBuilder& operator=(const BytecodeGraphBuilder&) = delete;
52 
53   // Creates a graph by visiting bytecodes.
54   void CreateGraph();
55 
56  private:
57   class Environment;
58   class OsrIteratorState;
59   struct SubEnvironment;
60 
61   void RemoveMergeEnvironmentsBeforeOffset(int limit_offset);
62   void AdvanceToOsrEntryAndPeelLoops();
63 
64   // Advance {bytecode_iterator} to the given offset. If possible, also advance
65   // {source_position_iterator} while updating the source position table.
66   void AdvanceIteratorsTo(int bytecode_offset);
67 
68   void VisitSingleBytecode();
69   void VisitBytecodes();
70 
71   // Get or create the node that represents the outer function closure.
72   Node* GetFunctionClosure();
73 
74   // Get or create the node for this parameter index. If such a node is
75   // already cached, it is returned directly and the {debug_name_hint} is
76   // ignored.
77   Node* GetParameter(int index, const char* debug_name_hint = nullptr);
78 
code_kind() const79   CodeKind code_kind() const { return code_kind_; }
80 
81   // The node representing the current feedback vector is generated once prior
82   // to visiting bytecodes, and is later passed as input to other nodes that
83   // may need it.
84   // TODO(jgruber): Remove feedback_vector() and rename feedback_vector_node()
85   // to feedback_vector() once all uses of the direct heap object reference
86   // have been replaced with a Node* reference.
87   void CreateFeedbackVectorNode();
feedback_vector_node() const88   Node* feedback_vector_node() const {
89     DCHECK_NOT_NULL(feedback_vector_node_);
90     return feedback_vector_node_;
91   }
92 
93   // Same as above for the feedback vector node.
94   void CreateNativeContextNode();
native_context_node() const95   Node* native_context_node() const {
96     DCHECK_NOT_NULL(native_context_node_);
97     return native_context_node_;
98   }
99 
100   Node* BuildLoadFeedbackCell(int index);
101 
102   // Builder for loading a native context field.
103   Node* BuildLoadNativeContextField(int index);
104 
105   // Helper function for creating a feedback source containing type feedback
106   // vector and a feedback slot.
107   FeedbackSource CreateFeedbackSource(int slot_id);
108   FeedbackSource CreateFeedbackSource(FeedbackSlot slot);
109 
set_environment(Environment* env)110   void set_environment(Environment* env) { environment_ = env; }
environment() const111   const Environment* environment() const { return environment_; }
environment()112   Environment* environment() { return environment_; }
113 
114   // Node creation helpers
NewNode(const Operator* op, bool incomplete = false)115   Node* NewNode(const Operator* op, bool incomplete = false) {
116     return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete);
117   }
118 
119   template <class... Args>
NewNode(const Operator* op, Node* n0, Args... nodes)120   Node* NewNode(const Operator* op, Node* n0, Args... nodes) {
121     Node* buffer[] = {n0, nodes...};
122     return MakeNode(op, arraysize(buffer), buffer);
123   }
124 
125   // Helpers to create new control nodes.
NewIfTrue()126   Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
NewIfFalse()127   Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
NewIfValue(int32_t value)128   Node* NewIfValue(int32_t value) { return NewNode(common()->IfValue(value)); }
NewIfDefault()129   Node* NewIfDefault() { return NewNode(common()->IfDefault()); }
NewMerge()130   Node* NewMerge() { return NewNode(common()->Merge(1), true); }
NewLoop()131   Node* NewLoop() { return NewNode(common()->Loop(1), true); }
NewBranch(Node* condition, BranchHint hint = BranchHint::kNone)132   Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) {
133     return NewNode(common()->Branch(hint), condition);
134   }
NewSwitch(Node* condition, int control_output_count)135   Node* NewSwitch(Node* condition, int control_output_count) {
136     return NewNode(common()->Switch(control_output_count), condition);
137   }
138 
139   // Creates a new Phi node having {count} input values.
140   Node* NewPhi(int count, Node* input, Node* control);
141   Node* NewEffectPhi(int count, Node* input, Node* control);
142 
143   // Helpers for merging control, effect or value dependencies.
144   Node* MergeControl(Node* control, Node* other);
145   Node* MergeEffect(Node* effect, Node* other_effect, Node* control);
146   Node* MergeValue(Node* value, Node* other_value, Node* control);
147 
148   // The main node creation chokepoint. Adds context, frame state, effect,
149   // and control dependencies depending on the operator.
150   Node* MakeNode(const Operator* op, int value_input_count,
151                  Node* const* value_inputs, bool incomplete = false);
152 
153   Node** EnsureInputBufferSize(int size);
154 
155   Node* const* GetCallArgumentsFromRegisters(Node* callee, Node* receiver,
156                                               interpreter::Register first_arg,
157                                               int arg_count);
158   Node* const* ProcessCallVarArgs(ConvertReceiverMode receiver_mode,
159                                   Node* callee, interpreter::Register first_reg,
160                                   int arg_count);
161   Node* const* GetConstructArgumentsFromRegister(
162       Node* target, Node* new_target, interpreter::Register first_arg,
163       int arg_count);
164   Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op,
165                                     interpreter::Register receiver,
166                                     size_t reg_count);
167 
168   // Prepare information for eager deoptimization. This information is carried
169   // by dedicated {Checkpoint} nodes that are wired into the effect chain.
170   // Conceptually this frame state is "before" a given operation.
171   void PrepareEagerCheckpoint();
172 
173   // Prepare information for lazy deoptimization. This information is attached
174   // to the given node and the output value produced by the node is combined.
175   //
176   // The low-level chokepoint - use the variants below instead.
177   void PrepareFrameState(Node* node, OutputFrameStateCombine combine,
178                          BytecodeOffset bailout_id,
179                          const BytecodeLivenessState* liveness);
180 
181   // In the common case, frame states are conceptually "after" a given
182   // operation and at the current bytecode offset.
PrepareFrameState(Node* node, OutputFrameStateCombine combine)183   void PrepareFrameState(Node* node, OutputFrameStateCombine combine) {
184     if (!OperatorProperties::HasFrameStateInput(node->op())) return;
185     const int offset = bytecode_iterator().current_offset();
186     return PrepareFrameState(node, combine, BytecodeOffset(offset),
187                              bytecode_analysis().GetOutLivenessFor(offset));
188   }
189 
190   // For function-entry stack checks, they're conceptually "before" the first
191   // bytecode and at a special marker bytecode offset.
192   // In the case of FE stack checks, the current bytecode is also the first
193   // bytecode, so we use a special marker bytecode offset to signify a virtual
194   // bytecode before the first physical bytecode.
PrepareFrameStateForFunctionEntryStackCheck(Node* node)195   void PrepareFrameStateForFunctionEntryStackCheck(Node* node) {
196     DCHECK_EQ(bytecode_iterator().current_offset(), 0);
197     DCHECK(OperatorProperties::HasFrameStateInput(node->op()));
198     DCHECK(node->opcode() == IrOpcode::kJSStackCheck);
199     return PrepareFrameState(node, OutputFrameStateCombine::Ignore(),
200                              BytecodeOffset(kFunctionEntryBytecodeOffset),
201                              bytecode_analysis().GetInLivenessFor(0));
202   }
203 
204   // For OSR-entry stack checks, they're conceptually "before" the first
205   // bytecode of the current loop. We implement this in a similar manner to
206   // function-entry (FE) stack checks above, i.e. we deopt at the predecessor
207   // of the current bytecode.
208   // In the case of OSR-entry stack checks, a physical predecessor bytecode
209   // exists: the JumpLoop bytecode. We attach to JumpLoop by using
210   // `bytecode_analysis().osr_bailout_id()` instead of current_offset (the
211   // former points at JumpLoop, the latter at the loop header, i.e. the target
212   // of JumpLoop).
PrepareFrameStateForOSREntryStackCheck(Node* node)213   void PrepareFrameStateForOSREntryStackCheck(Node* node) {
214     DCHECK(OperatorProperties::HasFrameStateInput(node->op()));
215     DCHECK(node->opcode() == IrOpcode::kJSStackCheck);
216     const int offset = bytecode_analysis().osr_bailout_id().ToInt();
217     return PrepareFrameState(node, OutputFrameStateCombine::Ignore(),
218                              BytecodeOffset(offset),
219                              bytecode_analysis().GetOutLivenessFor(offset));
220   }
221 
222   void BuildCreateArguments(CreateArgumentsType type);
223   Node* BuildLoadGlobal(NameRef name, uint32_t feedback_slot_index,
224                         TypeofMode typeof_mode);
225 
226   enum class NamedStoreMode {
227     // Check the prototype chain before storing.
228     kSet,
229     // Define value to the receiver without checking the prototype chain.
230     kDefineOwn,
231   };
232   void BuildNamedStore(NamedStoreMode store_mode);
233   void BuildLdaLookupSlot(TypeofMode typeof_mode);
234   void BuildLdaLookupContextSlot(TypeofMode typeof_mode);
235   void BuildLdaLookupGlobalSlot(TypeofMode typeof_mode);
236   void BuildCallVarArgs(ConvertReceiverMode receiver_mode);
237   void BuildCall(ConvertReceiverMode receiver_mode, Node* const* args,
238                  size_t arg_count, int slot_id);
BuildCall(ConvertReceiverMode receiver_mode, std::initializer_list<Node*> args, int slot_id)239   void BuildCall(ConvertReceiverMode receiver_mode,
240                  std::initializer_list<Node*> args, int slot_id) {
241     BuildCall(receiver_mode, args.begin(), args.size(), slot_id);
242   }
243   void BuildUnaryOp(const Operator* op);
244   void BuildBinaryOp(const Operator* op);
245   void BuildBinaryOpWithImmediate(const Operator* op);
246   void BuildCompareOp(const Operator* op);
247   void BuildDelete(LanguageMode language_mode);
248   void BuildCastOperator(const Operator* op);
249   void BuildHoleCheckAndThrow(Node* condition, Runtime::FunctionId runtime_id,
250                               Node* name = nullptr);
251 
252   // Optional early lowering to the simplified operator level.  Note that
253   // the result has already been wired into the environment just like
254   // any other invocation of {NewNode} would do.
255   JSTypeHintLowering::LoweringResult TryBuildSimplifiedUnaryOp(
256       const Operator* op, Node* operand, FeedbackSlot slot);
257   JSTypeHintLowering::LoweringResult TryBuildSimplifiedBinaryOp(
258       const Operator* op, Node* left, Node* right, FeedbackSlot slot);
259   JSTypeHintLowering::LoweringResult TryBuildSimplifiedForInNext(
260       Node* receiver, Node* cache_array, Node* cache_type, Node* index,
261       FeedbackSlot slot);
262   JSTypeHintLowering::LoweringResult TryBuildSimplifiedForInPrepare(
263       Node* receiver, FeedbackSlot slot);
264   JSTypeHintLowering::LoweringResult TryBuildSimplifiedToNumber(
265       Node* input, FeedbackSlot slot);
266   JSTypeHintLowering::LoweringResult TryBuildSimplifiedCall(const Operator* op,
267                                                             Node* const* args,
268                                                             int arg_count,
269                                                             FeedbackSlot slot);
270   JSTypeHintLowering::LoweringResult TryBuildSimplifiedConstruct(
271       const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot);
272   JSTypeHintLowering::LoweringResult TryBuildSimplifiedGetIterator(
273       const Operator* op, Node* receiver, FeedbackSlot load_slot,
274       FeedbackSlot call_slot);
275   JSTypeHintLowering::LoweringResult TryBuildSimplifiedLoadNamed(
276       const Operator* op, FeedbackSlot slot);
277   JSTypeHintLowering::LoweringResult TryBuildSimplifiedLoadKeyed(
278       const Operator* op, Node* receiver, Node* key, FeedbackSlot slot);
279   JSTypeHintLowering::LoweringResult TryBuildSimplifiedStoreNamed(
280       const Operator* op, Node* receiver, Node* value, FeedbackSlot slot);
281   JSTypeHintLowering::LoweringResult TryBuildSimplifiedStoreKeyed(
282       const Operator* op, Node* receiver, Node* key, Node* value,
283       FeedbackSlot slot);
284 
285   // Applies the given early reduction onto the current environment.
286   void ApplyEarlyReduction(JSTypeHintLowering::LoweringResult reduction);
287 
288   // Check the context chain for extensions, for lookup fast paths.
289   Environment* CheckContextExtensions(uint32_t depth);
290   // Slow path taken when we cannot figure out the current scope info.
291   Environment* CheckContextExtensionsSlowPath(uint32_t depth);
292   // Helper function that tries to get the current scope info.
293   base::Optional<ScopeInfoRef> TryGetScopeInfo();
294   // Helper function to create a context extension check.
295   Environment* CheckContextExtensionAtDepth(Environment* slow_environment,
296                                             uint32_t depth);
297 
298   // Helper function to create for-in mode from the recorded type feedback.
299   ForInMode GetForInMode(FeedbackSlot slot);
300 
301   // Helper function to compute call frequency from the recorded type
302   // feedback. Returns unknown if invocation count is unknown. Returns 0 if
303   // feedback is insufficient.
304   CallFrequency ComputeCallFrequency(int slot_id) const;
305 
306   // Helper function to extract the speculation mode from the recorded type
307   // feedback. Returns kDisallowSpeculation if feedback is insufficient.
308   SpeculationMode GetSpeculationMode(int slot_id) const;
309 
310   // Helper function to determine the call feedback relation from the recorded
311   // type feedback. Returns kUnrelated if feedback is insufficient.
312   CallFeedbackRelation ComputeCallFeedbackRelation(int slot_id) const;
313 
314   // Helpers for building the implicit FunctionEntry and IterationBody
315   // StackChecks.
316   void BuildFunctionEntryStackCheck();
317   void BuildIterationBodyStackCheck();
318   void BuildOSREntryStackCheck();
319 
320   // Control flow plumbing.
321   void BuildJump();
322   void BuildJumpIf(Node* condition);
323   void BuildJumpIfNot(Node* condition);
324   void BuildJumpIfEqual(Node* comperand);
325   void BuildJumpIfNotEqual(Node* comperand);
326   void BuildJumpIfTrue();
327   void BuildJumpIfFalse();
328   void BuildJumpIfToBooleanTrue();
329   void BuildJumpIfToBooleanFalse();
330   void BuildJumpIfNotHole();
331   void BuildJumpIfJSReceiver();
332 
333   void BuildSwitchOnSmi(Node* condition);
334   void BuildSwitchOnGeneratorState(
335       const ZoneVector<ResumeJumpTarget>& resume_jump_targets,
336       bool allow_fallthrough_on_executing);
337 
338   // Simulates control flow by forward-propagating environments.
339   void MergeIntoSuccessorEnvironment(int target_offset);
340   void BuildLoopHeaderEnvironment(int current_offset);
341   void SwitchToMergeEnvironment(int current_offset);
342 
343   // Simulates control flow that exits the function body.
344   void MergeControlToLeaveFunction(Node* exit);
345 
346   // Builds loop exit nodes for every exited loop between the current bytecode
347   // offset and {target_offset}.
348   void BuildLoopExitsForBranch(int target_offset);
349   void BuildLoopExitsForFunctionExit(const BytecodeLivenessState* liveness);
350   void BuildLoopExitsUntilLoop(int loop_offset,
351                                const BytecodeLivenessState* liveness);
352 
353   // Helper for building a return (from an actual return or a suspend).
354   void BuildReturn(const BytecodeLivenessState* liveness);
355 
356   // Simulates entry and exit of exception handlers.
357   void ExitThenEnterExceptionHandlers(int current_offset);
358 
359   // Update the current position of the {SourcePositionTable} to that of the
360   // bytecode at {offset}, if any.
361   void UpdateSourcePosition(int offset);
362 
363   // Growth increment for the temporary buffer used to construct input lists to
364   // new nodes.
365   static const int kInputBufferSizeIncrement = 64;
366 
367   // An abstract representation for an exception handler that is being
368   // entered and exited while the graph builder is iterating over the
369   // underlying bytecode. The exception handlers within the bytecode are
370   // well scoped, hence will form a stack during iteration.
371   struct ExceptionHandler {
372     int start_offset_;      // Start offset of the handled area in the bytecode.
373     int end_offset_;        // End offset of the handled area in the bytecode.
374     int handler_offset_;    // Handler entry offset within the bytecode.
375     int context_register_;  // Index of register holding handler context.
376   };
377 
378   template <class T = Object>
MakeRefForConstantForIndexOperand( int operand_index)379   typename ref_traits<T>::ref_type MakeRefForConstantForIndexOperand(
380       int operand_index) {
381     // The BytecodeArray itself was fetched by using a barrier so all reads
382     // from the constant pool are safe.
383     return MakeRefAssumeMemoryFence(
384         broker(), broker()->CanonicalPersistentHandle(Handle<T>::cast(
385                       bytecode_iterator().GetConstantForIndexOperand(
386                           operand_index, local_isolate_))));
387   }
388 
graph() const389   Graph* graph() const { return jsgraph_->graph(); }
common() const390   CommonOperatorBuilder* common() const { return jsgraph_->common(); }
graph_zone() const391   Zone* graph_zone() const { return graph()->zone(); }
jsgraph() const392   JSGraph* jsgraph() const { return jsgraph_; }
isolate() const393   Isolate* isolate() const { return jsgraph_->isolate(); }
javascript() const394   JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); }
simplified() const395   SimplifiedOperatorBuilder* simplified() const {
396     return jsgraph_->simplified();
397   }
local_zone() const398   Zone* local_zone() const { return local_zone_; }
bytecode_array() const399   BytecodeArrayRef bytecode_array() const { return bytecode_array_; }
feedback_vector() const400   FeedbackVectorRef const& feedback_vector() const { return feedback_vector_; }
type_hint_lowering() const401   const JSTypeHintLowering& type_hint_lowering() const {
402     return type_hint_lowering_;
403   }
frame_state_function_info() const404   const FrameStateFunctionInfo* frame_state_function_info() const {
405     return frame_state_function_info_;
406   }
source_position_iterator()407   SourcePositionTableIterator& source_position_iterator() {
408     return *source_position_iterator_.get();
409   }
bytecode_iterator() const410   interpreter::BytecodeArrayIterator const& bytecode_iterator() const {
411     return bytecode_iterator_;
412   }
bytecode_iterator()413   interpreter::BytecodeArrayIterator& bytecode_iterator() {
414     return bytecode_iterator_;
415   }
bytecode_analysis() const416   BytecodeAnalysis const& bytecode_analysis() const {
417     return bytecode_analysis_;
418   }
currently_peeled_loop_offset() const419   int currently_peeled_loop_offset() const {
420     return currently_peeled_loop_offset_;
421   }
set_currently_peeled_loop_offset(int offset)422   void set_currently_peeled_loop_offset(int offset) {
423     currently_peeled_loop_offset_ = offset;
424   }
skip_first_stack_check() const425   bool skip_first_stack_check() const {
426     return skip_first_stack_and_tierup_check_;
427   }
skip_tierup_check() const428   bool skip_tierup_check() const {
429     return skip_first_stack_and_tierup_check_ || osr_;
430   }
current_exception_handler() const431   int current_exception_handler() const { return current_exception_handler_; }
set_current_exception_handler(int index)432   void set_current_exception_handler(int index) {
433     current_exception_handler_ = index;
434   }
needs_eager_checkpoint() const435   bool needs_eager_checkpoint() const { return needs_eager_checkpoint_; }
mark_as_needing_eager_checkpoint(bool value)436   void mark_as_needing_eager_checkpoint(bool value) {
437     needs_eager_checkpoint_ = value;
438   }
broker() const439   JSHeapBroker* broker() const { return broker_; }
native_context() const440   NativeContextRef native_context() const { return native_context_; }
shared_info() const441   SharedFunctionInfoRef shared_info() const { return shared_info_; }
442 
443 #define DECLARE_VISIT_BYTECODE(name, ...) void Visit##name();
444   BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
445 #undef DECLARE_VISIT_BYTECODE
446 
447   JSHeapBroker* const broker_;
448   LocalIsolate* const local_isolate_;
449   Zone* const local_zone_;
450   JSGraph* const jsgraph_;
451   // The native context for which we optimize.
452   NativeContextRef const native_context_;
453   SharedFunctionInfoRef const shared_info_;
454   BytecodeArrayRef const bytecode_array_;
455   FeedbackCellRef const feedback_cell_;
456   FeedbackVectorRef const feedback_vector_;
457   CallFrequency const invocation_frequency_;
458   JSTypeHintLowering const type_hint_lowering_;
459   const FrameStateFunctionInfo* const frame_state_function_info_;
460   std::unique_ptr<SourcePositionTableIterator> source_position_iterator_;
461   interpreter::BytecodeArrayIterator bytecode_iterator_;
462   BytecodeAnalysis const bytecode_analysis_;
463   Environment* environment_;
464   bool const osr_;
465   int currently_peeled_loop_offset_;
466 
467   const bool skip_first_stack_and_tierup_check_;
468 
469   // Merge environments are snapshots of the environment at points where the
470   // control flow merges. This models a forward data flow propagation of all
471   // values from all predecessors of the merge in question. They are indexed by
472   // the bytecode offset
473   ZoneMap<int, Environment*> merge_environments_;
474 
475   // Generator merge environments are snapshots of the current resume
476   // environment, tracing back through loop headers to the resume switch of a
477   // generator. They allow us to model a single resume jump as several switch
478   // statements across loop headers, keeping those loop headers reducible,
479   // without having to merge the "executing" environments of the generator into
480   // the "resuming" ones. They are indexed by the suspend id of the resume.
481   ZoneMap<int, Environment*> generator_merge_environments_;
482 
483   ZoneVector<Node*> cached_parameters_;
484 
485   // Exception handlers currently entered by the iteration.
486   ZoneStack<ExceptionHandler> exception_handlers_;
487   int current_exception_handler_;
488 
489   // Temporary storage for building node input lists.
490   int input_buffer_size_;
491   Node** input_buffer_;
492 
493   const CodeKind code_kind_;
494   Node* feedback_vector_node_;
495   Node* native_context_node_;
496 
497   // Optimization to only create checkpoints when the current position in the
498   // control-flow is not effect-dominated by another checkpoint already. All
499   // operations that do not have observable side-effects can be re-evaluated.
500   bool needs_eager_checkpoint_;
501 
502   // Nodes representing values in the activation record.
503   SetOncePointer<Node> function_closure_;
504 
505   // Control nodes that exit the function body.
506   ZoneVector<Node*> exit_controls_;
507 
508   StateValuesCache state_values_cache_;
509 
510   // The source position table, to be populated.
511   SourcePositionTable* const source_positions_;
512 
513   SourcePosition const start_position_;
514 
515   TickCounter* const tick_counter_;
516 
517   ObserveNodeInfo const observe_node_info_;
518 
519   static constexpr int kBinaryOperationHintIndex = 1;
520   static constexpr int kBinaryOperationSmiHintIndex = 1;
521   static constexpr int kCompareOperationHintIndex = 1;
522   static constexpr int kCountOperationHintIndex = 0;
523   static constexpr int kUnaryOperationHintIndex = 0;
524 };
525 
526 // The abstract execution environment simulates the content of the interpreter
527 // register file. The environment performs SSA-renaming of all tracked nodes at
528 // split and merge points in the control flow.
529 class BytecodeGraphBuilder::Environment : public ZoneObject {
530  public:
531   Environment(BytecodeGraphBuilder* builder, int register_count,
532               int parameter_count,
533               interpreter::Register incoming_new_target_or_generator,
534               Node* control_dependency);
535 
536   // Specifies whether environment binding methods should attach frame state
537   // inputs to nodes representing the value being bound. This is done because
538   // the {OutputFrameStateCombine} is closely related to the binding method.
539   enum FrameStateAttachmentMode { kAttachFrameState, kDontAttachFrameState };
540 
parameter_count() const541   int parameter_count() const { return parameter_count_; }
register_count() const542   int register_count() const { return register_count_; }
543 
544   Node* LookupAccumulator() const;
545   Node* LookupRegister(interpreter::Register the_register) const;
546   Node* LookupGeneratorState() const;
547 
548   void BindAccumulator(Node* node,
549                        FrameStateAttachmentMode mode = kDontAttachFrameState);
550   void BindRegister(interpreter::Register the_register, Node* node,
551                     FrameStateAttachmentMode mode = kDontAttachFrameState);
552   void BindRegistersToProjections(
553       interpreter::Register first_reg, Node* node,
554       FrameStateAttachmentMode mode = kDontAttachFrameState);
555   void BindGeneratorState(Node* node);
556   void RecordAfterState(Node* node,
557                         FrameStateAttachmentMode mode = kDontAttachFrameState);
558 
559   // Effect dependency tracked by this environment.
GetEffectDependency()560   Node* GetEffectDependency() { return effect_dependency_; }
UpdateEffectDependency(Node* dependency)561   void UpdateEffectDependency(Node* dependency) {
562     effect_dependency_ = dependency;
563   }
564 
565   // Preserve a checkpoint of the environment for the IR graph. Any
566   // further mutation of the environment will not affect checkpoints.
567   Node* Checkpoint(BytecodeOffset bytecode_offset,
568                    OutputFrameStateCombine combine,
569                    const BytecodeLivenessState* liveness);
570 
571   // Control dependency tracked by this environment.
GetControlDependency() const572   Node* GetControlDependency() const { return control_dependency_; }
UpdateControlDependency(Node* dependency)573   void UpdateControlDependency(Node* dependency) {
574     control_dependency_ = dependency;
575   }
576 
Context() const577   Node* Context() const { return context_; }
SetContext(Node* new_context)578   void SetContext(Node* new_context) { context_ = new_context; }
579 
580   Environment* Copy();
581   void Merge(Environment* other, const BytecodeLivenessState* liveness);
582 
583   void FillWithOsrValues();
584   void PrepareForLoop(const BytecodeLoopAssignments& assignments,
585                       const BytecodeLivenessState* liveness);
586   void PrepareForLoopExit(Node* loop,
587                           const BytecodeLoopAssignments& assignments,
588                           const BytecodeLivenessState* liveness);
589 
590  private:
591   friend Zone;
592 
593   explicit Environment(const Environment* copy);
594 
595   bool StateValuesRequireUpdate(Node** state_values, Node** values, int count);
596   void UpdateStateValues(Node** state_values, Node** values, int count);
597   Node* GetStateValuesFromCache(Node** values, int count,
598                                 const BytecodeLivenessState* liveness);
599 
600   int RegisterToValuesIndex(interpreter::Register the_register) const;
601 
zone() const602   Zone* zone() const { return builder_->local_zone(); }
graph() const603   Graph* graph() const { return builder_->graph(); }
common() const604   CommonOperatorBuilder* common() const { return builder_->common(); }
builder() const605   BytecodeGraphBuilder* builder() const { return builder_; }
values() const606   const NodeVector* values() const { return &values_; }
values()607   NodeVector* values() { return &values_; }
register_base() const608   int register_base() const { return register_base_; }
accumulator_base() const609   int accumulator_base() const { return accumulator_base_; }
610 
611   BytecodeGraphBuilder* builder_;
612   int register_count_;
613   int parameter_count_;
614   Node* context_;
615   Node* control_dependency_;
616   Node* effect_dependency_;
617   NodeVector values_;
618   Node* parameters_state_values_;
619   Node* generator_state_;
620   int register_base_;
621   int accumulator_base_;
622 };
623 
624 // A helper for creating a temporary sub-environment for simple branches.
625 struct BytecodeGraphBuilder::SubEnvironment final {
626  public:
SubEnvironmentv8::internal::compiler::final627   explicit SubEnvironment(BytecodeGraphBuilder* builder)
628       : builder_(builder), parent_(builder->environment()->Copy()) {}
629 
~SubEnvironmentv8::internal::compiler::final630   ~SubEnvironment() { builder_->set_environment(parent_); }
631 
632  private:
633   BytecodeGraphBuilder* builder_;
634   BytecodeGraphBuilder::Environment* parent_;
635 };
636 
637 // Issues:
638 // - Scopes - intimately tied to AST. Need to eval what is needed.
639 // - Need to resolve closure parameter treatment.
Environment( BytecodeGraphBuilder* builder, int register_count, int parameter_count, interpreter::Register incoming_new_target_or_generator, Node* control_dependency)640 BytecodeGraphBuilder::Environment::Environment(
641     BytecodeGraphBuilder* builder, int register_count, int parameter_count,
642     interpreter::Register incoming_new_target_or_generator,
643     Node* control_dependency)
644     : builder_(builder),
645       register_count_(register_count),
646       parameter_count_(parameter_count),
647       control_dependency_(control_dependency),
648       effect_dependency_(control_dependency),
649       values_(builder->local_zone()),
650       parameters_state_values_(nullptr),
651       generator_state_(nullptr) {
652   // The layout of values_ is:
653   //
654   // [receiver] [parameters] [registers] [accumulator]
655   //
656   // parameter[0] is the receiver (this), parameters 1..N are the
657   // parameters supplied to the method (arg0..argN-1). The accumulator
658   // is stored separately.
659 
660   // Parameters including the receiver
661   for (int i = 0; i < parameter_count; i++) {
662     const char* debug_name = (i == 0) ? "%this" : nullptr;
663     Node* parameter = builder->GetParameter(i, debug_name);
664     values()->push_back(parameter);
665   }
666 
667   // Registers
668   register_base_ = static_cast<int>(values()->size());
669   Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
670   values()->insert(values()->end(), register_count, undefined_constant);
671 
672   // Accumulator
673   accumulator_base_ = static_cast<int>(values()->size());
674   values()->push_back(undefined_constant);
675 
676   // Context
677   int context_index = Linkage::GetJSCallContextParamIndex(parameter_count);
678   context_ = builder->GetParameter(context_index, "%context");
679 
680   // Incoming new.target or generator register
681   if (incoming_new_target_or_generator.is_valid()) {
682     int new_target_index =
683         Linkage::GetJSCallNewTargetParamIndex(parameter_count);
684     Node* new_target_node =
685         builder->GetParameter(new_target_index, "%new.target");
686 
687     int values_index = RegisterToValuesIndex(incoming_new_target_or_generator);
688     values()->at(values_index) = new_target_node;
689   }
690 }
691 
Environment( const BytecodeGraphBuilder::Environment* other)692 BytecodeGraphBuilder::Environment::Environment(
693     const BytecodeGraphBuilder::Environment* other)
694     : builder_(other->builder_),
695       register_count_(other->register_count_),
696       parameter_count_(other->parameter_count_),
697       context_(other->context_),
698       control_dependency_(other->control_dependency_),
699       effect_dependency_(other->effect_dependency_),
700       values_(other->zone()),
701       parameters_state_values_(other->parameters_state_values_),
702       generator_state_(other->generator_state_),
703       register_base_(other->register_base_),
704       accumulator_base_(other->accumulator_base_) {
705   values_ = other->values_;
706 }
707 
708 
RegisterToValuesIndex( interpreter::Register the_register) const709 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
710     interpreter::Register the_register) const {
711   if (the_register.is_parameter()) {
712     return the_register.ToParameterIndex();
713   } else {
714     return the_register.index() + register_base();
715   }
716 }
717 
LookupAccumulator() const718 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
719   return values()->at(accumulator_base_);
720 }
721 
LookupGeneratorState() const722 Node* BytecodeGraphBuilder::Environment::LookupGeneratorState() const {
723   DCHECK_NOT_NULL(generator_state_);
724   return generator_state_;
725 }
726 
LookupRegister( interpreter::Register the_register) const727 Node* BytecodeGraphBuilder::Environment::LookupRegister(
728     interpreter::Register the_register) const {
729   if (the_register.is_current_context()) {
730     return Context();
731   } else if (the_register.is_function_closure()) {
732     return builder()->GetFunctionClosure();
733   } else {
734     int values_index = RegisterToValuesIndex(the_register);
735     return values()->at(values_index);
736   }
737 }
738 
BindAccumulator( Node* node, FrameStateAttachmentMode mode)739 void BytecodeGraphBuilder::Environment::BindAccumulator(
740     Node* node, FrameStateAttachmentMode mode) {
741   if (mode == FrameStateAttachmentMode::kAttachFrameState) {
742     builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0));
743   }
744   values()->at(accumulator_base_) = node;
745 }
746 
BindGeneratorState(Node* node)747 void BytecodeGraphBuilder::Environment::BindGeneratorState(Node* node) {
748   generator_state_ = node;
749 }
750 
BindRegister( interpreter::Register the_register, Node* node, FrameStateAttachmentMode mode)751 void BytecodeGraphBuilder::Environment::BindRegister(
752     interpreter::Register the_register, Node* node,
753     FrameStateAttachmentMode mode) {
754   int values_index = RegisterToValuesIndex(the_register);
755   if (mode == FrameStateAttachmentMode::kAttachFrameState) {
756     builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
757                                            accumulator_base_ - values_index));
758   }
759   values()->at(values_index) = node;
760 }
761 
BindRegistersToProjections( interpreter::Register first_reg, Node* node, FrameStateAttachmentMode mode)762 void BytecodeGraphBuilder::Environment::BindRegistersToProjections(
763     interpreter::Register first_reg, Node* node,
764     FrameStateAttachmentMode mode) {
765   int values_index = RegisterToValuesIndex(first_reg);
766   if (mode == FrameStateAttachmentMode::kAttachFrameState) {
767     builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
768                                            accumulator_base_ - values_index));
769   }
770   for (int i = 0; i < node->op()->ValueOutputCount(); i++) {
771     values()->at(values_index + i) =
772         builder()->NewNode(common()->Projection(i), node);
773   }
774 }
775 
RecordAfterState( Node* node, FrameStateAttachmentMode mode)776 void BytecodeGraphBuilder::Environment::RecordAfterState(
777     Node* node, FrameStateAttachmentMode mode) {
778   if (mode == FrameStateAttachmentMode::kAttachFrameState) {
779     builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore());
780   }
781 }
782 
Copy()783 BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::Environment::Copy() {
784   return zone()->New<Environment>(this);
785 }
786 
Merge( BytecodeGraphBuilder::Environment* other, const BytecodeLivenessState* liveness)787 void BytecodeGraphBuilder::Environment::Merge(
788     BytecodeGraphBuilder::Environment* other,
789     const BytecodeLivenessState* liveness) {
790   // Create a merge of the control dependencies of both environments and update
791   // the current environment's control dependency accordingly.
792   Node* control = builder()->MergeControl(GetControlDependency(),
793                                           other->GetControlDependency());
794   UpdateControlDependency(control);
795 
796   // Create a merge of the effect dependencies of both environments and update
797   // the current environment's effect dependency accordingly.
798   Node* effect = builder()->MergeEffect(GetEffectDependency(),
799                                         other->GetEffectDependency(), control);
800   UpdateEffectDependency(effect);
801 
802   // Introduce Phi nodes for values that are live and have differing inputs at
803   // the merge point, potentially extending an existing Phi node if possible.
804   context_ = builder()->MergeValue(context_, other->context_, control);
805   for (int i = 0; i < parameter_count(); i++) {
806     values_[i] = builder()->MergeValue(values_[i], other->values_[i], control);
807   }
808   for (int i = 0; i < register_count(); i++) {
809     int index = register_base() + i;
810     if (liveness == nullptr || liveness->RegisterIsLive(i)) {
811 #if DEBUG
812       // We only do these DCHECKs when we are not in the resume path of a
813       // generator -- this is, when either there is no generator state at all,
814       // or the generator state is not the constant "executing" value.
815       if (generator_state_ == nullptr ||
816           NumberMatcher(generator_state_)
817               .Is(JSGeneratorObject::kGeneratorExecuting)) {
818         DCHECK_NE(values_[index], builder()->jsgraph()->OptimizedOutConstant());
819         DCHECK_NE(other->values_[index],
820                   builder()->jsgraph()->OptimizedOutConstant());
821       }
822 #endif
823 
824       values_[index] =
825           builder()->MergeValue(values_[index], other->values_[index], control);
826 
827     } else {
828       values_[index] = builder()->jsgraph()->OptimizedOutConstant();
829     }
830   }
831 
832   if (liveness == nullptr || liveness->AccumulatorIsLive()) {
833     DCHECK_NE(values_[accumulator_base()],
834               builder()->jsgraph()->OptimizedOutConstant());
835     DCHECK_NE(other->values_[accumulator_base()],
836               builder()->jsgraph()->OptimizedOutConstant());
837 
838     values_[accumulator_base()] =
839         builder()->MergeValue(values_[accumulator_base()],
840                               other->values_[accumulator_base()], control);
841   } else {
842     values_[accumulator_base()] = builder()->jsgraph()->OptimizedOutConstant();
843   }
844 
845   if (generator_state_ != nullptr) {
846     DCHECK_NOT_NULL(other->generator_state_);
847     generator_state_ = builder()->MergeValue(generator_state_,
848                                              other->generator_state_, control);
849   }
850 }
851 
PrepareForLoop( const BytecodeLoopAssignments& assignments, const BytecodeLivenessState* liveness)852 void BytecodeGraphBuilder::Environment::PrepareForLoop(
853     const BytecodeLoopAssignments& assignments,
854     const BytecodeLivenessState* liveness) {
855   // Create a control node for the loop header.
856   Node* control = builder()->NewLoop();
857 
858   // Create a Phi for external effects.
859   Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control);
860   UpdateEffectDependency(effect);
861 
862   // Create Phis for any values that are live on entry to the loop and may be
863   // updated by the end of the loop.
864   context_ = builder()->NewPhi(1, context_, control);
865   for (int i = 0; i < parameter_count(); i++) {
866     if (assignments.ContainsParameter(i)) {
867       values_[i] = builder()->NewPhi(1, values_[i], control);
868     }
869   }
870   for (int i = 0; i < register_count(); i++) {
871     if (assignments.ContainsLocal(i) &&
872         (liveness == nullptr || liveness->RegisterIsLive(i))) {
873       int index = register_base() + i;
874       values_[index] = builder()->NewPhi(1, values_[index], control);
875     }
876   }
877   // The accumulator should not be live on entry.
878   DCHECK_IMPLIES(liveness != nullptr, !liveness->AccumulatorIsLive());
879 
880   if (generator_state_ != nullptr) {
881     generator_state_ = builder()->NewPhi(1, generator_state_, control);
882   }
883 
884   // Connect to the loop end.
885   Node* terminate = builder()->graph()->NewNode(
886       builder()->common()->Terminate(), effect, control);
887   builder()->exit_controls_.push_back(terminate);
888 }
889 
FillWithOsrValues()890 void BytecodeGraphBuilder::Environment::FillWithOsrValues() {
891   Node* start = graph()->start();
892 
893   // Create OSR values for each environment value.
894   SetContext(graph()->NewNode(
895       common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), start));
896   int size = static_cast<int>(values()->size());
897   for (int i = 0; i < size; i++) {
898     int idx = i;  // Indexing scheme follows {StandardFrame}, adapt accordingly.
899     if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount;
900     if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex;
901     values()->at(i) = graph()->NewNode(common()->OsrValue(idx), start);
902   }
903 }
904 
StateValuesRequireUpdate( Node** state_values, Node** values, int count)905 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
906     Node** state_values, Node** values, int count) {
907   if (*state_values == nullptr) {
908     return true;
909   }
910   Node::Inputs inputs = (*state_values)->inputs();
911   if (inputs.count() != count) return true;
912   for (int i = 0; i < count; i++) {
913     if (inputs[i] != values[i]) {
914       return true;
915     }
916   }
917   return false;
918 }
919 
PrepareForLoopExit( Node* loop, const BytecodeLoopAssignments& assignments, const BytecodeLivenessState* liveness)920 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(
921     Node* loop, const BytecodeLoopAssignments& assignments,
922     const BytecodeLivenessState* liveness) {
923   DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);
924 
925   Node* control = GetControlDependency();
926 
927   // Create the loop exit node.
928   Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop);
929   UpdateControlDependency(loop_exit);
930 
931   // Rename the effect.
932   Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
933                                          GetEffectDependency(), loop_exit);
934   UpdateEffectDependency(effect_rename);
935 
936   // TODO(jarin) We should also rename context here. However, unconditional
937   // renaming confuses global object and native context specialization.
938   // We should only rename if the context is assigned in the loop.
939 
940   // Rename the environment values if they were assigned in the loop and are
941   // live after exiting the loop.
942   for (int i = 0; i < parameter_count(); i++) {
943     if (assignments.ContainsParameter(i)) {
944       Node* rename = graph()->NewNode(
945           common()->LoopExitValue(MachineRepresentation::kTagged), values_[i],
946           loop_exit);
947       values_[i] = rename;
948     }
949   }
950   for (int i = 0; i < register_count(); i++) {
951     if (assignments.ContainsLocal(i) &&
952         (liveness == nullptr || liveness->RegisterIsLive(i))) {
953       Node* rename = graph()->NewNode(
954           common()->LoopExitValue(MachineRepresentation::kTagged),
955           values_[register_base() + i], loop_exit);
956       values_[register_base() + i] = rename;
957     }
958   }
959   if (liveness == nullptr || liveness->AccumulatorIsLive()) {
960     Node* rename = graph()->NewNode(
961         common()->LoopExitValue(MachineRepresentation::kTagged),
962         values_[accumulator_base()], loop_exit);
963     values_[accumulator_base()] = rename;
964   }
965 
966   if (generator_state_ != nullptr) {
967     generator_state_ = graph()->NewNode(
968         common()->LoopExitValue(MachineRepresentation::kTagged),
969         generator_state_, loop_exit);
970   }
971 }
972 
UpdateStateValues(Node** state_values, Node** values, int count)973 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
974                                                           Node** values,
975                                                           int count) {
976   if (StateValuesRequireUpdate(state_values, values, count)) {
977     const Operator* op = common()->StateValues(count, SparseInputMask::Dense());
978     (*state_values) = graph()->NewNode(op, count, values);
979   }
980 }
981 
GetStateValuesFromCache( Node** values, int count, const BytecodeLivenessState* liveness)982 Node* BytecodeGraphBuilder::Environment::GetStateValuesFromCache(
983     Node** values, int count, const BytecodeLivenessState* liveness) {
984   return builder_->state_values_cache_.GetNodeForValues(
985       values, static_cast<size_t>(count), liveness);
986 }
987 
Checkpoint( BytecodeOffset bailout_id, OutputFrameStateCombine combine, const BytecodeLivenessState* liveness)988 Node* BytecodeGraphBuilder::Environment::Checkpoint(
989     BytecodeOffset bailout_id, OutputFrameStateCombine combine,
990     const BytecodeLivenessState* liveness) {
991   if (parameter_count() == register_count()) {
992     // Re-use the state-value cache if the number of local registers happens
993     // to match the parameter count.
994     parameters_state_values_ =
995         GetStateValuesFromCache(&values()->at(0), parameter_count(), nullptr);
996   } else {
997     UpdateStateValues(&parameters_state_values_, &values()->at(0),
998                       parameter_count());
999   }
1000 
1001   Node* registers_state_values = GetStateValuesFromCache(
1002       &values()->at(register_base()), register_count(), liveness);
1003 
1004   bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive();
1005   Node* accumulator_state_value =
1006       accumulator_is_live && combine != OutputFrameStateCombine::PokeAt(0)
1007           ? values()->at(accumulator_base())
1008           : builder()->jsgraph()->OptimizedOutConstant();
1009 
1010   const Operator* op = common()->FrameState(
1011       bailout_id, combine, builder()->frame_state_function_info());
1012   Node* result = graph()->NewNode(
1013       op, parameters_state_values_, registers_state_values,
1014       accumulator_state_value, Context(), builder()->GetFunctionClosure(),
1015       builder()->graph()->start());
1016 
1017   return result;
1018 }
1019 
BytecodeGraphBuilder( JSHeapBroker* broker, Zone* local_zone, NativeContextRef const& native_context, SharedFunctionInfoRef const& shared_info, FeedbackCellRef const& feedback_cell, BytecodeOffset osr_offset, JSGraph* jsgraph, CallFrequency const& invocation_frequency, SourcePositionTable* source_positions, int inlining_id, CodeKind code_kind, BytecodeGraphBuilderFlags flags, TickCounter* tick_counter, ObserveNodeInfo const& observe_node_info)1020 BytecodeGraphBuilder::BytecodeGraphBuilder(
1021     JSHeapBroker* broker, Zone* local_zone,
1022     NativeContextRef const& native_context,
1023     SharedFunctionInfoRef const& shared_info,
1024     FeedbackCellRef const& feedback_cell, BytecodeOffset osr_offset,
1025     JSGraph* jsgraph, CallFrequency const& invocation_frequency,
1026     SourcePositionTable* source_positions, int inlining_id, CodeKind code_kind,
1027     BytecodeGraphBuilderFlags flags, TickCounter* tick_counter,
1028     ObserveNodeInfo const& observe_node_info)
1029     : broker_(broker),
1030       local_isolate_(broker_->local_isolate()
1031                          ? broker_->local_isolate()
1032                          : broker_->isolate()->AsLocalIsolate()),
1033       local_zone_(local_zone),
1034       jsgraph_(jsgraph),
1035       native_context_(native_context),
1036       shared_info_(shared_info),
1037       bytecode_array_(shared_info.GetBytecodeArray()),
1038       feedback_cell_(feedback_cell),
1039       feedback_vector_(feedback_cell.feedback_vector().value()),
1040       invocation_frequency_(invocation_frequency),
1041       type_hint_lowering_(
1042           broker, jsgraph, feedback_vector_,
1043           (flags & BytecodeGraphBuilderFlag::kBailoutOnUninitialized)
1044               ? JSTypeHintLowering::kBailoutOnUninitialized
1045               : JSTypeHintLowering::kNoFlags),
1046       frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
1047           FrameStateType::kUnoptimizedFunction,
1048           bytecode_array().parameter_count(), bytecode_array().register_count(),
1049           shared_info.object())),
1050       source_position_iterator_(std::make_unique<SourcePositionTableIterator>(
1051           bytecode_array().SourcePositionTable())),
1052       bytecode_iterator_(bytecode_array().object()),
1053       bytecode_analysis_(
1054           bytecode_array().object(), local_zone, osr_offset,
1055           flags & BytecodeGraphBuilderFlag::kAnalyzeEnvironmentLiveness),
1056       environment_(nullptr),
1057       osr_(!osr_offset.IsNone()),
1058       currently_peeled_loop_offset_(-1),
1059       skip_first_stack_and_tierup_check_(
1060           flags & BytecodeGraphBuilderFlag::kSkipFirstStackAndTierupCheck),
1061       merge_environments_(local_zone),
1062       generator_merge_environments_(local_zone),
1063       cached_parameters_(local_zone),
1064       exception_handlers_(local_zone),
1065       current_exception_handler_(0),
1066       input_buffer_size_(0),
1067       input_buffer_(nullptr),
1068       code_kind_(code_kind),
1069       feedback_vector_node_(nullptr),
1070       native_context_node_(nullptr),
1071       needs_eager_checkpoint_(true),
1072       exit_controls_(local_zone),
1073       state_values_cache_(jsgraph),
1074       source_positions_(source_positions),
1075       start_position_(shared_info.StartPosition(), inlining_id),
1076       tick_counter_(tick_counter),
1077       observe_node_info_(observe_node_info) {}
1078 
GetFunctionClosure()1079 Node* BytecodeGraphBuilder::GetFunctionClosure() {
1080   if (!function_closure_.is_set()) {
1081     int index = Linkage::kJSCallClosureParamIndex;
1082     Node* node = GetParameter(index, "%closure");
1083     function_closure_.set(node);
1084   }
1085   return function_closure_.get();
1086 }
1087 
GetParameter(int parameter_index, const char* debug_name_hint)1088 Node* BytecodeGraphBuilder::GetParameter(int parameter_index,
1089                                          const char* debug_name_hint) {
1090   // We use negative indices for some parameters.
1091   DCHECK_LE(ParameterInfo::kMinIndex, parameter_index);
1092   const size_t index =
1093       static_cast<size_t>(parameter_index - ParameterInfo::kMinIndex);
1094 
1095   if (cached_parameters_.size() <= index) {
1096     cached_parameters_.resize(index + 1, nullptr);
1097   }
1098 
1099   if (cached_parameters_[index] == nullptr) {
1100     cached_parameters_[index] =
1101         NewNode(common()->Parameter(parameter_index, debug_name_hint),
1102                 graph()->start());
1103   }
1104 
1105   return cached_parameters_[index];
1106 }
1107 
CreateFeedbackVectorNode()1108 void BytecodeGraphBuilder::CreateFeedbackVectorNode() {
1109   DCHECK_NULL(feedback_vector_node_);
1110   feedback_vector_node_ = jsgraph()->Constant(feedback_vector());
1111 }
1112 
BuildLoadFeedbackCell(int index)1113 Node* BytecodeGraphBuilder::BuildLoadFeedbackCell(int index) {
1114   return jsgraph()->Constant(feedback_vector().GetClosureFeedbackCell(index));
1115 }
1116 
CreateNativeContextNode()1117 void BytecodeGraphBuilder::CreateNativeContextNode() {
1118   DCHECK_NULL(native_context_node_);
1119   native_context_node_ = jsgraph()->Constant(native_context());
1120 }
1121 
BuildLoadNativeContextField(int index)1122 Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
1123   Node* result = NewNode(javascript()->LoadContext(0, index, true));
1124   NodeProperties::ReplaceContextInput(result, native_context_node());
1125   return result;
1126 }
1127 
CreateFeedbackSource(int slot_id)1128 FeedbackSource BytecodeGraphBuilder::CreateFeedbackSource(int slot_id) {
1129   return CreateFeedbackSource(FeedbackVector::ToSlot(slot_id));
1130 }
1131 
CreateFeedbackSource(FeedbackSlot slot)1132 FeedbackSource BytecodeGraphBuilder::CreateFeedbackSource(FeedbackSlot slot) {
1133   return FeedbackSource(feedback_vector(), slot);
1134 }
1135 
CreateGraph()1136 void BytecodeGraphBuilder::CreateGraph() {
1137   SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
1138 
1139   // Set up the basic structure of the graph. Outputs for {Start} are the formal
1140   // parameters (including the receiver) plus new target, number of arguments,
1141   // context and closure.
1142   int start_output_arity = StartNode::OutputArityForFormalParameterCount(
1143       bytecode_array().parameter_count());
1144   graph()->SetStart(graph()->NewNode(common()->Start(start_output_arity)));
1145 
1146   Environment env(this, bytecode_array().register_count(),
1147                   bytecode_array().parameter_count(),
1148                   bytecode_array().incoming_new_target_or_generator_register(),
1149                   graph()->start());
1150   set_environment(&env);
1151 
1152   CreateFeedbackVectorNode();
1153   CreateNativeContextNode();
1154 
1155   VisitBytecodes();
1156 
1157   // Finish the basic structure of the graph.
1158   DCHECK_NE(0u, exit_controls_.size());
1159   int const input_count = static_cast<int>(exit_controls_.size());
1160   Node** const inputs = &exit_controls_.front();
1161   Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
1162   graph()->SetEnd(end);
1163 }
1164 
PrepareEagerCheckpoint()1165 void BytecodeGraphBuilder::PrepareEagerCheckpoint() {
1166   if (needs_eager_checkpoint()) {
1167     // Create an explicit checkpoint node for before the operation. This only
1168     // needs to happen if we aren't effect-dominated by a {Checkpoint} already.
1169     mark_as_needing_eager_checkpoint(false);
1170     Node* node = NewNode(common()->Checkpoint());
1171     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
1172     DCHECK_EQ(IrOpcode::kDead,
1173               NodeProperties::GetFrameStateInput(node)->opcode());
1174     BytecodeOffset bailout_id(bytecode_iterator().current_offset());
1175 
1176     const BytecodeLivenessState* liveness_before =
1177         bytecode_analysis().GetInLivenessFor(
1178             bytecode_iterator().current_offset());
1179 
1180     Node* frame_state_before = environment()->Checkpoint(
1181         bailout_id, OutputFrameStateCombine::Ignore(), liveness_before);
1182     NodeProperties::ReplaceFrameStateInput(node, frame_state_before);
1183 #ifdef DEBUG
1184   } else {
1185     // In case we skipped checkpoint creation above, we must be able to find an
1186     // existing checkpoint that effect-dominates the nodes about to be created.
1187     // Starting a search from the current effect-dependency has to succeed.
1188     Node* effect = environment()->GetEffectDependency();
1189     while (effect->opcode() != IrOpcode::kCheckpoint) {
1190       DCHECK(effect->op()->HasProperty(Operator::kNoWrite));
1191       DCHECK_EQ(1, effect->op()->EffectInputCount());
1192       effect = NodeProperties::GetEffectInput(effect);
1193     }
1194   }
1195 #else
1196   }
1197 #endif  // DEBUG
1198 }
1199 
PrepareFrameState( Node* node, OutputFrameStateCombine combine, BytecodeOffset bailout_id, const BytecodeLivenessState* liveness)1200 void BytecodeGraphBuilder::PrepareFrameState(
1201     Node* node, OutputFrameStateCombine combine, BytecodeOffset bailout_id,
1202     const BytecodeLivenessState* liveness) {
1203   if (OperatorProperties::HasFrameStateInput(node->op())) {
1204     // Add the frame state for after the operation. The node in question has
1205     // already been created and had a {Dead} frame state input up until now.
1206     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
1207     DCHECK_EQ(IrOpcode::kDead,
1208               NodeProperties::GetFrameStateInput(node)->opcode());
1209 
1210     Node* frame_state_after =
1211         environment()->Checkpoint(bailout_id, combine, liveness);
1212     NodeProperties::ReplaceFrameStateInput(node, frame_state_after);
1213   }
1214 }
1215 
AdvanceIteratorsTo(int bytecode_offset)1216 void BytecodeGraphBuilder::AdvanceIteratorsTo(int bytecode_offset) {
1217   for (; bytecode_iterator().current_offset() != bytecode_offset;
1218        bytecode_iterator().Advance()) {
1219     UpdateSourcePosition(bytecode_iterator().current_offset());
1220   }
1221 }
1222 
1223 // Stores the state of the SourcePosition iterator, and the index to the
1224 // current exception handlers stack. We need, during the OSR graph generation,
1225 // to backup the states of these iterators at the LoopHeader offset of each
1226 // outer loop which contains the OSR loop. The iterators are then restored when
1227 // peeling the loops, so that both exception handling and synchronisation with
1228 // the source position can be achieved.
1229 class BytecodeGraphBuilder::OsrIteratorState {
1230  public:
OsrIteratorState(BytecodeGraphBuilder* graph_builder)1231   explicit OsrIteratorState(BytecodeGraphBuilder* graph_builder)
1232       : graph_builder_(graph_builder),
1233         saved_states_(graph_builder->local_zone()) {}
1234 
ProcessOsrPrelude()1235   void ProcessOsrPrelude() {
1236     ZoneVector<int> outer_loop_offsets(graph_builder_->local_zone());
1237     int osr_entry = graph_builder_->bytecode_analysis().osr_entry_point();
1238 
1239     // We find here the outermost loop which contains the OSR loop.
1240     int outermost_loop_offset = osr_entry;
1241     while ((outermost_loop_offset = graph_builder_->bytecode_analysis()
1242                                         .GetLoopInfoFor(outermost_loop_offset)
1243                                         .parent_offset()) != -1) {
1244       outer_loop_offsets.push_back(outermost_loop_offset);
1245     }
1246     outermost_loop_offset =
1247         outer_loop_offsets.empty() ? osr_entry : outer_loop_offsets.back();
1248     graph_builder_->AdvanceIteratorsTo(outermost_loop_offset);
1249 
1250     // We save some iterators states at the offsets of the loop headers of the
1251     // outer loops (the ones containing the OSR loop). They will be used for
1252     // jumping back in the bytecode.
1253     for (ZoneVector<int>::const_reverse_iterator it =
1254              outer_loop_offsets.crbegin();
1255          it != outer_loop_offsets.crend(); ++it) {
1256       graph_builder_->AdvanceIteratorsTo(*it);
1257       graph_builder_->ExitThenEnterExceptionHandlers(
1258           graph_builder_->bytecode_iterator().current_offset());
1259       saved_states_.push(IteratorsStates(
1260           graph_builder_->current_exception_handler(),
1261           graph_builder_->source_position_iterator().GetState()));
1262     }
1263 
1264     // Finishing by advancing to the OSR entry
1265     graph_builder_->AdvanceIteratorsTo(osr_entry);
1266 
1267     // Enters all remaining exception handler which end before the OSR loop
1268     // so that on next call of VisitSingleBytecode they will get popped from
1269     // the exception handlers stack.
1270     graph_builder_->ExitThenEnterExceptionHandlers(osr_entry);
1271     graph_builder_->set_currently_peeled_loop_offset(
1272         graph_builder_->bytecode_analysis()
1273             .GetLoopInfoFor(osr_entry)
1274             .parent_offset());
1275   }
1276 
RestoreState(int target_offset, int new_parent_offset)1277   void RestoreState(int target_offset, int new_parent_offset) {
1278     graph_builder_->bytecode_iterator().SetOffset(target_offset);
1279     // In case of a return, we must not build loop exits for
1280     // not-yet-built outer loops.
1281     graph_builder_->set_currently_peeled_loop_offset(new_parent_offset);
1282     IteratorsStates saved_state = saved_states_.top();
1283     graph_builder_->source_position_iterator().RestoreState(
1284         saved_state.source_iterator_state_);
1285     graph_builder_->set_current_exception_handler(
1286         saved_state.exception_handler_index_);
1287     saved_states_.pop();
1288   }
1289 
1290  private:
1291   struct IteratorsStates {
1292     int exception_handler_index_;
1293     SourcePositionTableIterator::IndexAndPositionState source_iterator_state_;
1294 
IteratorsStatesv8::internal::BytecodeGraphBuilder::OsrIteratorState::IteratorsStates1295     IteratorsStates(int exception_handler_index,
1296                     SourcePositionTableIterator::IndexAndPositionState
1297                         source_iterator_state)
1298         : exception_handler_index_(exception_handler_index),
1299           source_iterator_state_(source_iterator_state) {}
1300   };
1301 
1302   BytecodeGraphBuilder* graph_builder_;
1303   ZoneStack<IteratorsStates> saved_states_;
1304 };
1305 
RemoveMergeEnvironmentsBeforeOffset( int limit_offset)1306 void BytecodeGraphBuilder::RemoveMergeEnvironmentsBeforeOffset(
1307     int limit_offset) {
1308   if (!merge_environments_.empty()) {
1309     ZoneMap<int, Environment*>::iterator it = merge_environments_.begin();
1310     ZoneMap<int, Environment*>::iterator stop_it = merge_environments_.end();
1311     while (it != stop_it && it->first <= limit_offset) {
1312       it = merge_environments_.erase(it);
1313     }
1314   }
1315 }
1316 
BuildFunctionEntryStackCheck()1317 void BytecodeGraphBuilder::BuildFunctionEntryStackCheck() {
1318   if (!skip_first_stack_check()) {
1319     DCHECK(exception_handlers_.empty());
1320     Node* node =
1321         NewNode(javascript()->StackCheck(StackCheckKind::kJSFunctionEntry));
1322     PrepareFrameStateForFunctionEntryStackCheck(node);
1323   }
1324 }
1325 
BuildIterationBodyStackCheck()1326 void BytecodeGraphBuilder::BuildIterationBodyStackCheck() {
1327   Node* node =
1328       NewNode(javascript()->StackCheck(StackCheckKind::kJSIterationBody));
1329   environment()->RecordAfterState(node, Environment::kAttachFrameState);
1330 }
1331 
BuildOSREntryStackCheck()1332 void BytecodeGraphBuilder::BuildOSREntryStackCheck() {
1333   DCHECK(exception_handlers_.empty());
1334   Node* node =
1335       NewNode(javascript()->StackCheck(StackCheckKind::kJSFunctionEntry));
1336   PrepareFrameStateForOSREntryStackCheck(node);
1337 }
1338 
1339 // We will iterate through the OSR loop, then its parent, and so on
1340 // until we have reached the outmost loop containing the OSR loop. We do
1341 // not generate nodes for anything before the outermost loop.
AdvanceToOsrEntryAndPeelLoops()1342 void BytecodeGraphBuilder::AdvanceToOsrEntryAndPeelLoops() {
1343   environment()->FillWithOsrValues();
1344 
1345   // The entry stack check has to happen *before* initialising the OSR prelude;
1346   // it has to happen before setting up exception handlers, so that the
1347   // optimized code can't accidentally catch a failingstack with a OSR-ed loop
1348   // inside a try-catch, e.g.
1349   //
1350   //   try {
1351   //     loop { OSR(); }
1352   //   } catch {
1353   //     // Ignore failed stack check.
1354   //   }
1355   BuildOSREntryStackCheck();
1356 
1357   OsrIteratorState iterator_states(this);
1358   iterator_states.ProcessOsrPrelude();
1359   int osr_entry = bytecode_analysis().osr_entry_point();
1360   DCHECK_EQ(bytecode_iterator().current_offset(), osr_entry);
1361 
1362   // Suppose we have n nested loops, loop_0 being the outermost one, and
1363   // loop_n being the OSR loop. We start iterating the bytecode at the header
1364   // of loop_n (the OSR loop), and then we peel the part of the the body of
1365   // loop_{n-1} following the end of loop_n. We then rewind the iterator to
1366   // the header of loop_{n-1}, and so on until we have partly peeled loop 0.
1367   // The full loop_0 body will be generating with the rest of the function,
1368   // outside the OSR generation.
1369 
1370   // To do so, if we are visiting a loop, we continue to visit what's left
1371   // of its parent, and then when reaching the parent's JumpLoop, we do not
1372   // create any jump for that but rewind the bytecode iterator to visit the
1373   // parent loop entirely, and so on.
1374 
1375   int current_parent_offset =
1376       bytecode_analysis().GetLoopInfoFor(osr_entry).parent_offset();
1377   while (current_parent_offset != -1) {
1378     const LoopInfo& current_parent_loop =
1379         bytecode_analysis().GetLoopInfoFor(current_parent_offset);
1380     // We iterate until the back edge of the parent loop, which we detect by
1381     // the offset that the JumpLoop targets.
1382     for (; !bytecode_iterator().done(); bytecode_iterator().Advance()) {
1383       if (bytecode_iterator().current_bytecode() ==
1384               interpreter::Bytecode::kJumpLoop &&
1385           bytecode_iterator().GetJumpTargetOffset() == current_parent_offset) {
1386         // Reached the end of the current parent loop.
1387         break;
1388       }
1389       VisitSingleBytecode();
1390     }
1391     DCHECK(!bytecode_iterator()
1392                 .done());  // Should have found the loop's jump target.
1393 
1394     // We also need to take care of the merge environments and exceptions
1395     // handlers here because the omitted JumpLoop bytecode can still be the
1396     // target of jumps or the first bytecode after a try block.
1397     ExitThenEnterExceptionHandlers(bytecode_iterator().current_offset());
1398     SwitchToMergeEnvironment(bytecode_iterator().current_offset());
1399 
1400     // This jump is the jump of our parent loop, which is not yet created.
1401     // So we do not build the jump nodes, but restore the bytecode and the
1402     // SourcePosition iterators to the values they had when we were visiting
1403     // the offset pointed at by the JumpLoop we've just reached.
1404     // We have already built nodes for inner loops, but now we will
1405     // iterate again over them and build new nodes corresponding to the same
1406     // bytecode offsets. Any jump or reference to this inner loops must now
1407     // point to the new nodes we will build, hence we clear the relevant part
1408     // of the environment.
1409     // Completely clearing the environment is not possible because merge
1410     // environments for forward jumps out of the loop need to be preserved
1411     // (e.g. a return or a labeled break in the middle of a loop).
1412     RemoveMergeEnvironmentsBeforeOffset(bytecode_iterator().current_offset());
1413     iterator_states.RestoreState(current_parent_offset,
1414                                  current_parent_loop.parent_offset());
1415     current_parent_offset = current_parent_loop.parent_offset();
1416   }
1417 }
1418 
VisitSingleBytecode()1419 void BytecodeGraphBuilder::VisitSingleBytecode() {
1420   tick_counter_->TickAndMaybeEnterSafepoint();
1421   int current_offset = bytecode_iterator().current_offset();
1422   UpdateSourcePosition(current_offset);
1423   ExitThenEnterExceptionHandlers(current_offset);
1424   DCHECK_GE(exception_handlers_.empty() ? current_offset
1425                                         : exception_handlers_.top().end_offset_,
1426             current_offset);
1427   SwitchToMergeEnvironment(current_offset);
1428 
1429   if (environment() != nullptr) {
1430     BuildLoopHeaderEnvironment(current_offset);
1431 
1432     switch (bytecode_iterator().current_bytecode()) {
1433 #define BYTECODE_CASE(name, ...)       \
1434   case interpreter::Bytecode::k##name: \
1435     Visit##name();                     \
1436     break;
1437       BYTECODE_LIST(BYTECODE_CASE)
1438 #undef BYTECODE_CASE
1439     }
1440   }
1441 }
1442 
VisitBytecodes()1443 void BytecodeGraphBuilder::VisitBytecodes() {
1444   if (!bytecode_analysis().resume_jump_targets().empty()) {
1445     environment()->BindGeneratorState(
1446         jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting));
1447   }
1448 
1449   if (osr_) {
1450     // We peel the OSR loop and any outer loop containing it except that we
1451     // leave the nodes corresponding to the whole outermost loop (including
1452     // the last copies of the loops it contains) to be generated by the normal
1453     // bytecode iteration below.
1454     AdvanceToOsrEntryAndPeelLoops();
1455   } else {
1456     BuildFunctionEntryStackCheck();
1457   }
1458 
1459   for (; !bytecode_iterator().done(); bytecode_iterator().Advance()) {
1460     VisitSingleBytecode();
1461   }
1462 
1463   DCHECK(exception_handlers_.empty());
1464 }
1465 
VisitLdaZero()1466 void BytecodeGraphBuilder::VisitLdaZero() {
1467   Node* node = jsgraph()->ZeroConstant();
1468   environment()->BindAccumulator(node);
1469 }
1470 
VisitLdaSmi()1471 void BytecodeGraphBuilder::VisitLdaSmi() {
1472   Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
1473   environment()->BindAccumulator(node);
1474 }
1475 
VisitLdaConstant()1476 void BytecodeGraphBuilder::VisitLdaConstant() {
1477   ObjectRef object = MakeRefForConstantForIndexOperand(0);
1478   Node* node = jsgraph()->Constant(object);
1479   environment()->BindAccumulator(node);
1480 }
1481 
VisitLdaUndefined()1482 void BytecodeGraphBuilder::VisitLdaUndefined() {
1483   Node* node = jsgraph()->UndefinedConstant();
1484   environment()->BindAccumulator(node);
1485 }
1486 
VisitLdaNull()1487 void BytecodeGraphBuilder::VisitLdaNull() {
1488   Node* node = jsgraph()->NullConstant();
1489   environment()->BindAccumulator(node);
1490 }
1491 
VisitLdaTheHole()1492 void BytecodeGraphBuilder::VisitLdaTheHole() {
1493   Node* node = jsgraph()->TheHoleConstant();
1494   environment()->BindAccumulator(node);
1495 }
1496 
VisitLdaTrue()1497 void BytecodeGraphBuilder::VisitLdaTrue() {
1498   Node* node = jsgraph()->TrueConstant();
1499   environment()->BindAccumulator(node);
1500 }
1501 
VisitLdaFalse()1502 void BytecodeGraphBuilder::VisitLdaFalse() {
1503   Node* node = jsgraph()->FalseConstant();
1504   environment()->BindAccumulator(node);
1505 }
1506 
VisitLdar()1507 void BytecodeGraphBuilder::VisitLdar() {
1508   Node* value =
1509       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1510   environment()->BindAccumulator(value);
1511 }
1512 
VisitStar()1513 void BytecodeGraphBuilder::VisitStar() {
1514   Node* value = environment()->LookupAccumulator();
1515   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value);
1516 }
1517 
1518 #define SHORT_STAR_VISITOR(Name, ...)                                         \
1519   void BytecodeGraphBuilder::Visit##Name() {                                  \
1520     Node* value = environment()->LookupAccumulator();                         \
1521     environment()->BindRegister(                                              \
1522         interpreter::Register::FromShortStar(interpreter::Bytecode::k##Name), \
1523         value);                                                               \
1524   }
1525 SHORT_STAR_BYTECODE_LIST(SHORT_STAR_VISITOR)
1526 #undef SHORT_STAR_VISITOR
1527 
VisitMov()1528 void BytecodeGraphBuilder::VisitMov() {
1529   Node* value =
1530       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1531   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value);
1532 }
1533 
BuildLoadGlobal(NameRef name, uint32_t feedback_slot_index, TypeofMode typeof_mode)1534 Node* BytecodeGraphBuilder::BuildLoadGlobal(NameRef name,
1535                                             uint32_t feedback_slot_index,
1536                                             TypeofMode typeof_mode) {
1537   FeedbackSource feedback = CreateFeedbackSource(feedback_slot_index);
1538   DCHECK(IsLoadGlobalICKind(broker()->GetFeedbackSlotKind(feedback)));
1539   const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
1540   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
1541   return NewNode(op, feedback_vector_node());
1542 }
1543 
VisitLdaGlobal()1544 void BytecodeGraphBuilder::VisitLdaGlobal() {
1545   PrepareEagerCheckpoint();
1546   NameRef name = MakeRefForConstantForIndexOperand<Name>(0);
1547   uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
1548   Node* node =
1549       BuildLoadGlobal(name, feedback_slot_index, TypeofMode::kNotInside);
1550   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1551 }
1552 
VisitLdaGlobalInsideTypeof()1553 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() {
1554   PrepareEagerCheckpoint();
1555   NameRef name = MakeRefForConstantForIndexOperand<Name>(0);
1556   uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
1557   Node* node = BuildLoadGlobal(name, feedback_slot_index, TypeofMode::kInside);
1558   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1559 }
1560 
VisitStaGlobal()1561 void BytecodeGraphBuilder::VisitStaGlobal() {
1562   PrepareEagerCheckpoint();
1563   NameRef name = MakeRefForConstantForIndexOperand<Name>(0);
1564   FeedbackSource feedback =
1565       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1));
1566   Node* value = environment()->LookupAccumulator();
1567 
1568   LanguageMode language_mode =
1569       GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(feedback));
1570   const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback);
1571   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
1572   Node* node = NewNode(op, value, feedback_vector_node());
1573   environment()->RecordAfterState(node, Environment::kAttachFrameState);
1574 }
1575 
VisitStaInArrayLiteral()1576 void BytecodeGraphBuilder::VisitStaInArrayLiteral() {
1577   PrepareEagerCheckpoint();
1578   Node* value = environment()->LookupAccumulator();
1579   Node* array =
1580       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1581   Node* index =
1582       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1583   FeedbackSource feedback =
1584       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2));
1585   const Operator* op = javascript()->StoreInArrayLiteral(feedback);
1586 
1587   JSTypeHintLowering::LoweringResult lowering =
1588       TryBuildSimplifiedStoreKeyed(op, array, index, value, feedback.slot);
1589   if (lowering.IsExit()) return;
1590 
1591   Node* node = nullptr;
1592   if (lowering.IsSideEffectFree()) {
1593     node = lowering.value();
1594   } else {
1595     DCHECK(!lowering.Changed());
1596     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
1597     node = NewNode(op, array, index, value, feedback_vector_node());
1598   }
1599 
1600   environment()->RecordAfterState(node, Environment::kAttachFrameState);
1601 }
1602 
VisitDefineKeyedOwnPropertyInLiteral()1603 void BytecodeGraphBuilder::VisitDefineKeyedOwnPropertyInLiteral() {
1604   PrepareEagerCheckpoint();
1605 
1606   Node* object =
1607       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1608   Node* name =
1609       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1610   Node* value = environment()->LookupAccumulator();
1611   int flags = bytecode_iterator().GetFlagOperand(2);
1612   FeedbackSource feedback =
1613       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(3));
1614   const Operator* op = javascript()->DefineKeyedOwnPropertyInLiteral(feedback);
1615 
1616   JSTypeHintLowering::LoweringResult lowering =
1617       TryBuildSimplifiedStoreKeyed(op, object, name, value, feedback.slot);
1618   if (lowering.IsExit()) return;
1619 
1620   Node* node = nullptr;
1621   if (lowering.IsSideEffectFree()) {
1622     node = lowering.value();
1623   } else {
1624     DCHECK(!lowering.Changed());
1625     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
1626     node = NewNode(op, object, name, value, jsgraph()->Constant(flags),
1627                    feedback_vector_node());
1628   }
1629 
1630   environment()->RecordAfterState(node, Environment::kAttachFrameState);
1631 }
1632 
VisitCollectTypeProfile()1633 void BytecodeGraphBuilder::VisitCollectTypeProfile() {
1634   PrepareEagerCheckpoint();
1635 
1636   Node* position =
1637       jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
1638   Node* value = environment()->LookupAccumulator();
1639   Node* vector = jsgraph()->Constant(feedback_vector());
1640 
1641   const Operator* op = javascript()->CallRuntime(Runtime::kCollectTypeProfile);
1642 
1643   Node* node = NewNode(op, position, value, vector);
1644   environment()->RecordAfterState(node, Environment::kAttachFrameState);
1645 }
1646 
VisitLdaContextSlot()1647 void BytecodeGraphBuilder::VisitLdaContextSlot() {
1648   const Operator* op = javascript()->LoadContext(
1649       bytecode_iterator().GetUnsignedImmediateOperand(2),
1650       bytecode_iterator().GetIndexOperand(1), false);
1651   Node* node = NewNode(op);
1652   Node* context =
1653       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1654   NodeProperties::ReplaceContextInput(node, context);
1655   environment()->BindAccumulator(node);
1656 }
1657 
VisitLdaImmutableContextSlot()1658 void BytecodeGraphBuilder::VisitLdaImmutableContextSlot() {
1659   const Operator* op = javascript()->LoadContext(
1660       bytecode_iterator().GetUnsignedImmediateOperand(2),
1661       bytecode_iterator().GetIndexOperand(1), true);
1662   Node* node = NewNode(op);
1663   Node* context =
1664       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1665   NodeProperties::ReplaceContextInput(node, context);
1666   environment()->BindAccumulator(node);
1667 }
1668 
VisitLdaCurrentContextSlot()1669 void BytecodeGraphBuilder::VisitLdaCurrentContextSlot() {
1670   const Operator* op = javascript()->LoadContext(
1671       0, bytecode_iterator().GetIndexOperand(0), false);
1672   Node* node = NewNode(op);
1673   environment()->BindAccumulator(node);
1674 }
1675 
VisitLdaImmutableCurrentContextSlot()1676 void BytecodeGraphBuilder::VisitLdaImmutableCurrentContextSlot() {
1677   const Operator* op = javascript()->LoadContext(
1678       0, bytecode_iterator().GetIndexOperand(0), true);
1679   Node* node = NewNode(op);
1680   environment()->BindAccumulator(node);
1681 }
1682 
VisitStaContextSlot()1683 void BytecodeGraphBuilder::VisitStaContextSlot() {
1684   const Operator* op = javascript()->StoreContext(
1685       bytecode_iterator().GetUnsignedImmediateOperand(2),
1686       bytecode_iterator().GetIndexOperand(1));
1687   Node* value = environment()->LookupAccumulator();
1688   Node* node = NewNode(op, value);
1689   Node* context =
1690       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1691   NodeProperties::ReplaceContextInput(node, context);
1692 }
1693 
VisitStaCurrentContextSlot()1694 void BytecodeGraphBuilder::VisitStaCurrentContextSlot() {
1695   const Operator* op =
1696       javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(0));
1697   Node* value = environment()->LookupAccumulator();
1698   NewNode(op, value);
1699 }
1700 
BuildLdaLookupSlot(TypeofMode typeof_mode)1701 void BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) {
1702   PrepareEagerCheckpoint();
1703   Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0));
1704   const Operator* op =
1705       javascript()->CallRuntime(typeof_mode == TypeofMode::kNotInside
1706                                     ? Runtime::kLoadLookupSlot
1707                                     : Runtime::kLoadLookupSlotInsideTypeof);
1708   Node* value = NewNode(op, name);
1709   environment()->BindAccumulator(value, Environment::kAttachFrameState);
1710 }
1711 
VisitLdaLookupSlot()1712 void BytecodeGraphBuilder::VisitLdaLookupSlot() {
1713   BuildLdaLookupSlot(TypeofMode::kNotInside);
1714 }
1715 
VisitLdaLookupSlotInsideTypeof()1716 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
1717   BuildLdaLookupSlot(TypeofMode::kInside);
1718 }
1719 
1720 BytecodeGraphBuilder::Environment*
CheckContextExtensionAtDepth( Environment* slow_environment, uint32_t depth)1721 BytecodeGraphBuilder::CheckContextExtensionAtDepth(
1722     Environment* slow_environment, uint32_t depth) {
1723   Node* extension_slot = NewNode(
1724       javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false));
1725   Node* check_no_extension =
1726       NewNode(simplified()->ReferenceEqual(), extension_slot,
1727               jsgraph()->UndefinedConstant());
1728   NewBranch(check_no_extension);
1729   {
1730     SubEnvironment sub_environment(this);
1731     NewIfFalse();
1732     // If there is an extension, merge into the slow path.
1733     if (slow_environment == nullptr) {
1734       slow_environment = environment();
1735       NewMerge();
1736     } else {
1737       slow_environment->Merge(environment(),
1738                               bytecode_analysis().GetInLivenessFor(
1739                                   bytecode_iterator().current_offset()));
1740     }
1741   }
1742   NewIfTrue();
1743   // Do nothing on if there is no extension, eventually falling through to
1744   // the fast path.
1745   DCHECK_NOT_NULL(slow_environment);
1746   return slow_environment;
1747 }
1748 
TryGetScopeInfo()1749 base::Optional<ScopeInfoRef> BytecodeGraphBuilder::TryGetScopeInfo() {
1750   Node* context = environment()->Context();
1751   switch (context->opcode()) {
1752     case IrOpcode::kJSCreateFunctionContext:
1753       return CreateFunctionContextParametersOf(context->op())
1754           .scope_info(broker());
1755     case IrOpcode::kJSCreateBlockContext:
1756     case IrOpcode::kJSCreateCatchContext:
1757     case IrOpcode::kJSCreateWithContext:
1758       return ScopeInfoOf(broker(), context->op());
1759     case IrOpcode::kParameter: {
1760       ScopeInfoRef scope_info = shared_info_.scope_info();
1761       if (scope_info.HasOuterScopeInfo()) {
1762         scope_info = scope_info.OuterScopeInfo();
1763       }
1764       return scope_info;
1765     }
1766     default:
1767       return base::nullopt;
1768   }
1769 }
1770 
CheckContextExtensions( uint32_t depth)1771 BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions(
1772     uint32_t depth) {
1773   base::Optional<ScopeInfoRef> maybe_scope_info = TryGetScopeInfo();
1774   if (!maybe_scope_info.has_value()) {
1775     return CheckContextExtensionsSlowPath(depth);
1776   }
1777 
1778   ScopeInfoRef scope_info = maybe_scope_info.value();
1779   // We only need to check up to the last-but-one depth, because an eval
1780   // in the same scope as the variable itself has no way of shadowing it.
1781   Environment* slow_environment = nullptr;
1782   for (uint32_t d = 0; d < depth; d++) {
1783     if (scope_info.HasContextExtensionSlot()) {
1784       slow_environment = CheckContextExtensionAtDepth(slow_environment, d);
1785     }
1786     DCHECK_IMPLIES(!scope_info.HasOuterScopeInfo(), d + 1 == depth);
1787     if (scope_info.HasOuterScopeInfo()) {
1788       scope_info = scope_info.OuterScopeInfo();
1789     }
1790   }
1791 
1792   // The depth can be zero, in which case no slow-path checks are built, and
1793   // the slow path environment can be null.
1794   DCHECK_IMPLIES(slow_environment == nullptr, depth == 0);
1795   return slow_environment;
1796 }
1797 
1798 BytecodeGraphBuilder::Environment*
CheckContextExtensionsSlowPath(uint32_t depth)1799 BytecodeGraphBuilder::CheckContextExtensionsSlowPath(uint32_t depth) {
1800   // Output environment where the context has an extension
1801   Environment* slow_environment = nullptr;
1802 
1803   // We only need to check up to the last-but-one depth, because an eval
1804   // in the same scope as the variable itself has no way of shadowing it.
1805   for (uint32_t d = 0; d < depth; d++) {
1806     Node* has_extension = NewNode(javascript()->HasContextExtension(d));
1807 
1808     Environment* undefined_extension_env;
1809     NewBranch(has_extension);
1810     {
1811       SubEnvironment sub_environment(this);
1812       NewIfTrue();
1813       slow_environment = CheckContextExtensionAtDepth(slow_environment, d);
1814       undefined_extension_env = environment();
1815     }
1816     NewIfFalse();
1817     environment()->Merge(undefined_extension_env,
1818                          bytecode_analysis().GetInLivenessFor(
1819                              bytecode_iterator().current_offset()));
1820     mark_as_needing_eager_checkpoint(true);
1821     // Do nothing on if there is no extension, eventually falling through to
1822     // the fast path.
1823   }
1824 
1825   // The depth can be zero, in which case no slow-path checks are built, and
1826   // the slow path environment can be null.
1827   DCHECK_IMPLIES(slow_environment == nullptr, depth == 0);
1828   return slow_environment;
1829 }
1830 
BuildLdaLookupContextSlot(TypeofMode typeof_mode)1831 void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) {
1832   uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
1833 
1834   // Check if any context in the depth has an extension.
1835   Environment* slow_environment = CheckContextExtensions(depth);
1836 
1837   // Fast path, do a context load.
1838   {
1839     uint32_t slot_index = bytecode_iterator().GetIndexOperand(1);
1840 
1841     const Operator* op = javascript()->LoadContext(depth, slot_index, false);
1842     environment()->BindAccumulator(NewNode(op));
1843   }
1844 
1845   // Only build the slow path if there were any slow-path checks.
1846   if (slow_environment != nullptr) {
1847     // Add a merge to the fast environment.
1848     NewMerge();
1849     Environment* fast_environment = environment();
1850 
1851     // Slow path, do a runtime load lookup.
1852     set_environment(slow_environment);
1853     {
1854       Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0));
1855 
1856       const Operator* op =
1857           javascript()->CallRuntime(typeof_mode == TypeofMode::kNotInside
1858                                         ? Runtime::kLoadLookupSlot
1859                                         : Runtime::kLoadLookupSlotInsideTypeof);
1860       Node* value = NewNode(op, name);
1861       environment()->BindAccumulator(value, Environment::kAttachFrameState);
1862     }
1863 
1864     fast_environment->Merge(environment(),
1865                             bytecode_analysis().GetOutLivenessFor(
1866                                 bytecode_iterator().current_offset()));
1867     set_environment(fast_environment);
1868     mark_as_needing_eager_checkpoint(true);
1869   }
1870 }
1871 
VisitLdaLookupContextSlot()1872 void BytecodeGraphBuilder::VisitLdaLookupContextSlot() {
1873   BuildLdaLookupContextSlot(TypeofMode::kNotInside);
1874 }
1875 
VisitLdaLookupContextSlotInsideTypeof()1876 void BytecodeGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() {
1877   BuildLdaLookupContextSlot(TypeofMode::kInside);
1878 }
1879 
BuildLdaLookupGlobalSlot(TypeofMode typeof_mode)1880 void BytecodeGraphBuilder::BuildLdaLookupGlobalSlot(TypeofMode typeof_mode) {
1881   uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
1882 
1883   // Check if any context in the depth has an extension.
1884   Environment* slow_environment = CheckContextExtensions(depth);
1885 
1886   // Fast path, do a global load.
1887   {
1888     PrepareEagerCheckpoint();
1889     NameRef name = MakeRefForConstantForIndexOperand<Name>(0);
1890     uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
1891     Node* node = BuildLoadGlobal(name, feedback_slot_index, typeof_mode);
1892     environment()->BindAccumulator(node, Environment::kAttachFrameState);
1893   }
1894 
1895   // Only build the slow path if there were any slow-path checks.
1896   if (slow_environment != nullptr) {
1897     // Add a merge to the fast environment.
1898     NewMerge();
1899     Environment* fast_environment = environment();
1900 
1901     // Slow path, do a runtime load lookup.
1902     set_environment(slow_environment);
1903     {
1904       Node* name =
1905           jsgraph()->Constant(MakeRefForConstantForIndexOperand<Name>(0));
1906 
1907       const Operator* op =
1908           javascript()->CallRuntime(typeof_mode == TypeofMode::kNotInside
1909                                         ? Runtime::kLoadLookupSlot
1910                                         : Runtime::kLoadLookupSlotInsideTypeof);
1911       Node* value = NewNode(op, name);
1912       environment()->BindAccumulator(value, Environment::kAttachFrameState);
1913     }
1914 
1915     fast_environment->Merge(environment(),
1916                             bytecode_analysis().GetOutLivenessFor(
1917                                 bytecode_iterator().current_offset()));
1918     set_environment(fast_environment);
1919     mark_as_needing_eager_checkpoint(true);
1920   }
1921 }
1922 
VisitLdaLookupGlobalSlot()1923 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlot() {
1924   BuildLdaLookupGlobalSlot(TypeofMode::kNotInside);
1925 }
1926 
VisitLdaLookupGlobalSlotInsideTypeof()1927 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() {
1928   BuildLdaLookupGlobalSlot(TypeofMode::kInside);
1929 }
1930 
VisitStaLookupSlot()1931 void BytecodeGraphBuilder::VisitStaLookupSlot() {
1932   PrepareEagerCheckpoint();
1933   Node* value = environment()->LookupAccumulator();
1934   Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0));
1935   int bytecode_flags = bytecode_iterator().GetFlagOperand(1);
1936   LanguageMode language_mode = static_cast<LanguageMode>(
1937       interpreter::StoreLookupSlotFlags::LanguageModeBit::decode(
1938           bytecode_flags));
1939   LookupHoistingMode lookup_hoisting_mode = static_cast<LookupHoistingMode>(
1940       interpreter::StoreLookupSlotFlags::LookupHoistingModeBit::decode(
1941           bytecode_flags));
1942   DCHECK_IMPLIES(lookup_hoisting_mode == LookupHoistingMode::kLegacySloppy,
1943                  is_sloppy(language_mode));
1944   const Operator* op = javascript()->CallRuntime(
1945       is_strict(language_mode)
1946           ? Runtime::kStoreLookupSlot_Strict
1947           : lookup_hoisting_mode == LookupHoistingMode::kLegacySloppy
1948                 ? Runtime::kStoreLookupSlot_SloppyHoisting
1949                 : Runtime::kStoreLookupSlot_Sloppy);
1950   Node* store = NewNode(op, name, value);
1951   environment()->BindAccumulator(store, Environment::kAttachFrameState);
1952 }
1953 
VisitGetNamedProperty()1954 void BytecodeGraphBuilder::VisitGetNamedProperty() {
1955   PrepareEagerCheckpoint();
1956   Node* object =
1957       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1958   NameRef name = MakeRefForConstantForIndexOperand<Name>(1);
1959   FeedbackSource feedback =
1960       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2));
1961   const Operator* op = javascript()->LoadNamed(name, feedback);
1962 
1963   JSTypeHintLowering::LoweringResult lowering =
1964       TryBuildSimplifiedLoadNamed(op, feedback.slot);
1965   if (lowering.IsExit()) return;
1966 
1967   Node* node = nullptr;
1968   if (lowering.IsSideEffectFree()) {
1969     node = lowering.value();
1970   } else {
1971     DCHECK(!lowering.Changed());
1972     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
1973     node = NewNode(op, object, feedback_vector_node());
1974   }
1975   environment()->BindAccumulator(node, Environment::kAttachFrameState);
1976 }
1977 
VisitGetNamedPropertyFromSuper()1978 void BytecodeGraphBuilder::VisitGetNamedPropertyFromSuper() {
1979   PrepareEagerCheckpoint();
1980   Node* receiver =
1981       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1982   Node* home_object = environment()->LookupAccumulator();
1983   NameRef name = MakeRefForConstantForIndexOperand<Name>(1);
1984 
1985   FeedbackSource feedback =
1986       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2));
1987   const Operator* op = javascript()->LoadNamedFromSuper(name, feedback);
1988 
1989   JSTypeHintLowering::LoweringResult lowering =
1990       TryBuildSimplifiedLoadNamed(op, feedback.slot);
1991   if (lowering.IsExit()) return;
1992 
1993   Node* node = nullptr;
1994   if (lowering.IsSideEffectFree()) {
1995     node = lowering.value();
1996   } else {
1997     DCHECK(!lowering.Changed());
1998     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
1999     node = NewNode(op, receiver, home_object, feedback_vector_node());
2000   }
2001   environment()->BindAccumulator(node, Environment::kAttachFrameState);
2002 }
2003 
VisitGetKeyedProperty()2004 void BytecodeGraphBuilder::VisitGetKeyedProperty() {
2005   PrepareEagerCheckpoint();
2006   Node* key = environment()->LookupAccumulator();
2007   Node* object =
2008       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2009   FeedbackSource feedback =
2010       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1));
2011   const Operator* op = javascript()->LoadProperty(feedback);
2012 
2013   JSTypeHintLowering::LoweringResult lowering =
2014       TryBuildSimplifiedLoadKeyed(op, object, key, feedback.slot);
2015   if (lowering.IsExit()) return;
2016 
2017   Node* node = nullptr;
2018   if (lowering.IsSideEffectFree()) {
2019     node = lowering.value();
2020   } else {
2021     DCHECK(!lowering.Changed());
2022     STATIC_ASSERT(JSLoadPropertyNode::ObjectIndex() == 0);
2023     STATIC_ASSERT(JSLoadPropertyNode::KeyIndex() == 1);
2024     STATIC_ASSERT(JSLoadPropertyNode::FeedbackVectorIndex() == 2);
2025     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2026     node = NewNode(op, object, key, feedback_vector_node());
2027   }
2028   environment()->BindAccumulator(node, Environment::kAttachFrameState);
2029 }
2030 
BuildNamedStore(NamedStoreMode store_mode)2031 void BytecodeGraphBuilder::BuildNamedStore(NamedStoreMode store_mode) {
2032   PrepareEagerCheckpoint();
2033   Node* value = environment()->LookupAccumulator();
2034   Node* object =
2035       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2036   NameRef name = MakeRefForConstantForIndexOperand<Name>(1);
2037   FeedbackSource feedback =
2038       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2));
2039 
2040   const Operator* op;
2041   if (store_mode == NamedStoreMode::kDefineOwn) {
2042     DCHECK_EQ(FeedbackSlotKind::kDefineNamedOwn,
2043               broker()->GetFeedbackSlotKind(feedback));
2044 
2045     op = javascript()->DefineNamedOwnProperty(name, feedback);
2046   } else {
2047     DCHECK_EQ(NamedStoreMode::kSet, store_mode);
2048     LanguageMode language_mode =
2049         GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(feedback));
2050     op = javascript()->SetNamedProperty(language_mode, name, feedback);
2051   }
2052 
2053   JSTypeHintLowering::LoweringResult lowering =
2054       TryBuildSimplifiedStoreNamed(op, object, value, feedback.slot);
2055   if (lowering.IsExit()) return;
2056 
2057   Node* node = nullptr;
2058   if (lowering.IsSideEffectFree()) {
2059     node = lowering.value();
2060   } else {
2061     DCHECK(!lowering.Changed());
2062     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2063     node = NewNode(op, object, value, feedback_vector_node());
2064   }
2065   environment()->RecordAfterState(node, Environment::kAttachFrameState);
2066 }
2067 
VisitSetNamedProperty()2068 void BytecodeGraphBuilder::VisitSetNamedProperty() {
2069   BuildNamedStore(NamedStoreMode::kSet);
2070 }
2071 
VisitDefineNamedOwnProperty()2072 void BytecodeGraphBuilder::VisitDefineNamedOwnProperty() {
2073   BuildNamedStore(NamedStoreMode::kDefineOwn);
2074 }
2075 
VisitSetKeyedProperty()2076 void BytecodeGraphBuilder::VisitSetKeyedProperty() {
2077   PrepareEagerCheckpoint();
2078   Node* value = environment()->LookupAccumulator();
2079   Node* object =
2080       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2081   Node* key =
2082       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2083   FeedbackSource source =
2084       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2));
2085   LanguageMode language_mode =
2086       GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(source));
2087   const Operator* op = javascript()->SetKeyedProperty(language_mode, source);
2088 
2089   JSTypeHintLowering::LoweringResult lowering =
2090       TryBuildSimplifiedStoreKeyed(op, object, key, value, source.slot);
2091   if (lowering.IsExit()) return;
2092 
2093   Node* node = nullptr;
2094   if (lowering.IsSideEffectFree()) {
2095     node = lowering.value();
2096   } else {
2097     DCHECK(!lowering.Changed());
2098     STATIC_ASSERT(JSSetKeyedPropertyNode::ObjectIndex() == 0);
2099     STATIC_ASSERT(JSSetKeyedPropertyNode::KeyIndex() == 1);
2100     STATIC_ASSERT(JSSetKeyedPropertyNode::ValueIndex() == 2);
2101     STATIC_ASSERT(JSSetKeyedPropertyNode::FeedbackVectorIndex() == 3);
2102     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2103     node = NewNode(op, object, key, value, feedback_vector_node());
2104   }
2105 
2106   environment()->RecordAfterState(node, Environment::kAttachFrameState);
2107 }
2108 
VisitDefineKeyedOwnProperty()2109 void BytecodeGraphBuilder::VisitDefineKeyedOwnProperty() {
2110   PrepareEagerCheckpoint();
2111   Node* value = environment()->LookupAccumulator();
2112   Node* object =
2113       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2114   Node* key =
2115       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2116   FeedbackSource source =
2117       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2));
2118   LanguageMode language_mode =
2119       GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(source));
2120 
2121   const Operator* op =
2122       javascript()->DefineKeyedOwnProperty(language_mode, source);
2123 
2124   JSTypeHintLowering::LoweringResult lowering =
2125       TryBuildSimplifiedStoreKeyed(op, object, key, value, source.slot);
2126   if (lowering.IsExit()) return;
2127 
2128   Node* node = nullptr;
2129   if (lowering.IsSideEffectFree()) {
2130     node = lowering.value();
2131   } else {
2132     DCHECK(!lowering.Changed());
2133     STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::ObjectIndex() == 0);
2134     STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::KeyIndex() == 1);
2135     STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::ValueIndex() == 2);
2136     STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::FeedbackVectorIndex() == 3);
2137     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2138     node = NewNode(op, object, key, value, feedback_vector_node());
2139   }
2140 
2141   environment()->RecordAfterState(node, Environment::kAttachFrameState);
2142 }
2143 
VisitLdaModuleVariable()2144 void BytecodeGraphBuilder::VisitLdaModuleVariable() {
2145   int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
2146   uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
2147   Node* module =
2148       NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true));
2149   Node* value = NewNode(javascript()->LoadModule(cell_index), module);
2150   environment()->BindAccumulator(value);
2151 }
2152 
VisitStaModuleVariable()2153 void BytecodeGraphBuilder::VisitStaModuleVariable() {
2154   int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
2155   uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
2156   Node* module =
2157       NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true));
2158   Node* value = environment()->LookupAccumulator();
2159   NewNode(javascript()->StoreModule(cell_index), module, value);
2160 }
2161 
VisitPushContext()2162 void BytecodeGraphBuilder::VisitPushContext() {
2163   Node* new_context = environment()->LookupAccumulator();
2164   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0),
2165                               environment()->Context());
2166   environment()->SetContext(new_context);
2167 }
2168 
VisitPopContext()2169 void BytecodeGraphBuilder::VisitPopContext() {
2170   Node* context =
2171       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2172   environment()->SetContext(context);
2173 }
2174 
VisitCreateClosure()2175 void BytecodeGraphBuilder::VisitCreateClosure() {
2176   SharedFunctionInfoRef shared_info =
2177       MakeRefForConstantForIndexOperand<SharedFunctionInfo>(0);
2178   AllocationType allocation =
2179       interpreter::CreateClosureFlags::PretenuredBit::decode(
2180           bytecode_iterator().GetFlagOperand(2))
2181           ? AllocationType::kOld
2182           : AllocationType::kYoung;
2183   CodeTRef compile_lazy =
2184       MakeRef(broker(), *BUILTIN_CODE(jsgraph()->isolate(), CompileLazy));
2185   const Operator* op =
2186       javascript()->CreateClosure(shared_info, compile_lazy, allocation);
2187   Node* closure = NewNode(
2188       op, BuildLoadFeedbackCell(bytecode_iterator().GetIndexOperand(1)));
2189   environment()->BindAccumulator(closure);
2190 }
2191 
VisitCreateBlockContext()2192 void BytecodeGraphBuilder::VisitCreateBlockContext() {
2193   ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(0);
2194   const Operator* op = javascript()->CreateBlockContext(scope_info);
2195   Node* context = NewNode(op);
2196   environment()->BindAccumulator(context);
2197 }
2198 
VisitCreateFunctionContext()2199 void BytecodeGraphBuilder::VisitCreateFunctionContext() {
2200   ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(0);
2201   uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(1);
2202   const Operator* op =
2203       javascript()->CreateFunctionContext(scope_info, slots, FUNCTION_SCOPE);
2204   Node* context = NewNode(op);
2205   environment()->BindAccumulator(context);
2206 }
2207 
VisitCreateEvalContext()2208 void BytecodeGraphBuilder::VisitCreateEvalContext() {
2209   ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(0);
2210   uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(1);
2211   const Operator* op =
2212       javascript()->CreateFunctionContext(scope_info, slots, EVAL_SCOPE);
2213   Node* context = NewNode(op);
2214   environment()->BindAccumulator(context);
2215 }
2216 
VisitCreateCatchContext()2217 void BytecodeGraphBuilder::VisitCreateCatchContext() {
2218   interpreter::Register reg = bytecode_iterator().GetRegisterOperand(0);
2219   Node* exception = environment()->LookupRegister(reg);
2220   ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(1);
2221 
2222   const Operator* op = javascript()->CreateCatchContext(scope_info);
2223   Node* context = NewNode(op, exception);
2224   environment()->BindAccumulator(context);
2225 }
2226 
VisitCreateWithContext()2227 void BytecodeGraphBuilder::VisitCreateWithContext() {
2228   Node* object =
2229       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2230   ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(1);
2231 
2232   const Operator* op = javascript()->CreateWithContext(scope_info);
2233   Node* context = NewNode(op, object);
2234   environment()->BindAccumulator(context);
2235 }
2236 
BuildCreateArguments(CreateArgumentsType type)2237 void BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) {
2238   const Operator* op = javascript()->CreateArguments(type);
2239   Node* object = NewNode(op, GetFunctionClosure());
2240   environment()->BindAccumulator(object, Environment::kAttachFrameState);
2241 }
2242 
VisitCreateMappedArguments()2243 void BytecodeGraphBuilder::VisitCreateMappedArguments() {
2244   BuildCreateArguments(CreateArgumentsType::kMappedArguments);
2245 }
2246 
VisitCreateUnmappedArguments()2247 void BytecodeGraphBuilder::VisitCreateUnmappedArguments() {
2248   BuildCreateArguments(CreateArgumentsType::kUnmappedArguments);
2249 }
2250 
VisitCreateRestParameter()2251 void BytecodeGraphBuilder::VisitCreateRestParameter() {
2252   BuildCreateArguments(CreateArgumentsType::kRestParameter);
2253 }
2254 
VisitCreateRegExpLiteral()2255 void BytecodeGraphBuilder::VisitCreateRegExpLiteral() {
2256   StringRef constant_pattern = MakeRefForConstantForIndexOperand<String>(0);
2257   int const slot_id = bytecode_iterator().GetIndexOperand(1);
2258   FeedbackSource pair = CreateFeedbackSource(slot_id);
2259   int literal_flags = bytecode_iterator().GetFlagOperand(2);
2260   STATIC_ASSERT(JSCreateLiteralRegExpNode::FeedbackVectorIndex() == 0);
2261   const Operator* op =
2262       javascript()->CreateLiteralRegExp(constant_pattern, pair, literal_flags);
2263   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2264   Node* literal = NewNode(op, feedback_vector_node());
2265   environment()->BindAccumulator(literal, Environment::kAttachFrameState);
2266 }
2267 
VisitCreateArrayLiteral()2268 void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
2269   ArrayBoilerplateDescriptionRef array_boilerplate_description =
2270       MakeRefForConstantForIndexOperand<ArrayBoilerplateDescription>(0);
2271   int const slot_id = bytecode_iterator().GetIndexOperand(1);
2272   FeedbackSource pair = CreateFeedbackSource(slot_id);
2273   int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
2274   int literal_flags =
2275       interpreter::CreateArrayLiteralFlags::FlagsBits::decode(bytecode_flags);
2276   // Disable allocation site mementos. Only unoptimized code will collect
2277   // feedback about allocation site. Once the code is optimized we expect the
2278   // data to converge. So, we disable allocation site mementos in optimized
2279   // code. We can revisit this when we have data to the contrary.
2280   literal_flags |= ArrayLiteral::kDisableMementos;
2281   int number_of_elements =
2282       array_boilerplate_description.constants_elements_length();
2283   STATIC_ASSERT(JSCreateLiteralArrayNode::FeedbackVectorIndex() == 0);
2284   const Operator* op = javascript()->CreateLiteralArray(
2285       array_boilerplate_description, pair, literal_flags, number_of_elements);
2286   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2287   Node* literal = NewNode(op, feedback_vector_node());
2288   environment()->BindAccumulator(literal, Environment::kAttachFrameState);
2289 }
2290 
VisitCreateEmptyArrayLiteral()2291 void BytecodeGraphBuilder::VisitCreateEmptyArrayLiteral() {
2292   int const slot_id = bytecode_iterator().GetIndexOperand(0);
2293   FeedbackSource pair = CreateFeedbackSource(slot_id);
2294   const Operator* op = javascript()->CreateEmptyLiteralArray(pair);
2295   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2296   Node* literal = NewNode(op, feedback_vector_node());
2297   environment()->BindAccumulator(literal);
2298 }
2299 
VisitCreateArrayFromIterable()2300 void BytecodeGraphBuilder::VisitCreateArrayFromIterable() {
2301   Node* iterable = NewNode(javascript()->CreateArrayFromIterable(),
2302                            environment()->LookupAccumulator());
2303   environment()->BindAccumulator(iterable, Environment::kAttachFrameState);
2304 }
2305 
VisitCreateObjectLiteral()2306 void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
2307   ObjectBoilerplateDescriptionRef constant_properties =
2308       MakeRefForConstantForIndexOperand<ObjectBoilerplateDescription>(0);
2309   int const slot_id = bytecode_iterator().GetIndexOperand(1);
2310   FeedbackSource pair = CreateFeedbackSource(slot_id);
2311   int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
2312   int literal_flags =
2313       interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
2314   int number_of_properties = constant_properties.size();
2315   STATIC_ASSERT(JSCreateLiteralObjectNode::FeedbackVectorIndex() == 0);
2316   const Operator* op = javascript()->CreateLiteralObject(
2317       constant_properties, pair, literal_flags, number_of_properties);
2318   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2319   Node* literal = NewNode(op, feedback_vector_node());
2320   environment()->BindAccumulator(literal, Environment::kAttachFrameState);
2321 }
2322 
VisitCreateEmptyObjectLiteral()2323 void BytecodeGraphBuilder::VisitCreateEmptyObjectLiteral() {
2324   Node* literal = NewNode(javascript()->CreateEmptyLiteralObject());
2325   environment()->BindAccumulator(literal);
2326 }
2327 
VisitCloneObject()2328 void BytecodeGraphBuilder::VisitCloneObject() {
2329   PrepareEagerCheckpoint();
2330   Node* source =
2331       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2332   int flags = bytecode_iterator().GetFlagOperand(1);
2333   int slot = bytecode_iterator().GetIndexOperand(2);
2334   const Operator* op =
2335       javascript()->CloneObject(CreateFeedbackSource(slot), flags);
2336   STATIC_ASSERT(JSCloneObjectNode::SourceIndex() == 0);
2337   STATIC_ASSERT(JSCloneObjectNode::FeedbackVectorIndex() == 1);
2338   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2339   Node* value = NewNode(op, source, feedback_vector_node());
2340   environment()->BindAccumulator(value, Environment::kAttachFrameState);
2341 }
2342 
VisitGetTemplateObject()2343 void BytecodeGraphBuilder::VisitGetTemplateObject() {
2344   FeedbackSource source =
2345       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1));
2346   TemplateObjectDescriptionRef description =
2347       MakeRefForConstantForIndexOperand<TemplateObjectDescription>(0);
2348   STATIC_ASSERT(JSGetTemplateObjectNode::FeedbackVectorIndex() == 0);
2349   const Operator* op =
2350       javascript()->GetTemplateObject(description, shared_info(), source);
2351   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2352   Node* template_object = NewNode(op, feedback_vector_node());
2353   environment()->BindAccumulator(template_object);
2354 }
2355 
GetCallArgumentsFromRegisters( Node* callee, Node* receiver, interpreter::Register first_arg, int arg_count)2356 Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegisters(
2357     Node* callee, Node* receiver, interpreter::Register first_arg,
2358     int arg_count) {
2359   const int arity = JSCallNode::ArityForArgc(arg_count);
2360   Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
2361   int cursor = 0;
2362 
2363   STATIC_ASSERT(JSCallNode::TargetIndex() == 0);
2364   STATIC_ASSERT(JSCallNode::ReceiverIndex() == 1);
2365   STATIC_ASSERT(JSCallNode::FirstArgumentIndex() == 2);
2366   STATIC_ASSERT(JSCallNode::kFeedbackVectorIsLastInput);
2367 
2368   all[cursor++] = callee;
2369   all[cursor++] = receiver;
2370 
2371   // The function arguments are in consecutive registers.
2372   const int arg_base = first_arg.index();
2373   for (int i = 0; i < arg_count; ++i) {
2374     all[cursor++] =
2375         environment()->LookupRegister(interpreter::Register(arg_base + i));
2376   }
2377 
2378   all[cursor++] = feedback_vector_node();
2379 
2380   DCHECK_EQ(cursor, arity);
2381   return all;
2382 }
2383 
BuildCall(ConvertReceiverMode receiver_mode, Node* const* args, size_t arg_count, int slot_id)2384 void BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode,
2385                                      Node* const* args, size_t arg_count,
2386                                      int slot_id) {
2387   DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode(
2388                 bytecode_iterator().current_bytecode()),
2389             receiver_mode);
2390   PrepareEagerCheckpoint();
2391 
2392   FeedbackSource feedback = CreateFeedbackSource(slot_id);
2393   CallFrequency frequency = ComputeCallFrequency(slot_id);
2394   SpeculationMode speculation_mode = GetSpeculationMode(slot_id);
2395   CallFeedbackRelation call_feedback_relation =
2396       ComputeCallFeedbackRelation(slot_id);
2397   const Operator* op =
2398       javascript()->Call(arg_count, frequency, feedback, receiver_mode,
2399                          speculation_mode, call_feedback_relation);
2400   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2401 
2402   JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall(
2403       op, args, static_cast<int>(arg_count), feedback.slot);
2404   if (lowering.IsExit()) return;
2405 
2406   Node* node = nullptr;
2407   if (lowering.IsSideEffectFree()) {
2408     node = lowering.value();
2409   } else {
2410     DCHECK(!lowering.Changed());
2411     node = MakeNode(op, static_cast<int>(arg_count), args);
2412   }
2413   environment()->BindAccumulator(node, Environment::kAttachFrameState);
2414 }
2415 
ProcessCallVarArgs( ConvertReceiverMode receiver_mode, Node* callee, interpreter::Register first_reg, int arg_count)2416 Node* const* BytecodeGraphBuilder::ProcessCallVarArgs(
2417     ConvertReceiverMode receiver_mode, Node* callee,
2418     interpreter::Register first_reg, int arg_count) {
2419   DCHECK_GE(arg_count, 0);
2420   Node* receiver_node;
2421   interpreter::Register first_arg;
2422 
2423   if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
2424     // The receiver is implicit (and undefined), the arguments are in
2425     // consecutive registers.
2426     receiver_node = jsgraph()->UndefinedConstant();
2427     first_arg = first_reg;
2428   } else {
2429     // The receiver is the first register, followed by the arguments in the
2430     // consecutive registers.
2431     receiver_node = environment()->LookupRegister(first_reg);
2432     first_arg = interpreter::Register(first_reg.index() + 1);
2433   }
2434 
2435   Node* const* call_args = GetCallArgumentsFromRegisters(callee, receiver_node,
2436                                                          first_arg, arg_count);
2437   return call_args;
2438 }
2439 
BuildCallVarArgs(ConvertReceiverMode receiver_mode)2440 void BytecodeGraphBuilder::BuildCallVarArgs(ConvertReceiverMode receiver_mode) {
2441   DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode(
2442                 bytecode_iterator().current_bytecode()),
2443             receiver_mode);
2444   Node* callee =
2445       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2446   interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
2447   size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
2448   int const slot_id = bytecode_iterator().GetIndexOperand(3);
2449 
2450   int arg_count = receiver_mode == ConvertReceiverMode::kNullOrUndefined
2451                       ? static_cast<int>(reg_count)
2452                       : static_cast<int>(reg_count) - 1;
2453   Node* const* call_args =
2454       ProcessCallVarArgs(receiver_mode, callee, first_reg, arg_count);
2455   BuildCall(receiver_mode, call_args, JSCallNode::ArityForArgc(arg_count),
2456             slot_id);
2457 }
2458 
VisitCallAnyReceiver()2459 void BytecodeGraphBuilder::VisitCallAnyReceiver() {
2460   BuildCallVarArgs(ConvertReceiverMode::kAny);
2461 }
2462 
VisitCallProperty()2463 void BytecodeGraphBuilder::VisitCallProperty() {
2464   BuildCallVarArgs(ConvertReceiverMode::kNotNullOrUndefined);
2465 }
2466 
VisitCallProperty0()2467 void BytecodeGraphBuilder::VisitCallProperty0() {
2468   Node* callee =
2469       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2470   Node* receiver =
2471       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2472   int const slot_id = bytecode_iterator().GetIndexOperand(2);
2473   BuildCall(ConvertReceiverMode::kNotNullOrUndefined,
2474             {callee, receiver, feedback_vector_node()}, slot_id);
2475 }
2476 
VisitCallProperty1()2477 void BytecodeGraphBuilder::VisitCallProperty1() {
2478   Node* callee =
2479       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2480   Node* receiver =
2481       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2482   Node* arg0 =
2483       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
2484   int const slot_id = bytecode_iterator().GetIndexOperand(3);
2485   BuildCall(ConvertReceiverMode::kNotNullOrUndefined,
2486             {callee, receiver, arg0, feedback_vector_node()}, slot_id);
2487 }
2488 
VisitCallProperty2()2489 void BytecodeGraphBuilder::VisitCallProperty2() {
2490   Node* callee =
2491       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2492   Node* receiver =
2493       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2494   Node* arg0 =
2495       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
2496   Node* arg1 =
2497       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(3));
2498   int const slot_id = bytecode_iterator().GetIndexOperand(4);
2499   BuildCall(ConvertReceiverMode::kNotNullOrUndefined,
2500             {callee, receiver, arg0, arg1, feedback_vector_node()}, slot_id);
2501 }
2502 
VisitCallUndefinedReceiver()2503 void BytecodeGraphBuilder::VisitCallUndefinedReceiver() {
2504   BuildCallVarArgs(ConvertReceiverMode::kNullOrUndefined);
2505 }
2506 
VisitCallUndefinedReceiver0()2507 void BytecodeGraphBuilder::VisitCallUndefinedReceiver0() {
2508   Node* callee =
2509       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2510   Node* receiver = jsgraph()->UndefinedConstant();
2511   int const slot_id = bytecode_iterator().GetIndexOperand(1);
2512   BuildCall(ConvertReceiverMode::kNullOrUndefined,
2513             {callee, receiver, feedback_vector_node()}, slot_id);
2514 }
2515 
VisitCallUndefinedReceiver1()2516 void BytecodeGraphBuilder::VisitCallUndefinedReceiver1() {
2517   Node* callee =
2518       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2519   Node* receiver = jsgraph()->UndefinedConstant();
2520   Node* arg0 =
2521       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2522   int const slot_id = bytecode_iterator().GetIndexOperand(2);
2523   BuildCall(ConvertReceiverMode::kNullOrUndefined,
2524             {callee, receiver, arg0, feedback_vector_node()}, slot_id);
2525 }
2526 
VisitCallUndefinedReceiver2()2527 void BytecodeGraphBuilder::VisitCallUndefinedReceiver2() {
2528   Node* callee =
2529       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2530   Node* receiver = jsgraph()->UndefinedConstant();
2531   Node* arg0 =
2532       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2533   Node* arg1 =
2534       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
2535   int const slot_id = bytecode_iterator().GetIndexOperand(3);
2536   BuildCall(ConvertReceiverMode::kNullOrUndefined,
2537             {callee, receiver, arg0, arg1, feedback_vector_node()}, slot_id);
2538 }
2539 
VisitCallWithSpread()2540 void BytecodeGraphBuilder::VisitCallWithSpread() {
2541   PrepareEagerCheckpoint();
2542   Node* callee =
2543       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2544   interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
2545   Node* receiver_node = environment()->LookupRegister(receiver);
2546   size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
2547   interpreter::Register first_arg = interpreter::Register(receiver.index() + 1);
2548   int arg_count = static_cast<int>(reg_count) - 1;
2549   Node* const* args = GetCallArgumentsFromRegisters(callee, receiver_node,
2550                                                     first_arg, arg_count);
2551   int const slot_id = bytecode_iterator().GetIndexOperand(3);
2552   FeedbackSource feedback = CreateFeedbackSource(slot_id);
2553   CallFrequency frequency = ComputeCallFrequency(slot_id);
2554   SpeculationMode speculation_mode = GetSpeculationMode(slot_id);
2555   const Operator* op = javascript()->CallWithSpread(
2556       JSCallWithSpreadNode::ArityForArgc(arg_count), frequency, feedback,
2557       speculation_mode);
2558   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2559 
2560   JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall(
2561       op, args, static_cast<int>(arg_count), feedback.slot);
2562   if (lowering.IsExit()) return;
2563 
2564   Node* node = nullptr;
2565   if (lowering.IsSideEffectFree()) {
2566     node = lowering.value();
2567   } else {
2568     DCHECK(!lowering.Changed());
2569     node = MakeNode(op, JSCallWithSpreadNode::ArityForArgc(arg_count), args);
2570   }
2571   environment()->BindAccumulator(node, Environment::kAttachFrameState);
2572 }
2573 
VisitCallJSRuntime()2574 void BytecodeGraphBuilder::VisitCallJSRuntime() {
2575   PrepareEagerCheckpoint();
2576   Node* callee = BuildLoadNativeContextField(
2577       bytecode_iterator().GetNativeContextIndexOperand(0));
2578   interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
2579   size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
2580   int arg_count = static_cast<int>(reg_count);
2581   int arity = JSCallNode::ArityForArgc(arg_count);
2582 
2583   const Operator* call = javascript()->Call(arity);
2584   Node* const* call_args = ProcessCallVarArgs(
2585       ConvertReceiverMode::kNullOrUndefined, callee, first_reg, arg_count);
2586   Node* value = MakeNode(call, arity, call_args);
2587   environment()->BindAccumulator(value, Environment::kAttachFrameState);
2588 }
2589 
ProcessCallRuntimeArguments( const Operator* call_runtime_op, interpreter::Register receiver, size_t reg_count)2590 Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
2591     const Operator* call_runtime_op, interpreter::Register receiver,
2592     size_t reg_count) {
2593   int arg_count = static_cast<int>(reg_count);
2594   // arity is args.
2595   int arity = arg_count;
2596   Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
2597   int first_arg_index = receiver.index();
2598   for (int i = 0; i < static_cast<int>(reg_count); ++i) {
2599     all[i] = environment()->LookupRegister(
2600         interpreter::Register(first_arg_index + i));
2601   }
2602   Node* value = MakeNode(call_runtime_op, arity, all);
2603   return value;
2604 }
2605 
VisitCallRuntime()2606 void BytecodeGraphBuilder::VisitCallRuntime() {
2607   PrepareEagerCheckpoint();
2608   Runtime::FunctionId function_id = bytecode_iterator().GetRuntimeIdOperand(0);
2609   interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
2610   size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
2611 
2612   // Handle %ObserveNode here (rather than in JSIntrinsicLowering) to observe
2613   // the node as early as possible.
2614   if (function_id == Runtime::FunctionId::kObserveNode) {
2615     DCHECK_EQ(1, reg_count);
2616     Node* value = environment()->LookupRegister(receiver);
2617     observe_node_info_.StartObserving(value);
2618     environment()->BindAccumulator(value);
2619   } else {
2620     // Create node to perform the runtime call.
2621     const Operator* call = javascript()->CallRuntime(function_id, reg_count);
2622     Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count);
2623     environment()->BindAccumulator(value, Environment::kAttachFrameState);
2624 
2625     // Connect to the end if {function_id} is non-returning.
2626     if (Runtime::IsNonReturning(function_id)) {
2627       // TODO(7099): Investigate if we need LoopExit node here.
2628       Node* control = NewNode(common()->Throw());
2629       MergeControlToLeaveFunction(control);
2630     }
2631   }
2632 }
2633 
VisitCallRuntimeForPair()2634 void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
2635   PrepareEagerCheckpoint();
2636   Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
2637   interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
2638   size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
2639   interpreter::Register first_return =
2640       bytecode_iterator().GetRegisterOperand(3);
2641 
2642   // Create node to perform the runtime call.
2643   const Operator* call = javascript()->CallRuntime(functionId, reg_count);
2644   Node* return_pair = ProcessCallRuntimeArguments(call, receiver, reg_count);
2645   environment()->BindRegistersToProjections(first_return, return_pair,
2646                                             Environment::kAttachFrameState);
2647 }
2648 
GetConstructArgumentsFromRegister( Node* target, Node* new_target, interpreter::Register first_arg, int arg_count)2649 Node* const* BytecodeGraphBuilder::GetConstructArgumentsFromRegister(
2650     Node* target, Node* new_target, interpreter::Register first_arg,
2651     int arg_count) {
2652   const int arity = JSConstructNode::ArityForArgc(arg_count);
2653   Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
2654   int cursor = 0;
2655 
2656   STATIC_ASSERT(JSConstructNode::TargetIndex() == 0);
2657   STATIC_ASSERT(JSConstructNode::NewTargetIndex() == 1);
2658   STATIC_ASSERT(JSConstructNode::FirstArgumentIndex() == 2);
2659   STATIC_ASSERT(JSConstructNode::kFeedbackVectorIsLastInput);
2660 
2661   all[cursor++] = target;
2662   all[cursor++] = new_target;
2663 
2664   // The function arguments are in consecutive registers.
2665   int arg_base = first_arg.index();
2666   for (int i = 0; i < arg_count; ++i) {
2667     all[cursor++] =
2668         environment()->LookupRegister(interpreter::Register(arg_base + i));
2669   }
2670 
2671   all[cursor++] = feedback_vector_node();
2672 
2673   DCHECK_EQ(cursor, arity);
2674   return all;
2675 }
2676 
VisitConstruct()2677 void BytecodeGraphBuilder::VisitConstruct() {
2678   PrepareEagerCheckpoint();
2679   interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
2680   interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
2681   size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
2682   int const slot_id = bytecode_iterator().GetIndexOperand(3);
2683   FeedbackSource feedback = CreateFeedbackSource(slot_id);
2684 
2685   Node* new_target = environment()->LookupAccumulator();
2686   Node* callee = environment()->LookupRegister(callee_reg);
2687 
2688   CallFrequency frequency = ComputeCallFrequency(slot_id);
2689   const uint32_t arg_count = static_cast<uint32_t>(reg_count);
2690   const uint32_t arity = JSConstructNode::ArityForArgc(arg_count);
2691   const Operator* op = javascript()->Construct(arity, frequency, feedback);
2692   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2693   Node* const* args = GetConstructArgumentsFromRegister(callee, new_target,
2694                                                         first_reg, arg_count);
2695   JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedConstruct(
2696       op, args, static_cast<int>(arg_count), feedback.slot);
2697   if (lowering.IsExit()) return;
2698 
2699   Node* node = nullptr;
2700   if (lowering.IsSideEffectFree()) {
2701     node = lowering.value();
2702   } else {
2703     DCHECK(!lowering.Changed());
2704     node = MakeNode(op, arity, args);
2705   }
2706   environment()->BindAccumulator(node, Environment::kAttachFrameState);
2707 }
2708 
VisitConstructWithSpread()2709 void BytecodeGraphBuilder::VisitConstructWithSpread() {
2710   PrepareEagerCheckpoint();
2711   interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
2712   interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
2713   size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
2714   int const slot_id = bytecode_iterator().GetIndexOperand(3);
2715   FeedbackSource feedback = CreateFeedbackSource(slot_id);
2716 
2717   Node* new_target = environment()->LookupAccumulator();
2718   Node* callee = environment()->LookupRegister(callee_reg);
2719 
2720   CallFrequency frequency = ComputeCallFrequency(slot_id);
2721   const uint32_t arg_count = static_cast<uint32_t>(reg_count);
2722   const uint32_t arity = JSConstructNode::ArityForArgc(arg_count);
2723   const Operator* op =
2724       javascript()->ConstructWithSpread(arity, frequency, feedback);
2725   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2726   Node* const* args = GetConstructArgumentsFromRegister(callee, new_target,
2727                                                         first_reg, arg_count);
2728   JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedConstruct(
2729       op, args, static_cast<int>(arg_count), feedback.slot);
2730   if (lowering.IsExit()) return;
2731 
2732   Node* node = nullptr;
2733   if (lowering.IsSideEffectFree()) {
2734     node = lowering.value();
2735   } else {
2736     DCHECK(!lowering.Changed());
2737     node = MakeNode(op, arity, args);
2738   }
2739   environment()->BindAccumulator(node, Environment::kAttachFrameState);
2740 }
2741 
VisitInvokeIntrinsic()2742 void BytecodeGraphBuilder::VisitInvokeIntrinsic() {
2743   PrepareEagerCheckpoint();
2744   Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0);
2745   interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
2746   size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
2747 
2748   // Create node to perform the runtime call. Turbofan will take care of the
2749   // lowering.
2750   const Operator* call = javascript()->CallRuntime(functionId, reg_count);
2751   Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count);
2752   environment()->BindAccumulator(value, Environment::kAttachFrameState);
2753 }
2754 
VisitThrow()2755 void BytecodeGraphBuilder::VisitThrow() {
2756   BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor(
2757       bytecode_iterator().current_offset()));
2758   Node* value = environment()->LookupAccumulator();
2759   Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value);
2760   environment()->BindAccumulator(call, Environment::kAttachFrameState);
2761   Node* control = NewNode(common()->Throw());
2762   MergeControlToLeaveFunction(control);
2763 }
2764 
VisitAbort()2765 void BytecodeGraphBuilder::VisitAbort() {
2766   BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor(
2767       bytecode_iterator().current_offset()));
2768   AbortReason reason =
2769       static_cast<AbortReason>(bytecode_iterator().GetIndexOperand(0));
2770   NewNode(simplified()->RuntimeAbort(reason));
2771   Node* control = NewNode(common()->Throw());
2772   MergeControlToLeaveFunction(control);
2773 }
2774 
VisitReThrow()2775 void BytecodeGraphBuilder::VisitReThrow() {
2776   BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor(
2777       bytecode_iterator().current_offset()));
2778   Node* value = environment()->LookupAccumulator();
2779   NewNode(javascript()->CallRuntime(Runtime::kReThrow), value);
2780   Node* control = NewNode(common()->Throw());
2781   MergeControlToLeaveFunction(control);
2782 }
2783 
BuildHoleCheckAndThrow( Node* condition, Runtime::FunctionId runtime_id, Node* name)2784 void BytecodeGraphBuilder::BuildHoleCheckAndThrow(
2785     Node* condition, Runtime::FunctionId runtime_id, Node* name) {
2786   Node* accumulator = environment()->LookupAccumulator();
2787   NewBranch(condition, BranchHint::kFalse);
2788   {
2789     SubEnvironment sub_environment(this);
2790 
2791     NewIfTrue();
2792     BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor(
2793         bytecode_iterator().current_offset()));
2794     Node* node;
2795     const Operator* op = javascript()->CallRuntime(runtime_id);
2796     if (runtime_id == Runtime::kThrowAccessedUninitializedVariable) {
2797       DCHECK_NOT_NULL(name);
2798       node = NewNode(op, name);
2799     } else {
2800       DCHECK(runtime_id == Runtime::kThrowSuperAlreadyCalledError ||
2801              runtime_id == Runtime::kThrowSuperNotCalled);
2802       node = NewNode(op);
2803     }
2804     environment()->RecordAfterState(node, Environment::kAttachFrameState);
2805     Node* control = NewNode(common()->Throw());
2806     MergeControlToLeaveFunction(control);
2807   }
2808   NewIfFalse();
2809   environment()->BindAccumulator(accumulator);
2810 }
2811 
VisitThrowReferenceErrorIfHole()2812 void BytecodeGraphBuilder::VisitThrowReferenceErrorIfHole() {
2813   Node* accumulator = environment()->LookupAccumulator();
2814   Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator,
2815                                  jsgraph()->TheHoleConstant());
2816   Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0));
2817   BuildHoleCheckAndThrow(check_for_hole,
2818                          Runtime::kThrowAccessedUninitializedVariable, name);
2819 }
2820 
VisitThrowSuperNotCalledIfHole()2821 void BytecodeGraphBuilder::VisitThrowSuperNotCalledIfHole() {
2822   Node* accumulator = environment()->LookupAccumulator();
2823   Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator,
2824                                  jsgraph()->TheHoleConstant());
2825   BuildHoleCheckAndThrow(check_for_hole, Runtime::kThrowSuperNotCalled);
2826 }
2827 
VisitThrowSuperAlreadyCalledIfNotHole()2828 void BytecodeGraphBuilder::VisitThrowSuperAlreadyCalledIfNotHole() {
2829   Node* accumulator = environment()->LookupAccumulator();
2830   Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator,
2831                                  jsgraph()->TheHoleConstant());
2832   Node* check_for_not_hole =
2833       NewNode(simplified()->BooleanNot(), check_for_hole);
2834   BuildHoleCheckAndThrow(check_for_not_hole,
2835                          Runtime::kThrowSuperAlreadyCalledError);
2836 }
2837 
VisitThrowIfNotSuperConstructor()2838 void BytecodeGraphBuilder::VisitThrowIfNotSuperConstructor() {
2839   Node* constructor =
2840       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2841   Node* check_is_constructor =
2842       NewNode(simplified()->ObjectIsConstructor(), constructor);
2843   NewBranch(check_is_constructor, BranchHint::kTrue);
2844   {
2845     SubEnvironment sub_environment(this);
2846     NewIfFalse();
2847     BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor(
2848         bytecode_iterator().current_offset()));
2849     Node* node =
2850         NewNode(javascript()->CallRuntime(Runtime::kThrowNotSuperConstructor),
2851                 constructor, GetFunctionClosure());
2852     environment()->RecordAfterState(node, Environment::kAttachFrameState);
2853     Node* control = NewNode(common()->Throw());
2854     MergeControlToLeaveFunction(control);
2855   }
2856   NewIfTrue();
2857 
2858   constructor = NewNode(common()->TypeGuard(Type::Callable()), constructor);
2859   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0),
2860                               constructor);
2861 }
2862 
BuildUnaryOp(const Operator* op)2863 void BytecodeGraphBuilder::BuildUnaryOp(const Operator* op) {
2864   DCHECK(JSOperator::IsUnaryWithFeedback(op->opcode()));
2865   PrepareEagerCheckpoint();
2866   Node* operand = environment()->LookupAccumulator();
2867 
2868   FeedbackSlot slot =
2869       bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex);
2870   JSTypeHintLowering::LoweringResult lowering =
2871       TryBuildSimplifiedUnaryOp(op, operand, slot);
2872   if (lowering.IsExit()) return;
2873 
2874   Node* node = nullptr;
2875   if (lowering.IsSideEffectFree()) {
2876     node = lowering.value();
2877   } else {
2878     DCHECK(!lowering.Changed());
2879     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2880     node = NewNode(op, operand, feedback_vector_node());
2881   }
2882 
2883   environment()->BindAccumulator(node, Environment::kAttachFrameState);
2884 }
2885 
BuildBinaryOp(const Operator* op)2886 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) {
2887   DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode()));
2888   PrepareEagerCheckpoint();
2889   Node* left =
2890       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2891   Node* right = environment()->LookupAccumulator();
2892 
2893   FeedbackSlot slot =
2894       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex);
2895   JSTypeHintLowering::LoweringResult lowering =
2896       TryBuildSimplifiedBinaryOp(op, left, right, slot);
2897   if (lowering.IsExit()) return;
2898 
2899   Node* node = nullptr;
2900   if (lowering.IsSideEffectFree()) {
2901     node = lowering.value();
2902   } else {
2903     DCHECK(!lowering.Changed());
2904     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
2905     node = NewNode(op, left, right, feedback_vector_node());
2906   }
2907 
2908   environment()->BindAccumulator(node, Environment::kAttachFrameState);
2909 }
2910 
2911 // Helper function to create for-in mode from the recorded type feedback.
GetForInMode(FeedbackSlot slot)2912 ForInMode BytecodeGraphBuilder::GetForInMode(FeedbackSlot slot) {
2913   FeedbackSource source(feedback_vector(), slot);
2914   switch (broker()->GetFeedbackForForIn(source)) {
2915     case ForInHint::kNone:
2916     case ForInHint::kEnumCacheKeysAndIndices:
2917       return ForInMode::kUseEnumCacheKeysAndIndices;
2918     case ForInHint::kEnumCacheKeys:
2919       return ForInMode::kUseEnumCacheKeys;
2920     case ForInHint::kAny:
2921       return ForInMode::kGeneric;
2922   }
2923   UNREACHABLE();
2924 }
2925 
ComputeCallFrequency(int slot_id) const2926 CallFrequency BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const {
2927   if (invocation_frequency_.IsUnknown()) return CallFrequency();
2928   FeedbackSlot slot = FeedbackVector::ToSlot(slot_id);
2929   FeedbackSource source(feedback_vector(), slot);
2930   ProcessedFeedback const& feedback = broker()->GetFeedbackForCall(source);
2931   float feedback_frequency =
2932       feedback.IsInsufficient() ? 0.0f : feedback.AsCall().frequency();
2933   if (feedback_frequency == 0.0f) {  // Prevent multiplying zero and infinity.
2934     return CallFrequency(0.0f);
2935   } else {
2936     return CallFrequency(feedback_frequency * invocation_frequency_.value());
2937   }
2938 }
2939 
GetSpeculationMode(int slot_id) const2940 SpeculationMode BytecodeGraphBuilder::GetSpeculationMode(int slot_id) const {
2941   FeedbackSlot slot = FeedbackVector::ToSlot(slot_id);
2942   FeedbackSource source(feedback_vector(), slot);
2943   ProcessedFeedback const& feedback = broker()->GetFeedbackForCall(source);
2944   return feedback.IsInsufficient() ? SpeculationMode::kDisallowSpeculation
2945                                    : feedback.AsCall().speculation_mode();
2946 }
2947 
ComputeCallFeedbackRelation( int slot_id) const2948 CallFeedbackRelation BytecodeGraphBuilder::ComputeCallFeedbackRelation(
2949     int slot_id) const {
2950   FeedbackSlot slot = FeedbackVector::ToSlot(slot_id);
2951   FeedbackSource source(feedback_vector(), slot);
2952   ProcessedFeedback const& feedback = broker()->GetFeedbackForCall(source);
2953   if (feedback.IsInsufficient()) return CallFeedbackRelation::kUnrelated;
2954   CallFeedbackContent call_feedback_content =
2955       feedback.AsCall().call_feedback_content();
2956   return call_feedback_content == CallFeedbackContent::kTarget
2957              ? CallFeedbackRelation::kTarget
2958              : CallFeedbackRelation::kReceiver;
2959 }
2960 
VisitBitwiseNot()2961 void BytecodeGraphBuilder::VisitBitwiseNot() {
2962   FeedbackSource feedback = CreateFeedbackSource(
2963       bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex));
2964   BuildUnaryOp(javascript()->BitwiseNot(feedback));
2965 }
2966 
VisitDec()2967 void BytecodeGraphBuilder::VisitDec() {
2968   FeedbackSource feedback = CreateFeedbackSource(
2969       bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex));
2970   BuildUnaryOp(javascript()->Decrement(feedback));
2971 }
2972 
VisitInc()2973 void BytecodeGraphBuilder::VisitInc() {
2974   FeedbackSource feedback = CreateFeedbackSource(
2975       bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex));
2976   BuildUnaryOp(javascript()->Increment(feedback));
2977 }
2978 
VisitNegate()2979 void BytecodeGraphBuilder::VisitNegate() {
2980   FeedbackSource feedback = CreateFeedbackSource(
2981       bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex));
2982   BuildUnaryOp(javascript()->Negate(feedback));
2983 }
2984 
VisitAdd()2985 void BytecodeGraphBuilder::VisitAdd() {
2986   FeedbackSource feedback = CreateFeedbackSource(
2987       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
2988   BuildBinaryOp(javascript()->Add(feedback));
2989 }
2990 
VisitSub()2991 void BytecodeGraphBuilder::VisitSub() {
2992   FeedbackSource feedback = CreateFeedbackSource(
2993       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
2994   BuildBinaryOp(javascript()->Subtract(feedback));
2995 }
2996 
VisitMul()2997 void BytecodeGraphBuilder::VisitMul() {
2998   FeedbackSource feedback = CreateFeedbackSource(
2999       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
3000   BuildBinaryOp(javascript()->Multiply(feedback));
3001 }
3002 
VisitDiv()3003 void BytecodeGraphBuilder::VisitDiv() {
3004   FeedbackSource feedback = CreateFeedbackSource(
3005       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
3006   BuildBinaryOp(javascript()->Divide(feedback));
3007 }
3008 
VisitMod()3009 void BytecodeGraphBuilder::VisitMod() {
3010   FeedbackSource feedback = CreateFeedbackSource(
3011       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
3012   BuildBinaryOp(javascript()->Modulus(feedback));
3013 }
3014 
VisitExp()3015 void BytecodeGraphBuilder::VisitExp() {
3016   FeedbackSource feedback = CreateFeedbackSource(
3017       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
3018   BuildBinaryOp(javascript()->Exponentiate(feedback));
3019 }
3020 
VisitBitwiseOr()3021 void BytecodeGraphBuilder::VisitBitwiseOr() {
3022   FeedbackSource feedback = CreateFeedbackSource(
3023       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
3024   BuildBinaryOp(javascript()->BitwiseOr(feedback));
3025 }
3026 
VisitBitwiseXor()3027 void BytecodeGraphBuilder::VisitBitwiseXor() {
3028   FeedbackSource feedback = CreateFeedbackSource(
3029       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
3030   BuildBinaryOp(javascript()->BitwiseXor(feedback));
3031 }
3032 
VisitBitwiseAnd()3033 void BytecodeGraphBuilder::VisitBitwiseAnd() {
3034   FeedbackSource feedback = CreateFeedbackSource(
3035       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
3036   BuildBinaryOp(javascript()->BitwiseAnd(feedback));
3037 }
3038 
VisitShiftLeft()3039 void BytecodeGraphBuilder::VisitShiftLeft() {
3040   FeedbackSource feedback = CreateFeedbackSource(
3041       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
3042   BuildBinaryOp(javascript()->ShiftLeft(feedback));
3043 }
3044 
VisitShiftRight()3045 void BytecodeGraphBuilder::VisitShiftRight() {
3046   FeedbackSource feedback = CreateFeedbackSource(
3047       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
3048   BuildBinaryOp(javascript()->ShiftRight(feedback));
3049 }
3050 
VisitShiftRightLogical()3051 void BytecodeGraphBuilder::VisitShiftRightLogical() {
3052   FeedbackSource feedback = CreateFeedbackSource(
3053       bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex));
3054   BuildBinaryOp(javascript()->ShiftRightLogical(feedback));
3055 }
3056 
BuildBinaryOpWithImmediate(const Operator* op)3057 void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) {
3058   DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode()));
3059   PrepareEagerCheckpoint();
3060   Node* left = environment()->LookupAccumulator();
3061   Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
3062 
3063   FeedbackSlot slot =
3064       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex);
3065   JSTypeHintLowering::LoweringResult lowering =
3066       TryBuildSimplifiedBinaryOp(op, left, right, slot);
3067   if (lowering.IsExit()) return;
3068 
3069   Node* node = nullptr;
3070   if (lowering.IsSideEffectFree()) {
3071     node = lowering.value();
3072   } else {
3073     DCHECK(!lowering.Changed());
3074     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
3075     node = NewNode(op, left, right, feedback_vector_node());
3076   }
3077   environment()->BindAccumulator(node, Environment::kAttachFrameState);
3078 }
3079 
VisitAddSmi()3080 void BytecodeGraphBuilder::VisitAddSmi() {
3081   FeedbackSource feedback = CreateFeedbackSource(
3082       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3083   BuildBinaryOpWithImmediate(javascript()->Add(feedback));
3084 }
3085 
VisitSubSmi()3086 void BytecodeGraphBuilder::VisitSubSmi() {
3087   FeedbackSource feedback = CreateFeedbackSource(
3088       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3089   BuildBinaryOpWithImmediate(javascript()->Subtract(feedback));
3090 }
3091 
VisitMulSmi()3092 void BytecodeGraphBuilder::VisitMulSmi() {
3093   FeedbackSource feedback = CreateFeedbackSource(
3094       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3095   BuildBinaryOpWithImmediate(javascript()->Multiply(feedback));
3096 }
3097 
VisitDivSmi()3098 void BytecodeGraphBuilder::VisitDivSmi() {
3099   FeedbackSource feedback = CreateFeedbackSource(
3100       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3101   BuildBinaryOpWithImmediate(javascript()->Divide(feedback));
3102 }
3103 
VisitModSmi()3104 void BytecodeGraphBuilder::VisitModSmi() {
3105   FeedbackSource feedback = CreateFeedbackSource(
3106       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3107   BuildBinaryOpWithImmediate(javascript()->Modulus(feedback));
3108 }
3109 
VisitExpSmi()3110 void BytecodeGraphBuilder::VisitExpSmi() {
3111   FeedbackSource feedback = CreateFeedbackSource(
3112       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3113   BuildBinaryOpWithImmediate(javascript()->Exponentiate(feedback));
3114 }
3115 
VisitBitwiseOrSmi()3116 void BytecodeGraphBuilder::VisitBitwiseOrSmi() {
3117   FeedbackSource feedback = CreateFeedbackSource(
3118       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3119   BuildBinaryOpWithImmediate(javascript()->BitwiseOr(feedback));
3120 }
3121 
VisitBitwiseXorSmi()3122 void BytecodeGraphBuilder::VisitBitwiseXorSmi() {
3123   FeedbackSource feedback = CreateFeedbackSource(
3124       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3125   BuildBinaryOpWithImmediate(javascript()->BitwiseXor(feedback));
3126 }
3127 
VisitBitwiseAndSmi()3128 void BytecodeGraphBuilder::VisitBitwiseAndSmi() {
3129   FeedbackSource feedback = CreateFeedbackSource(
3130       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3131   BuildBinaryOpWithImmediate(javascript()->BitwiseAnd(feedback));
3132 }
3133 
VisitShiftLeftSmi()3134 void BytecodeGraphBuilder::VisitShiftLeftSmi() {
3135   FeedbackSource feedback = CreateFeedbackSource(
3136       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3137   BuildBinaryOpWithImmediate(javascript()->ShiftLeft(feedback));
3138 }
3139 
VisitShiftRightSmi()3140 void BytecodeGraphBuilder::VisitShiftRightSmi() {
3141   FeedbackSource feedback = CreateFeedbackSource(
3142       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3143   BuildBinaryOpWithImmediate(javascript()->ShiftRight(feedback));
3144 }
3145 
VisitShiftRightLogicalSmi()3146 void BytecodeGraphBuilder::VisitShiftRightLogicalSmi() {
3147   FeedbackSource feedback = CreateFeedbackSource(
3148       bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex));
3149   BuildBinaryOpWithImmediate(javascript()->ShiftRightLogical(feedback));
3150 }
3151 
VisitLogicalNot()3152 void BytecodeGraphBuilder::VisitLogicalNot() {
3153   Node* value = environment()->LookupAccumulator();
3154   Node* node = NewNode(simplified()->BooleanNot(), value);
3155   environment()->BindAccumulator(node);
3156 }
3157 
VisitToBooleanLogicalNot()3158 void BytecodeGraphBuilder::VisitToBooleanLogicalNot() {
3159   Node* value =
3160       NewNode(simplified()->ToBoolean(), environment()->LookupAccumulator());
3161   Node* node = NewNode(simplified()->BooleanNot(), value);
3162   environment()->BindAccumulator(node);
3163 }
3164 
VisitTypeOf()3165 void BytecodeGraphBuilder::VisitTypeOf() {
3166   Node* node =
3167       NewNode(simplified()->TypeOf(), environment()->LookupAccumulator());
3168   environment()->BindAccumulator(node);
3169 }
3170 
BuildDelete(LanguageMode language_mode)3171 void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) {
3172   PrepareEagerCheckpoint();
3173   Node* key = environment()->LookupAccumulator();
3174   Node* object =
3175       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3176   Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode));
3177   Node* node = NewNode(javascript()->DeleteProperty(), object, key, mode);
3178   environment()->BindAccumulator(node, Environment::kAttachFrameState);
3179 }
3180 
VisitDeletePropertyStrict()3181 void BytecodeGraphBuilder::VisitDeletePropertyStrict() {
3182   BuildDelete(LanguageMode::kStrict);
3183 }
3184 
VisitDeletePropertySloppy()3185 void BytecodeGraphBuilder::VisitDeletePropertySloppy() {
3186   BuildDelete(LanguageMode::kSloppy);
3187 }
3188 
VisitGetSuperConstructor()3189 void BytecodeGraphBuilder::VisitGetSuperConstructor() {
3190   Node* node = NewNode(javascript()->GetSuperConstructor(),
3191                        environment()->LookupAccumulator());
3192   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node,
3193                               Environment::kAttachFrameState);
3194 }
3195 
BuildCompareOp(const Operator* op)3196 void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) {
3197   DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode()));
3198   PrepareEagerCheckpoint();
3199   Node* left =
3200       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3201   Node* right = environment()->LookupAccumulator();
3202 
3203   FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
3204   JSTypeHintLowering::LoweringResult lowering =
3205       TryBuildSimplifiedBinaryOp(op, left, right, slot);
3206   if (lowering.IsExit()) return;
3207 
3208   Node* node = nullptr;
3209   if (lowering.IsSideEffectFree()) {
3210     node = lowering.value();
3211   } else {
3212     DCHECK(!lowering.Changed());
3213     DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
3214     node = NewNode(op, left, right, feedback_vector_node());
3215   }
3216   environment()->BindAccumulator(node, Environment::kAttachFrameState);
3217 }
3218 
VisitTestEqual()3219 void BytecodeGraphBuilder::VisitTestEqual() {
3220   FeedbackSource feedback = CreateFeedbackSource(
3221       bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex));
3222   BuildCompareOp(javascript()->Equal(feedback));
3223 }
3224 
VisitTestEqualStrict()3225 void BytecodeGraphBuilder::VisitTestEqualStrict() {
3226   FeedbackSource feedback = CreateFeedbackSource(
3227       bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex));
3228   BuildCompareOp(javascript()->StrictEqual(feedback));
3229 }
3230 
VisitTestLessThan()3231 void BytecodeGraphBuilder::VisitTestLessThan() {
3232   FeedbackSource feedback = CreateFeedbackSource(
3233       bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex));
3234   BuildCompareOp(javascript()->LessThan(feedback));
3235 }
3236 
VisitTestGreaterThan()3237 void BytecodeGraphBuilder::VisitTestGreaterThan() {
3238   FeedbackSource feedback = CreateFeedbackSource(
3239       bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex));
3240   BuildCompareOp(javascript()->GreaterThan(feedback));
3241 }
3242 
VisitTestLessThanOrEqual()3243 void BytecodeGraphBuilder::VisitTestLessThanOrEqual() {
3244   FeedbackSource feedback = CreateFeedbackSource(
3245       bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex));
3246   BuildCompareOp(javascript()->LessThanOrEqual(feedback));
3247 }
3248 
VisitTestGreaterThanOrEqual()3249 void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() {
3250   FeedbackSource feedback = CreateFeedbackSource(
3251       bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex));
3252   BuildCompareOp(javascript()->GreaterThanOrEqual(feedback));
3253 }
3254 
VisitTestReferenceEqual()3255 void BytecodeGraphBuilder::VisitTestReferenceEqual() {
3256   Node* left =
3257       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3258   Node* right = environment()->LookupAccumulator();
3259   Node* result = NewNode(simplified()->ReferenceEqual(), left, right);
3260   environment()->BindAccumulator(result);
3261 }
3262 
VisitTestIn()3263 void BytecodeGraphBuilder::VisitTestIn() {
3264   PrepareEagerCheckpoint();
3265   Node* object = environment()->LookupAccumulator();
3266   Node* key =
3267       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3268   FeedbackSource feedback =
3269       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1));
3270   STATIC_ASSERT(JSHasPropertyNode::ObjectIndex() == 0);
3271   STATIC_ASSERT(JSHasPropertyNode::KeyIndex() == 1);
3272   STATIC_ASSERT(JSHasPropertyNode::FeedbackVectorIndex() == 2);
3273   const Operator* op = javascript()->HasProperty(feedback);
3274   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
3275   Node* node = NewNode(op, object, key, feedback_vector_node());
3276   environment()->BindAccumulator(node, Environment::kAttachFrameState);
3277 }
3278 
VisitTestInstanceOf()3279 void BytecodeGraphBuilder::VisitTestInstanceOf() {
3280   FeedbackSource feedback = CreateFeedbackSource(
3281       bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex));
3282   BuildCompareOp(javascript()->InstanceOf(feedback));
3283 }
3284 
VisitTestUndetectable()3285 void BytecodeGraphBuilder::VisitTestUndetectable() {
3286   Node* object = environment()->LookupAccumulator();
3287   Node* node = NewNode(jsgraph()->simplified()->ObjectIsUndetectable(), object);
3288   environment()->BindAccumulator(node);
3289 }
3290 
VisitTestNull()3291 void BytecodeGraphBuilder::VisitTestNull() {
3292   Node* object = environment()->LookupAccumulator();
3293   Node* result = NewNode(simplified()->ReferenceEqual(), object,
3294                          jsgraph()->NullConstant());
3295   environment()->BindAccumulator(result);
3296 }
3297 
VisitTestUndefined()3298 void BytecodeGraphBuilder::VisitTestUndefined() {
3299   Node* object = environment()->LookupAccumulator();
3300   Node* result = NewNode(simplified()->ReferenceEqual(), object,
3301                          jsgraph()->UndefinedConstant());
3302   environment()->BindAccumulator(result);
3303 }
3304 
VisitTestTypeOf()3305 void BytecodeGraphBuilder::VisitTestTypeOf() {
3306   Node* object = environment()->LookupAccumulator();
3307   auto literal_flag = interpreter::TestTypeOfFlags::Decode(
3308       bytecode_iterator().GetFlagOperand(0));
3309   Node* result;
3310   switch (literal_flag) {
3311     case interpreter::TestTypeOfFlags::LiteralFlag::kNumber:
3312       result = NewNode(simplified()->ObjectIsNumber(), object);
3313       break;
3314     case interpreter::TestTypeOfFlags::LiteralFlag::kString:
3315       result = NewNode(simplified()->ObjectIsString(), object);
3316       break;
3317     case interpreter::TestTypeOfFlags::LiteralFlag::kSymbol:
3318       result = NewNode(simplified()->ObjectIsSymbol(), object);
3319       break;
3320     case interpreter::TestTypeOfFlags::LiteralFlag::kBigInt:
3321       result = NewNode(simplified()->ObjectIsBigInt(), object);
3322       break;
3323     case interpreter::TestTypeOfFlags::LiteralFlag::kBoolean:
3324       result = NewNode(common()->Select(MachineRepresentation::kTagged),
3325                        NewNode(simplified()->ReferenceEqual(), object,
3326                                jsgraph()->TrueConstant()),
3327                        jsgraph()->TrueConstant(),
3328                        NewNode(simplified()->ReferenceEqual(), object,
3329                                jsgraph()->FalseConstant()));
3330       break;
3331     case interpreter::TestTypeOfFlags::LiteralFlag::kUndefined:
3332       result = graph()->NewNode(
3333           common()->Select(MachineRepresentation::kTagged),
3334           graph()->NewNode(simplified()->ReferenceEqual(), object,
3335                            jsgraph()->NullConstant()),
3336           jsgraph()->FalseConstant(),
3337           graph()->NewNode(simplified()->ObjectIsUndetectable(), object));
3338       break;
3339     case interpreter::TestTypeOfFlags::LiteralFlag::kFunction:
3340       result =
3341           graph()->NewNode(simplified()->ObjectIsDetectableCallable(), object);
3342       break;
3343     case interpreter::TestTypeOfFlags::LiteralFlag::kObject:
3344       result = graph()->NewNode(
3345           common()->Select(MachineRepresentation::kTagged),
3346           graph()->NewNode(simplified()->ObjectIsNonCallable(), object),
3347           jsgraph()->TrueConstant(),
3348           graph()->NewNode(simplified()->ReferenceEqual(), object,
3349                            jsgraph()->NullConstant()));
3350       break;
3351     case interpreter::TestTypeOfFlags::LiteralFlag::kOther:
3352       UNREACHABLE();  // Should never be emitted.
3353   }
3354   environment()->BindAccumulator(result);
3355 }
3356 
BuildCastOperator(const Operator* js_op)3357 void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) {
3358   Node* value = NewNode(js_op, environment()->LookupAccumulator());
3359   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value,
3360                               Environment::kAttachFrameState);
3361 }
3362 
VisitToName()3363 void BytecodeGraphBuilder::VisitToName() {
3364   BuildCastOperator(javascript()->ToName());
3365 }
3366 
VisitToObject()3367 void BytecodeGraphBuilder::VisitToObject() {
3368   BuildCastOperator(javascript()->ToObject());
3369 }
3370 
VisitToString()3371 void BytecodeGraphBuilder::VisitToString() {
3372   Node* value =
3373       NewNode(javascript()->ToString(), environment()->LookupAccumulator());
3374   environment()->BindAccumulator(value, Environment::kAttachFrameState);
3375 }
3376 
VisitToNumber()3377 void BytecodeGraphBuilder::VisitToNumber() {
3378   PrepareEagerCheckpoint();
3379   Node* object = environment()->LookupAccumulator();
3380 
3381   FeedbackSlot slot = bytecode_iterator().GetSlotOperand(0);
3382   JSTypeHintLowering::LoweringResult lowering =
3383       TryBuildSimplifiedToNumber(object, slot);
3384 
3385   Node* node = nullptr;
3386   if (lowering.IsSideEffectFree()) {
3387     node = lowering.value();
3388   } else {
3389     DCHECK(!lowering.Changed());
3390     node = NewNode(javascript()->ToNumber(), object);
3391   }
3392 
3393   environment()->BindAccumulator(node, Environment::kAttachFrameState);
3394 }
3395 
VisitToNumeric()3396 void BytecodeGraphBuilder::VisitToNumeric() {
3397   PrepareEagerCheckpoint();
3398   Node* object = environment()->LookupAccumulator();
3399 
3400   // If we have some kind of Number feedback, we do the same lowering as for
3401   // ToNumber.
3402   FeedbackSlot slot = bytecode_iterator().GetSlotOperand(0);
3403   JSTypeHintLowering::LoweringResult lowering =
3404       TryBuildSimplifiedToNumber(object, slot);
3405 
3406   Node* node = nullptr;
3407   if (lowering.IsSideEffectFree()) {
3408     node = lowering.value();
3409   } else {
3410     DCHECK(!lowering.Changed());
3411     node = NewNode(javascript()->ToNumeric(), object);
3412   }
3413 
3414   environment()->BindAccumulator(node, Environment::kAttachFrameState);
3415 }
3416 
VisitJump()3417 void BytecodeGraphBuilder::VisitJump() { BuildJump(); }
3418 
VisitJumpConstant()3419 void BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); }
3420 
VisitJumpIfTrue()3421 void BytecodeGraphBuilder::VisitJumpIfTrue() { BuildJumpIfTrue(); }
3422 
VisitJumpIfTrueConstant()3423 void BytecodeGraphBuilder::VisitJumpIfTrueConstant() { BuildJumpIfTrue(); }
3424 
VisitJumpIfFalse()3425 void BytecodeGraphBuilder::VisitJumpIfFalse() { BuildJumpIfFalse(); }
3426 
VisitJumpIfFalseConstant()3427 void BytecodeGraphBuilder::VisitJumpIfFalseConstant() { BuildJumpIfFalse(); }
3428 
VisitJumpIfToBooleanTrue()3429 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() {
3430   BuildJumpIfToBooleanTrue();
3431 }
3432 
VisitJumpIfToBooleanTrueConstant()3433 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() {
3434   BuildJumpIfToBooleanTrue();
3435 }
3436 
VisitJumpIfToBooleanFalse()3437 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() {
3438   BuildJumpIfToBooleanFalse();
3439 }
3440 
VisitJumpIfToBooleanFalseConstant()3441 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() {
3442   BuildJumpIfToBooleanFalse();
3443 }
3444 
VisitJumpIfJSReceiver()3445 void BytecodeGraphBuilder::VisitJumpIfJSReceiver() { BuildJumpIfJSReceiver(); }
3446 
VisitJumpIfJSReceiverConstant()3447 void BytecodeGraphBuilder::VisitJumpIfJSReceiverConstant() {
3448   BuildJumpIfJSReceiver();
3449 }
3450 
VisitJumpIfNull()3451 void BytecodeGraphBuilder::VisitJumpIfNull() {
3452   BuildJumpIfEqual(jsgraph()->NullConstant());
3453 }
3454 
VisitJumpIfNullConstant()3455 void BytecodeGraphBuilder::VisitJumpIfNullConstant() {
3456   BuildJumpIfEqual(jsgraph()->NullConstant());
3457 }
3458 
VisitJumpIfNotNull()3459 void BytecodeGraphBuilder::VisitJumpIfNotNull() {
3460   BuildJumpIfNotEqual(jsgraph()->NullConstant());
3461 }
3462 
VisitJumpIfNotNullConstant()3463 void BytecodeGraphBuilder::VisitJumpIfNotNullConstant() {
3464   BuildJumpIfNotEqual(jsgraph()->NullConstant());
3465 }
3466 
VisitJumpIfUndefined()3467 void BytecodeGraphBuilder::VisitJumpIfUndefined() {
3468   BuildJumpIfEqual(jsgraph()->UndefinedConstant());
3469 }
3470 
VisitJumpIfUndefinedConstant()3471 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() {
3472   BuildJumpIfEqual(jsgraph()->UndefinedConstant());
3473 }
3474 
VisitJumpIfNotUndefined()3475 void BytecodeGraphBuilder::VisitJumpIfNotUndefined() {
3476   BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
3477 }
3478 
VisitJumpIfNotUndefinedConstant()3479 void BytecodeGraphBuilder::VisitJumpIfNotUndefinedConstant() {
3480   BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
3481 }
3482 
VisitJumpIfUndefinedOrNull()3483 void BytecodeGraphBuilder::VisitJumpIfUndefinedOrNull() {
3484   BuildJumpIfEqual(jsgraph()->UndefinedConstant());
3485   BuildJumpIfEqual(jsgraph()->NullConstant());
3486 }
3487 
VisitJumpIfUndefinedOrNullConstant()3488 void BytecodeGraphBuilder::VisitJumpIfUndefinedOrNullConstant() {
3489   BuildJumpIfEqual(jsgraph()->UndefinedConstant());
3490   BuildJumpIfEqual(jsgraph()->NullConstant());
3491 }
3492 
VisitJumpLoop()3493 void BytecodeGraphBuilder::VisitJumpLoop() {
3494   BuildIterationBodyStackCheck();
3495   BuildJump();
3496 }
3497 
BuildSwitchOnSmi(Node* condition)3498 void BytecodeGraphBuilder::BuildSwitchOnSmi(Node* condition) {
3499   interpreter::JumpTableTargetOffsets offsets =
3500       bytecode_iterator().GetJumpTableTargetOffsets();
3501 
3502   NewSwitch(condition, offsets.size() + 1);
3503   for (interpreter::JumpTableTargetOffset entry : offsets) {
3504     SubEnvironment sub_environment(this);
3505     NewIfValue(entry.case_value);
3506     MergeIntoSuccessorEnvironment(entry.target_offset);
3507   }
3508   NewIfDefault();
3509 }
3510 
VisitSwitchOnSmiNoFeedback()3511 void BytecodeGraphBuilder::VisitSwitchOnSmiNoFeedback() {
3512   PrepareEagerCheckpoint();
3513 
3514   Node* acc = environment()->LookupAccumulator();
3515   Node* acc_smi = NewNode(simplified()->CheckSmi(FeedbackSource()), acc);
3516   BuildSwitchOnSmi(acc_smi);
3517 }
3518 
VisitSetPendingMessage()3519 void BytecodeGraphBuilder::VisitSetPendingMessage() {
3520   Node* previous_message = NewNode(javascript()->LoadMessage());
3521   NewNode(javascript()->StoreMessage(), environment()->LookupAccumulator());
3522   environment()->BindAccumulator(previous_message);
3523 }
3524 
BuildReturn(const BytecodeLivenessState* liveness)3525 void BytecodeGraphBuilder::BuildReturn(const BytecodeLivenessState* liveness) {
3526   BuildLoopExitsForFunctionExit(liveness);
3527   Node* pop_node = jsgraph()->ZeroConstant();
3528   Node* control =
3529       NewNode(common()->Return(), pop_node, environment()->LookupAccumulator());
3530   MergeControlToLeaveFunction(control);
3531 }
3532 
VisitReturn()3533 void BytecodeGraphBuilder::VisitReturn() {
3534   BuildReturn(bytecode_analysis().GetInLivenessFor(
3535       bytecode_iterator().current_offset()));
3536 }
3537 
VisitDebugger()3538 void BytecodeGraphBuilder::VisitDebugger() {
3539   PrepareEagerCheckpoint();
3540   Node* call = NewNode(javascript()->Debugger());
3541   environment()->RecordAfterState(call, Environment::kAttachFrameState);
3542 }
3543 
3544 // We cannot create a graph from the debugger copy of the bytecode array.
3545 #define DEBUG_BREAK(Name, ...) \
3546   void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); }
3547 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK)
3548 #undef DEBUG_BREAK
3549 
VisitIncBlockCounter()3550 void BytecodeGraphBuilder::VisitIncBlockCounter() {
3551   Node* closure = GetFunctionClosure();
3552   Node* coverage_array_slot =
3553       jsgraph()->Constant(bytecode_iterator().GetIndexOperand(0));
3554 
3555   // Lowered by js-intrinsic-lowering to call Builtin::kIncBlockCounter.
3556   const Operator* op =
3557       javascript()->CallRuntime(Runtime::kInlineIncBlockCounter);
3558 
3559   NewNode(op, closure, coverage_array_slot);
3560 }
3561 
VisitForInEnumerate()3562 void BytecodeGraphBuilder::VisitForInEnumerate() {
3563   Node* receiver =
3564       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3565   Node* enumerator = NewNode(javascript()->ForInEnumerate(), receiver);
3566   environment()->BindAccumulator(enumerator, Environment::kAttachFrameState);
3567 }
3568 
VisitForInPrepare()3569 void BytecodeGraphBuilder::VisitForInPrepare() {
3570   PrepareEagerCheckpoint();
3571   Node* enumerator = environment()->LookupAccumulator();
3572 
3573   FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
3574   JSTypeHintLowering::LoweringResult lowering =
3575       TryBuildSimplifiedForInPrepare(enumerator, slot);
3576   if (lowering.IsExit()) return;
3577   DCHECK(!lowering.Changed());
3578   FeedbackSource feedback = CreateFeedbackSource(slot);
3579   Node* node = NewNode(javascript()->ForInPrepare(GetForInMode(slot), feedback),
3580                        enumerator, feedback_vector_node());
3581   environment()->BindRegistersToProjections(
3582       bytecode_iterator().GetRegisterOperand(0), node);
3583 }
3584 
VisitForInContinue()3585 void BytecodeGraphBuilder::VisitForInContinue() {
3586   PrepareEagerCheckpoint();
3587   Node* index =
3588       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3589   Node* cache_length =
3590       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
3591   Node* exit_cond = NewNode(simplified()->SpeculativeNumberLessThan(
3592                                 NumberOperationHint::kSignedSmall),
3593                             index, cache_length);
3594   environment()->BindAccumulator(exit_cond);
3595 }
3596 
VisitForInNext()3597 void BytecodeGraphBuilder::VisitForInNext() {
3598   PrepareEagerCheckpoint();
3599   Node* receiver =
3600       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3601   Node* index =
3602       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
3603   int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index();
3604   Node* cache_type = environment()->LookupRegister(
3605       interpreter::Register(catch_reg_pair_index));
3606   Node* cache_array = environment()->LookupRegister(
3607       interpreter::Register(catch_reg_pair_index + 1));
3608 
3609   // We need to rename the {index} here, as in case of OSR we lose the
3610   // information that the {index} is always a valid unsigned Smi value.
3611   index = NewNode(common()->TypeGuard(Type::UnsignedSmall()), index);
3612 
3613   FeedbackSlot slot = bytecode_iterator().GetSlotOperand(3);
3614   JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedForInNext(
3615       receiver, cache_array, cache_type, index, slot);
3616   if (lowering.IsExit()) return;
3617 
3618   DCHECK(!lowering.Changed());
3619   FeedbackSource feedback = CreateFeedbackSource(slot);
3620   Node* node =
3621       NewNode(javascript()->ForInNext(GetForInMode(slot), feedback), receiver,
3622               cache_array, cache_type, index, feedback_vector_node());
3623   environment()->BindAccumulator(node, Environment::kAttachFrameState);
3624 }
3625 
VisitForInStep()3626 void BytecodeGraphBuilder::VisitForInStep() {
3627   PrepareEagerCheckpoint();
3628   Node* index =
3629       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3630   index = NewNode(simplified()->SpeculativeSafeIntegerAdd(
3631                       NumberOperationHint::kSignedSmall),
3632                   index, jsgraph()->OneConstant());
3633   environment()->BindAccumulator(index, Environment::kAttachFrameState);
3634 }
3635 
VisitGetIterator()3636 void BytecodeGraphBuilder::VisitGetIterator() {
3637   PrepareEagerCheckpoint();
3638   Node* receiver =
3639       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3640   FeedbackSource load_feedback =
3641       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1));
3642   FeedbackSource call_feedback =
3643       CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2));
3644   const Operator* op = javascript()->GetIterator(load_feedback, call_feedback);
3645 
3646   JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedGetIterator(
3647       op, receiver, load_feedback.slot, call_feedback.slot);
3648   if (lowering.IsExit()) return;
3649 
3650   DCHECK(!lowering.Changed());
3651   STATIC_ASSERT(JSGetIteratorNode::ReceiverIndex() == 0);
3652   STATIC_ASSERT(JSGetIteratorNode::FeedbackVectorIndex() == 1);
3653   DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode()));
3654   Node* iterator = NewNode(op, receiver, feedback_vector_node());
3655   environment()->BindAccumulator(iterator, Environment::kAttachFrameState);
3656 }
3657 
VisitSuspendGenerator()3658 void BytecodeGraphBuilder::VisitSuspendGenerator() {
3659   Node* generator = environment()->LookupRegister(
3660       bytecode_iterator().GetRegisterOperand(0));
3661   interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
3662   // We assume we are storing a range starting from index 0.
3663   CHECK_EQ(0, first_reg.index());
3664   int register_count =
3665       static_cast<int>(bytecode_iterator().GetRegisterCountOperand(2));
3666   int parameter_count_without_receiver = bytecode_array().parameter_count() - 1;
3667 
3668   Node* suspend_id = jsgraph()->SmiConstant(
3669       bytecode_iterator().GetUnsignedImmediateOperand(3));
3670 
3671   // The offsets used by the bytecode iterator are relative to a different base
3672   // than what is used in the interpreter, hence the addition.
3673   Node* offset =
3674       jsgraph()->Constant(bytecode_iterator().current_offset() +
3675                           (BytecodeArray::kHeaderSize - kHeapObjectTag));
3676 
3677   const BytecodeLivenessState* liveness = bytecode_analysis().GetInLivenessFor(
3678       bytecode_iterator().current_offset());
3679 
3680   // Maybe overallocate the value list since we don't know how many registers
3681   // are live.
3682   // TODO(leszeks): We could get this count from liveness rather than the
3683   // register list.
3684   int value_input_count = 3 + parameter_count_without_receiver + register_count;
3685 
3686   Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count);
3687   value_inputs[0] = generator;
3688   value_inputs[1] = suspend_id;
3689   value_inputs[2] = offset;
3690 
3691   int count_written = 0;
3692   // Store the parameters.
3693   for (int i = 0; i < parameter_count_without_receiver; i++) {
3694     value_inputs[3 + count_written++] =
3695         environment()->LookupRegister(bytecode_iterator().GetParameter(i));
3696   }
3697 
3698   // Store the registers.
3699   for (int i = 0; i < register_count; ++i) {
3700     if (liveness == nullptr || liveness->RegisterIsLive(i)) {
3701       int index_in_parameters_and_registers =
3702           parameter_count_without_receiver + i;
3703       while (count_written < index_in_parameters_and_registers) {
3704         value_inputs[3 + count_written++] = jsgraph()->OptimizedOutConstant();
3705       }
3706       value_inputs[3 + count_written++] =
3707           environment()->LookupRegister(interpreter::Register(i));
3708       DCHECK_EQ(count_written, index_in_parameters_and_registers + 1);
3709     }
3710   }
3711 
3712   // Use the actual written count rather than the register count to create the
3713   // node.
3714   MakeNode(javascript()->GeneratorStore(count_written), 3 + count_written,
3715            value_inputs, false);
3716 
3717   // TODO(leszeks): This over-approximates the liveness at exit, only the
3718   // accumulator should be live by this point.
3719   BuildReturn(bytecode_analysis().GetInLivenessFor(
3720       bytecode_iterator().current_offset()));
3721 }
3722 
BuildSwitchOnGeneratorState( const ZoneVector<ResumeJumpTarget>& resume_jump_targets, bool allow_fallthrough_on_executing)3723 void BytecodeGraphBuilder::BuildSwitchOnGeneratorState(
3724     const ZoneVector<ResumeJumpTarget>& resume_jump_targets,
3725     bool allow_fallthrough_on_executing) {
3726   Node* generator_state = environment()->LookupGeneratorState();
3727 
3728   int extra_cases = allow_fallthrough_on_executing ? 2 : 1;
3729   NewSwitch(generator_state,
3730             static_cast<int>(resume_jump_targets.size() + extra_cases));
3731   for (const ResumeJumpTarget& target : resume_jump_targets) {
3732     SubEnvironment sub_environment(this);
3733     NewIfValue(target.suspend_id());
3734     if (target.is_leaf()) {
3735       // Mark that we are resuming executing.
3736       environment()->BindGeneratorState(
3737           jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting));
3738     }
3739     // Jump to the target offset, whether it's a loop header or the resume.
3740     MergeIntoSuccessorEnvironment(target.target_offset());
3741   }
3742 
3743   {
3744     SubEnvironment sub_environment(this);
3745     // We should never hit the default case (assuming generator state cannot be
3746     // corrupted), so abort if we do.
3747     // TODO(leszeks): Maybe only check this in debug mode, and otherwise use
3748     // the default to represent one of the cases above/fallthrough below?
3749     NewIfDefault();
3750     NewNode(simplified()->RuntimeAbort(AbortReason::kInvalidJumpTableIndex));
3751     // TODO(7099): Investigate if we need LoopExit here.
3752     Node* control = NewNode(common()->Throw());
3753     MergeControlToLeaveFunction(control);
3754   }
3755 
3756   if (allow_fallthrough_on_executing) {
3757     // If we are executing (rather than resuming), and we allow it, just fall
3758     // through to the actual loop body.
3759     NewIfValue(JSGeneratorObject::kGeneratorExecuting);
3760   } else {
3761     // Otherwise, this environment is dead.
3762     set_environment(nullptr);
3763   }
3764 }
3765 
VisitSwitchOnGeneratorState()3766 void BytecodeGraphBuilder::VisitSwitchOnGeneratorState() {
3767   Node* generator =
3768       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3769 
3770   Node* generator_is_undefined =
3771       NewNode(simplified()->ReferenceEqual(), generator,
3772               jsgraph()->UndefinedConstant());
3773 
3774   NewBranch(generator_is_undefined);
3775   {
3776     SubEnvironment resume_env(this);
3777     NewIfFalse();
3778 
3779     Node* generator_state =
3780         NewNode(javascript()->GeneratorRestoreContinuation(), generator);
3781     environment()->BindGeneratorState(generator_state);
3782 
3783     Node* generator_context =
3784         NewNode(javascript()->GeneratorRestoreContext(), generator);
3785     environment()->SetContext(generator_context);
3786 
3787     BuildSwitchOnGeneratorState(bytecode_analysis().resume_jump_targets(),
3788                                 false);
3789   }
3790 
3791   // Fallthrough for the first-call case.
3792   NewIfTrue();
3793 }
3794 
VisitResumeGenerator()3795 void BytecodeGraphBuilder::VisitResumeGenerator() {
3796   Node* generator =
3797       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
3798   interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
3799   // We assume we are restoring registers starting fromm index 0.
3800   CHECK_EQ(0, first_reg.index());
3801 
3802   const BytecodeLivenessState* liveness = bytecode_analysis().GetOutLivenessFor(
3803       bytecode_iterator().current_offset());
3804 
3805   int parameter_count_without_receiver = bytecode_array().parameter_count() - 1;
3806 
3807   // Mapping between registers and array indices must match that used in
3808   // InterpreterAssembler::ExportParametersAndRegisterFile.
3809   for (int i = 0; i < environment()->register_count(); ++i) {
3810     if (liveness == nullptr || liveness->RegisterIsLive(i)) {
3811       Node* value = NewNode(javascript()->GeneratorRestoreRegister(
3812                                 parameter_count_without_receiver + i),
3813                             generator);
3814       environment()->BindRegister(interpreter::Register(i), value);
3815     }
3816   }
3817 
3818   // Update the accumulator with the generator's input_or_debug_pos.
3819   Node* input_or_debug_pos =
3820       NewNode(javascript()->GeneratorRestoreInputOrDebugPos(), generator);
3821   environment()->BindAccumulator(input_or_debug_pos);
3822 }
3823 
VisitWide()3824 void BytecodeGraphBuilder::VisitWide() {
3825   // Consumed by the BytecodeArrayIterator.
3826   UNREACHABLE();
3827 }
3828 
VisitExtraWide()3829 void BytecodeGraphBuilder::VisitExtraWide() {
3830   // Consumed by the BytecodeArrayIterator.
3831   UNREACHABLE();
3832 }
3833 
VisitIllegal()3834 void BytecodeGraphBuilder::VisitIllegal() {
3835   // Not emitted in valid bytecode.
3836   UNREACHABLE();
3837 }
3838 
SwitchToMergeEnvironment(int current_offset)3839 void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) {
3840   auto it = merge_environments_.find(current_offset);
3841   if (it != merge_environments_.end()) {
3842     mark_as_needing_eager_checkpoint(true);
3843     if (environment() != nullptr) {
3844       it->second->Merge(environment(),
3845                         bytecode_analysis().GetInLivenessFor(current_offset));
3846     }
3847     set_environment(it->second);
3848   }
3849 }
3850 
BuildLoopHeaderEnvironment(int current_offset)3851 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) {
3852   if (bytecode_analysis().IsLoopHeader(current_offset)) {
3853     mark_as_needing_eager_checkpoint(true);
3854     const LoopInfo& loop_info =
3855         bytecode_analysis().GetLoopInfoFor(current_offset);
3856     const BytecodeLivenessState* liveness =
3857         bytecode_analysis().GetInLivenessFor(current_offset);
3858 
3859     const auto& resume_jump_targets = loop_info.resume_jump_targets();
3860     bool generate_suspend_switch = !resume_jump_targets.empty();
3861 
3862     // Add loop header.
3863     environment()->PrepareForLoop(loop_info.assignments(), liveness);
3864 
3865     // Store a copy of the environment so we can connect merged back edge inputs
3866     // to the loop header.
3867     merge_environments_[current_offset] = environment()->Copy();
3868 
3869     // If this loop contains resumes, create a new switch just after the loop
3870     // for those resumes.
3871     if (generate_suspend_switch) {
3872       BuildSwitchOnGeneratorState(loop_info.resume_jump_targets(), true);
3873 
3874       // TODO(leszeks): At this point we know we are executing rather than
3875       // resuming, so we should be able to prune off the phis in the environment
3876       // related to the resume path.
3877 
3878       // Set the generator state to a known constant.
3879       environment()->BindGeneratorState(
3880           jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting));
3881     }
3882   }
3883 }
3884 
MergeIntoSuccessorEnvironment(int target_offset)3885 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) {
3886   BuildLoopExitsForBranch(target_offset);
3887   Environment*& merge_environment = merge_environments_[target_offset];
3888 
3889   if (merge_environment == nullptr) {
3890     // Append merge nodes to the environment. We may merge here with another
3891     // environment. So add a place holder for merge nodes. We may add redundant
3892     // but will be eliminated in a later pass.
3893     NewMerge();
3894     merge_environment = environment();
3895   } else {
3896     // Merge any values which are live coming into the successor.
3897     merge_environment->Merge(
3898         environment(), bytecode_analysis().GetInLivenessFor(target_offset));
3899   }
3900   set_environment(nullptr);
3901 }
3902 
MergeControlToLeaveFunction(Node* exit)3903 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) {
3904   exit_controls_.push_back(exit);
3905   set_environment(nullptr);
3906 }
3907 
BuildLoopExitsForBranch(int target_offset)3908 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) {
3909   int origin_offset = bytecode_iterator().current_offset();
3910   // Only build loop exits for forward edges.
3911   if (target_offset > origin_offset) {
3912     BuildLoopExitsUntilLoop(
3913         bytecode_analysis().GetLoopOffsetFor(target_offset),
3914         bytecode_analysis().GetInLivenessFor(target_offset));
3915   }
3916 }
3917 
BuildLoopExitsUntilLoop( int loop_offset, const BytecodeLivenessState* liveness)3918 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(
3919     int loop_offset, const BytecodeLivenessState* liveness) {
3920   int origin_offset = bytecode_iterator().current_offset();
3921   int current_loop = bytecode_analysis().GetLoopOffsetFor(origin_offset);
3922   // The limit_offset is the stop offset for building loop exists, used for OSR.
3923   // It prevents the creations of loopexits for loops which do not exist.
3924   loop_offset = std::max(loop_offset, currently_peeled_loop_offset_);
3925 
3926   while (loop_offset < current_loop) {
3927     Node* loop_node = merge_environments_[current_loop]->GetControlDependency();
3928     const LoopInfo& loop_info =
3929         bytecode_analysis().GetLoopInfoFor(current_loop);
3930     environment()->PrepareForLoopExit(loop_node, loop_info.assignments(),
3931                                       liveness);
3932     current_loop = loop_info.parent_offset();
3933   }
3934 }
3935 
BuildLoopExitsForFunctionExit( const BytecodeLivenessState* liveness)3936 void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit(
3937     const BytecodeLivenessState* liveness) {
3938   BuildLoopExitsUntilLoop(-1, liveness);
3939 }
3940 
BuildJump()3941 void BytecodeGraphBuilder::BuildJump() {
3942   MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
3943 }
3944 
BuildJumpIf(Node* condition)3945 void BytecodeGraphBuilder::BuildJumpIf(Node* condition) {
3946   NewBranch(condition, BranchHint::kNone);
3947   {
3948     SubEnvironment sub_environment(this);
3949     NewIfTrue();
3950     MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
3951   }
3952   NewIfFalse();
3953 }
3954 
BuildJumpIfNot(Node* condition)3955 void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) {
3956   NewBranch(condition, BranchHint::kNone);
3957   {
3958     SubEnvironment sub_environment(this);
3959     NewIfFalse();
3960     MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
3961   }
3962   NewIfTrue();
3963 }
3964 
BuildJumpIfEqual(Node* comperand)3965 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
3966   Node* accumulator = environment()->LookupAccumulator();
3967   Node* condition =
3968       NewNode(simplified()->ReferenceEqual(), accumulator, comperand);
3969   BuildJumpIf(condition);
3970 }
3971 
BuildJumpIfNotEqual(Node* comperand)3972 void BytecodeGraphBuilder::BuildJumpIfNotEqual(Node* comperand) {
3973   Node* accumulator = environment()->LookupAccumulator();
3974   Node* condition =
3975       NewNode(simplified()->ReferenceEqual(), accumulator, comperand);
3976   BuildJumpIfNot(condition);
3977 }
3978 
BuildJumpIfFalse()3979 void BytecodeGraphBuilder::BuildJumpIfFalse() {
3980   NewBranch(environment()->LookupAccumulator(), BranchHint::kNone);
3981   {
3982     SubEnvironment sub_environment(this);
3983     NewIfFalse();
3984     environment()->BindAccumulator(jsgraph()->FalseConstant());
3985     MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
3986   }
3987   NewIfTrue();
3988   environment()->BindAccumulator(jsgraph()->TrueConstant());
3989 }
3990 
BuildJumpIfTrue()3991 void BytecodeGraphBuilder::BuildJumpIfTrue() {
3992   NewBranch(environment()->LookupAccumulator(), BranchHint::kNone);
3993   {
3994     SubEnvironment sub_environment(this);
3995     NewIfTrue();
3996     environment()->BindAccumulator(jsgraph()->TrueConstant());
3997     MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
3998   }
3999   NewIfFalse();
4000   environment()->BindAccumulator(jsgraph()->FalseConstant());
4001 }
4002 
BuildJumpIfToBooleanTrue()4003 void BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() {
4004   Node* accumulator = environment()->LookupAccumulator();
4005   Node* condition = NewNode(simplified()->ToBoolean(), accumulator);
4006   BuildJumpIf(condition);
4007 }
4008 
BuildJumpIfToBooleanFalse()4009 void BytecodeGraphBuilder::BuildJumpIfToBooleanFalse() {
4010   Node* accumulator = environment()->LookupAccumulator();
4011   Node* condition = NewNode(simplified()->ToBoolean(), accumulator);
4012   BuildJumpIfNot(condition);
4013 }
4014 
BuildJumpIfNotHole()4015 void BytecodeGraphBuilder::BuildJumpIfNotHole() {
4016   Node* accumulator = environment()->LookupAccumulator();
4017   Node* condition = NewNode(simplified()->ReferenceEqual(), accumulator,
4018                             jsgraph()->TheHoleConstant());
4019   BuildJumpIfNot(condition);
4020 }
4021 
BuildJumpIfJSReceiver()4022 void BytecodeGraphBuilder::BuildJumpIfJSReceiver() {
4023   Node* accumulator = environment()->LookupAccumulator();
4024   Node* condition = NewNode(simplified()->ObjectIsReceiver(), accumulator);
4025   BuildJumpIf(condition);
4026 }
4027 
4028 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedUnaryOp(const Operator* op, Node* operand, FeedbackSlot slot)4029 BytecodeGraphBuilder::TryBuildSimplifiedUnaryOp(const Operator* op,
4030                                                 Node* operand,
4031                                                 FeedbackSlot slot) {
4032   Node* effect = environment()->GetEffectDependency();
4033   Node* control = environment()->GetControlDependency();
4034   JSTypeHintLowering::LoweringResult result =
4035       type_hint_lowering().ReduceUnaryOperation(op, operand, effect, control,
4036                                                 slot);
4037   ApplyEarlyReduction(result);
4038   return result;
4039 }
4040 
4041 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedBinaryOp(const Operator* op, Node* left, Node* right, FeedbackSlot slot)4042 BytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op, Node* left,
4043                                                  Node* right,
4044                                                  FeedbackSlot slot) {
4045   Node* effect = environment()->GetEffectDependency();
4046   Node* control = environment()->GetControlDependency();
4047   JSTypeHintLowering::LoweringResult result =
4048       type_hint_lowering().ReduceBinaryOperation(op, left, right, effect,
4049                                                  control, slot);
4050   ApplyEarlyReduction(result);
4051   return result;
4052 }
4053 
4054 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedForInNext(Node* receiver, Node* cache_array, Node* cache_type, Node* index, FeedbackSlot slot)4055 BytecodeGraphBuilder::TryBuildSimplifiedForInNext(Node* receiver,
4056                                                   Node* cache_array,
4057                                                   Node* cache_type, Node* index,
4058                                                   FeedbackSlot slot) {
4059   Node* effect = environment()->GetEffectDependency();
4060   Node* control = environment()->GetControlDependency();
4061   JSTypeHintLowering::LoweringResult result =
4062       type_hint_lowering().ReduceForInNextOperation(
4063           receiver, cache_array, cache_type, index, effect, control, slot);
4064   ApplyEarlyReduction(result);
4065   return result;
4066 }
4067 
4068 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedForInPrepare(Node* enumerator, FeedbackSlot slot)4069 BytecodeGraphBuilder::TryBuildSimplifiedForInPrepare(Node* enumerator,
4070                                                      FeedbackSlot slot) {
4071   Node* effect = environment()->GetEffectDependency();
4072   Node* control = environment()->GetControlDependency();
4073   JSTypeHintLowering::LoweringResult result =
4074       type_hint_lowering().ReduceForInPrepareOperation(enumerator, effect,
4075                                                        control, slot);
4076   ApplyEarlyReduction(result);
4077   return result;
4078 }
4079 
4080 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedToNumber(Node* value, FeedbackSlot slot)4081 BytecodeGraphBuilder::TryBuildSimplifiedToNumber(Node* value,
4082                                                  FeedbackSlot slot) {
4083   Node* effect = environment()->GetEffectDependency();
4084   Node* control = environment()->GetControlDependency();
4085   JSTypeHintLowering::LoweringResult result =
4086       type_hint_lowering().ReduceToNumberOperation(value, effect, control,
4087                                                    slot);
4088   ApplyEarlyReduction(result);
4089   return result;
4090 }
4091 
TryBuildSimplifiedCall( const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot)4092 JSTypeHintLowering::LoweringResult BytecodeGraphBuilder::TryBuildSimplifiedCall(
4093     const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot) {
4094   Node* effect = environment()->GetEffectDependency();
4095   Node* control = environment()->GetControlDependency();
4096   JSTypeHintLowering::LoweringResult result =
4097       type_hint_lowering().ReduceCallOperation(op, args, arg_count, effect,
4098                                                control, slot);
4099   ApplyEarlyReduction(result);
4100   return result;
4101 }
4102 
4103 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedConstruct(const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot)4104 BytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op,
4105                                                   Node* const* args,
4106                                                   int arg_count,
4107                                                   FeedbackSlot slot) {
4108   Node* effect = environment()->GetEffectDependency();
4109   Node* control = environment()->GetControlDependency();
4110   JSTypeHintLowering::LoweringResult result =
4111       type_hint_lowering().ReduceConstructOperation(op, args, arg_count, effect,
4112                                                     control, slot);
4113   ApplyEarlyReduction(result);
4114   return result;
4115 }
4116 
4117 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedGetIterator(const Operator* op, Node* receiver, FeedbackSlot load_slot, FeedbackSlot call_slot)4118 BytecodeGraphBuilder::TryBuildSimplifiedGetIterator(const Operator* op,
4119                                                     Node* receiver,
4120                                                     FeedbackSlot load_slot,
4121                                                     FeedbackSlot call_slot) {
4122   Node* effect = environment()->GetEffectDependency();
4123   Node* control = environment()->GetControlDependency();
4124   JSTypeHintLowering::LoweringResult early_reduction =
4125       type_hint_lowering().ReduceGetIteratorOperation(
4126           op, receiver, effect, control, load_slot, call_slot);
4127   ApplyEarlyReduction(early_reduction);
4128   return early_reduction;
4129 }
4130 
4131 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedLoadNamed(const Operator* op, FeedbackSlot slot)4132 BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op,
4133                                                   FeedbackSlot slot) {
4134   Node* effect = environment()->GetEffectDependency();
4135   Node* control = environment()->GetControlDependency();
4136   JSTypeHintLowering::LoweringResult early_reduction =
4137       type_hint_lowering().ReduceLoadNamedOperation(op, effect, control, slot);
4138   ApplyEarlyReduction(early_reduction);
4139   return early_reduction;
4140 }
4141 
4142 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedLoadKeyed(const Operator* op, Node* receiver, Node* key, FeedbackSlot slot)4143 BytecodeGraphBuilder::TryBuildSimplifiedLoadKeyed(const Operator* op,
4144                                                   Node* receiver, Node* key,
4145                                                   FeedbackSlot slot) {
4146   Node* effect = environment()->GetEffectDependency();
4147   Node* control = environment()->GetControlDependency();
4148   JSTypeHintLowering::LoweringResult result =
4149       type_hint_lowering().ReduceLoadKeyedOperation(op, receiver, key, effect,
4150                                                     control, slot);
4151   ApplyEarlyReduction(result);
4152   return result;
4153 }
4154 
4155 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedStoreNamed(const Operator* op, Node* receiver, Node* value, FeedbackSlot slot)4156 BytecodeGraphBuilder::TryBuildSimplifiedStoreNamed(const Operator* op,
4157                                                    Node* receiver, Node* value,
4158                                                    FeedbackSlot slot) {
4159   Node* effect = environment()->GetEffectDependency();
4160   Node* control = environment()->GetControlDependency();
4161   JSTypeHintLowering::LoweringResult result =
4162       type_hint_lowering().ReduceStoreNamedOperation(op, receiver, value,
4163                                                      effect, control, slot);
4164   ApplyEarlyReduction(result);
4165   return result;
4166 }
4167 
4168 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedStoreKeyed(const Operator* op, Node* receiver, Node* key, Node* value, FeedbackSlot slot)4169 BytecodeGraphBuilder::TryBuildSimplifiedStoreKeyed(const Operator* op,
4170                                                    Node* receiver, Node* key,
4171                                                    Node* value,
4172                                                    FeedbackSlot slot) {
4173   Node* effect = environment()->GetEffectDependency();
4174   Node* control = environment()->GetControlDependency();
4175   JSTypeHintLowering::LoweringResult result =
4176       type_hint_lowering().ReduceStoreKeyedOperation(op, receiver, key, value,
4177                                                      effect, control, slot);
4178   ApplyEarlyReduction(result);
4179   return result;
4180 }
4181 
ApplyEarlyReduction( JSTypeHintLowering::LoweringResult reduction)4182 void BytecodeGraphBuilder::ApplyEarlyReduction(
4183     JSTypeHintLowering::LoweringResult reduction) {
4184   if (reduction.IsExit()) {
4185     MergeControlToLeaveFunction(reduction.control());
4186   } else if (reduction.IsSideEffectFree()) {
4187     environment()->UpdateEffectDependency(reduction.effect());
4188     environment()->UpdateControlDependency(reduction.control());
4189   } else {
4190     DCHECK(!reduction.Changed());
4191     // At the moment, we assume side-effect free reduction. To support
4192     // side-effects, we would have to invalidate the eager checkpoint,
4193     // so that deoptimization does not repeat the side effect.
4194   }
4195 }
4196 
EnsureInputBufferSize(int size)4197 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
4198   if (size > input_buffer_size_) {
4199     size = size + kInputBufferSizeIncrement + input_buffer_size_;
4200     input_buffer_ = local_zone()->NewArray<Node*>(size);
4201     input_buffer_size_ = size;
4202   }
4203   return input_buffer_;
4204 }
4205 
ExitThenEnterExceptionHandlers(int current_offset)4206 void BytecodeGraphBuilder::ExitThenEnterExceptionHandlers(int current_offset) {
4207   DisallowGarbageCollection no_gc;
4208   HandlerTable table(bytecode_array().handler_table_address(),
4209                      bytecode_array().handler_table_size(),
4210                      HandlerTable::kRangeBasedEncoding);
4211 
4212   // Potentially exit exception handlers.
4213   while (!exception_handlers_.empty()) {
4214     int current_end = exception_handlers_.top().end_offset_;
4215     if (current_offset < current_end) break;  // Still covered by range.
4216     exception_handlers_.pop();
4217   }
4218 
4219   // Potentially enter exception handlers.
4220   int num_entries = table.NumberOfRangeEntries();
4221   while (current_exception_handler_ < num_entries) {
4222     int next_start = table.GetRangeStart(current_exception_handler_);
4223     if (current_offset < next_start) break;  // Not yet covered by range.
4224     int next_end = table.GetRangeEnd(current_exception_handler_);
4225     int next_handler = table.GetRangeHandler(current_exception_handler_);
4226     int context_register = table.GetRangeData(current_exception_handler_);
4227     exception_handlers_.push(
4228         {next_start, next_end, next_handler, context_register});
4229     current_exception_handler_++;
4230   }
4231 }
4232 
MakeNode(const Operator* op, int value_input_count, Node* const* value_inputs, bool incomplete)4233 Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
4234                                      Node* const* value_inputs,
4235                                      bool incomplete) {
4236   DCHECK_EQ(op->ValueInputCount(), value_input_count);
4237   // Parameter nodes must be created through GetParameter.
4238   DCHECK_IMPLIES(
4239       op->opcode() == IrOpcode::kParameter,
4240       (nullptr == cached_parameters_[static_cast<std::size_t>(
4241                       ParameterIndexOf(op) - ParameterInfo::kMinIndex)]));
4242 
4243   bool has_context = OperatorProperties::HasContextInput(op);
4244   bool has_frame_state = OperatorProperties::HasFrameStateInput(op);
4245   bool has_control = op->ControlInputCount() == 1;
4246   bool has_effect = op->EffectInputCount() == 1;
4247 
4248   DCHECK_LT(op->ControlInputCount(), 2);
4249   DCHECK_LT(op->EffectInputCount(), 2);
4250 
4251   Node* result = nullptr;
4252   if (!has_context && !has_frame_state && !has_control && !has_effect) {
4253     result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
4254   } else {
4255     bool inside_handler = !exception_handlers_.empty();
4256     int input_count_with_deps = value_input_count;
4257     if (has_context) ++input_count_with_deps;
4258     if (has_frame_state) ++input_count_with_deps;
4259     if (has_control) ++input_count_with_deps;
4260     if (has_effect) ++input_count_with_deps;
4261     Node** buffer = EnsureInputBufferSize(input_count_with_deps);
4262     if (value_input_count > 0) {
4263       memcpy(buffer, value_inputs, kSystemPointerSize * value_input_count);
4264     }
4265     Node** current_input = buffer + value_input_count;
4266     if (has_context) {
4267       *current_input++ = OperatorProperties::NeedsExactContext(op)
4268                              ? environment()->Context()
4269                              : native_context_node();
4270     }
4271     if (has_frame_state) {
4272       // The frame state will be inserted later. Here we misuse the {Dead} node
4273       // as a sentinel to be later overwritten with the real frame state by the
4274       // calls to {PrepareFrameState} within individual visitor methods.
4275       *current_input++ = jsgraph()->Dead();
4276     }
4277     if (has_effect) {
4278       *current_input++ = environment()->GetEffectDependency();
4279     }
4280     if (has_control) {
4281       *current_input++ = environment()->GetControlDependency();
4282     }
4283     result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
4284     // Update the current control dependency for control-producing nodes.
4285     if (result->op()->ControlOutputCount() > 0) {
4286       environment()->UpdateControlDependency(result);
4287     }
4288     // Update the current effect dependency for effect-producing nodes.
4289     if (result->op()->EffectOutputCount() > 0) {
4290       environment()->UpdateEffectDependency(result);
4291     }
4292     // Add implicit exception continuation for throwing nodes.
4293     if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
4294       int handler_offset = exception_handlers_.top().handler_offset_;
4295       int context_index = exception_handlers_.top().context_register_;
4296       interpreter::Register context_register(context_index);
4297       Environment* success_env = environment()->Copy();
4298       const Operator* if_exception = common()->IfException();
4299       Node* effect = environment()->GetEffectDependency();
4300       Node* on_exception = graph()->NewNode(if_exception, effect, result);
4301       Node* context = environment()->LookupRegister(context_register);
4302       environment()->UpdateControlDependency(on_exception);
4303       environment()->UpdateEffectDependency(on_exception);
4304       environment()->BindAccumulator(on_exception);
4305       environment()->SetContext(context);
4306       MergeIntoSuccessorEnvironment(handler_offset);
4307       set_environment(success_env);
4308     }
4309     // Add implicit success continuation for throwing nodes.
4310     if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
4311       const Operator* if_success = common()->IfSuccess();
4312       Node* on_success = graph()->NewNode(if_success, result);
4313       environment()->UpdateControlDependency(on_success);
4314     }
4315     // Ensure checkpoints are created after operations with side-effects.
4316     if (has_effect && !result->op()->HasProperty(Operator::kNoWrite)) {
4317       mark_as_needing_eager_checkpoint(true);
4318     }
4319   }
4320 
4321   return result;
4322 }
4323 
4324 
NewPhi(int count, Node* input, Node* control)4325 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) {
4326   const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
4327   Node** buffer = EnsureInputBufferSize(count + 1);
4328   MemsetPointer(buffer, input, count);
4329   buffer[count] = control;
4330   return graph()->NewNode(phi_op, count + 1, buffer, true);
4331 }
4332 
NewEffectPhi(int count, Node* input, Node* control)4333 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input,
4334                                          Node* control) {
4335   const Operator* phi_op = common()->EffectPhi(count);
4336   Node** buffer = EnsureInputBufferSize(count + 1);
4337   MemsetPointer(buffer, input, count);
4338   buffer[count] = control;
4339   return graph()->NewNode(phi_op, count + 1, buffer, true);
4340 }
4341 
4342 
MergeControl(Node* control, Node* other)4343 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
4344   int inputs = control->op()->ControlInputCount() + 1;
4345   if (control->opcode() == IrOpcode::kLoop) {
4346     // Control node for loop exists, add input.
4347     const Operator* op = common()->Loop(inputs);
4348     control->AppendInput(graph_zone(), other);
4349     NodeProperties::ChangeOp(control, op);
4350   } else if (control->opcode() == IrOpcode::kMerge) {
4351     // Control node for merge exists, add input.
4352     const Operator* op = common()->Merge(inputs);
4353     control->AppendInput(graph_zone(), other);
4354     NodeProperties::ChangeOp(control, op);
4355   } else {
4356     // Control node is a singleton, introduce a merge.
4357     const Operator* op = common()->Merge(inputs);
4358     Node* merge_inputs[] = {control, other};
4359     control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true);
4360   }
4361   return control;
4362 }
4363 
MergeEffect(Node* value, Node* other, Node* control)4364 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
4365                                         Node* control) {
4366   int inputs = control->op()->ControlInputCount();
4367   if (value->opcode() == IrOpcode::kEffectPhi &&
4368       NodeProperties::GetControlInput(value) == control) {
4369     // Phi already exists, add input.
4370     value->InsertInput(graph_zone(), inputs - 1, other);
4371     NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
4372   } else if (value != other) {
4373     // Phi does not exist yet, introduce one.
4374     value = NewEffectPhi(inputs, value, control);
4375     value->ReplaceInput(inputs - 1, other);
4376   }
4377   return value;
4378 }
4379 
MergeValue(Node* value, Node* other, Node* control)4380 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
4381                                        Node* control) {
4382   int inputs = control->op()->ControlInputCount();
4383   if (value->opcode() == IrOpcode::kPhi &&
4384       NodeProperties::GetControlInput(value) == control) {
4385     // Phi already exists, add input.
4386     value->InsertInput(graph_zone(), inputs - 1, other);
4387     NodeProperties::ChangeOp(
4388         value, common()->Phi(MachineRepresentation::kTagged, inputs));
4389   } else if (value != other) {
4390     // Phi does not exist yet, introduce one.
4391     value = NewPhi(inputs, value, control);
4392     value->ReplaceInput(inputs - 1, other);
4393   }
4394   return value;
4395 }
4396 
UpdateSourcePosition(int offset)4397 void BytecodeGraphBuilder::UpdateSourcePosition(int offset) {
4398   if (source_position_iterator().done()) return;
4399   if (source_position_iterator().code_offset() == offset) {
4400     source_positions_->SetCurrentPosition(SourcePosition(
4401         source_position_iterator().source_position().ScriptOffset(),
4402         start_position_.InliningId()));
4403     source_position_iterator().Advance();
4404   } else {
4405     DCHECK_GT(source_position_iterator().code_offset(), offset);
4406   }
4407 }
4408 
BuildGraphFromBytecode(JSHeapBroker* broker, Zone* local_zone, SharedFunctionInfoRef const& shared_info, FeedbackCellRef const& feedback_cell, BytecodeOffset osr_offset, JSGraph* jsgraph, CallFrequency const& invocation_frequency, SourcePositionTable* source_positions, int inlining_id, CodeKind code_kind, BytecodeGraphBuilderFlags flags, TickCounter* tick_counter, ObserveNodeInfo const& observe_node_info)4409 void BuildGraphFromBytecode(JSHeapBroker* broker, Zone* local_zone,
4410                             SharedFunctionInfoRef const& shared_info,
4411                             FeedbackCellRef const& feedback_cell,
4412                             BytecodeOffset osr_offset, JSGraph* jsgraph,
4413                             CallFrequency const& invocation_frequency,
4414                             SourcePositionTable* source_positions,
4415                             int inlining_id, CodeKind code_kind,
4416                             BytecodeGraphBuilderFlags flags,
4417                             TickCounter* tick_counter,
4418                             ObserveNodeInfo const& observe_node_info) {
4419   BytecodeGraphBuilder builder(
4420       broker, local_zone, broker->target_native_context(), shared_info,
4421       feedback_cell, osr_offset, jsgraph, invocation_frequency,
4422       source_positions, inlining_id, code_kind, flags, tick_counter,
4423       observe_node_info);
4424   builder.CreateGraph();
4425 }
4426 
4427 }  // namespace compiler
4428 }  // namespace internal
4429 }  // namespace v8
4430