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