1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/compiler/bytecode-graph-builder.h"
6
7 #include "src/ast/ast.h"
8 #include "src/ast/scopes.h"
9 #include "src/compiler/access-builder.h"
10 #include "src/compiler/compiler-source-position-table.h"
11 #include "src/compiler/linkage.h"
12 #include "src/compiler/node-matchers.h"
13 #include "src/compiler/operator-properties.h"
14 #include "src/compiler/simplified-operator.h"
15 #include "src/interpreter/bytecodes.h"
16 #include "src/objects-inl.h"
17 #include "src/objects/js-array-inl.h"
18 #include "src/objects/js-generator.h"
19 #include "src/objects/literal-objects-inl.h"
20 #include "src/vector-slot-pair.h"
21
22 namespace v8 {
23 namespace internal {
24 namespace compiler {
25
26 // The abstract execution environment simulates the content of the interpreter
27 // register file. The environment performs SSA-renaming of all tracked nodes at
28 // split and merge points in the control flow.
29 class BytecodeGraphBuilder::Environment : public ZoneObject {
30 public:
31 Environment(BytecodeGraphBuilder* builder, int register_count,
32 int parameter_count,
33 interpreter::Register incoming_new_target_or_generator,
34 Node* control_dependency);
35
36 // Specifies whether environment binding methods should attach frame state
37 // inputs to nodes representing the value being bound. This is done because
38 // the {OutputFrameStateCombine} is closely related to the binding method.
39 enum FrameStateAttachmentMode { kAttachFrameState, kDontAttachFrameState };
40
parameter_count() const41 int parameter_count() const { return parameter_count_; }
register_count() const42 int register_count() const { return register_count_; }
43
44 Node* LookupAccumulator() const;
45 Node* LookupRegister(interpreter::Register the_register) const;
46 Node* LookupGeneratorState() const;
47
48 void BindAccumulator(Node* node,
49 FrameStateAttachmentMode mode = kDontAttachFrameState);
50 void BindRegister(interpreter::Register the_register, Node* node,
51 FrameStateAttachmentMode mode = kDontAttachFrameState);
52 void BindRegistersToProjections(
53 interpreter::Register first_reg, Node* node,
54 FrameStateAttachmentMode mode = kDontAttachFrameState);
55 void BindGeneratorState(Node* node);
56 void RecordAfterState(Node* node,
57 FrameStateAttachmentMode mode = kDontAttachFrameState);
58
59 // Effect dependency tracked by this environment.
GetEffectDependency()60 Node* GetEffectDependency() { return effect_dependency_; }
UpdateEffectDependency(Node * dependency)61 void UpdateEffectDependency(Node* dependency) {
62 effect_dependency_ = dependency;
63 }
64
65 // Preserve a checkpoint of the environment for the IR graph. Any
66 // further mutation of the environment will not affect checkpoints.
67 Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine,
68 const BytecodeLivenessState* liveness);
69
70 // Control dependency tracked by this environment.
GetControlDependency() const71 Node* GetControlDependency() const { return control_dependency_; }
UpdateControlDependency(Node * dependency)72 void UpdateControlDependency(Node* dependency) {
73 control_dependency_ = dependency;
74 }
75
Context() const76 Node* Context() const { return context_; }
SetContext(Node * new_context)77 void SetContext(Node* new_context) { context_ = new_context; }
78
79 Environment* Copy();
80 void Merge(Environment* other, const BytecodeLivenessState* liveness);
81
82 void FillWithOsrValues();
83 void PrepareForLoop(const BytecodeLoopAssignments& assignments,
84 const BytecodeLivenessState* liveness);
85 void PrepareForLoopExit(Node* loop,
86 const BytecodeLoopAssignments& assignments,
87 const BytecodeLivenessState* liveness);
88
89 private:
90 explicit Environment(const Environment* copy);
91
92 bool StateValuesRequireUpdate(Node** state_values, Node** values, int count);
93 void UpdateStateValues(Node** state_values, Node** values, int count);
94 Node* GetStateValuesFromCache(Node** values, int count,
95 const BitVector* liveness, int liveness_offset);
96
97 int RegisterToValuesIndex(interpreter::Register the_register) const;
98
zone() const99 Zone* zone() const { return builder_->local_zone(); }
graph() const100 Graph* graph() const { return builder_->graph(); }
common() const101 CommonOperatorBuilder* common() const { return builder_->common(); }
builder() const102 BytecodeGraphBuilder* builder() const { return builder_; }
values() const103 const NodeVector* values() const { return &values_; }
values()104 NodeVector* values() { return &values_; }
register_base() const105 int register_base() const { return register_base_; }
accumulator_base() const106 int accumulator_base() const { return accumulator_base_; }
107
108 BytecodeGraphBuilder* builder_;
109 int register_count_;
110 int parameter_count_;
111 Node* context_;
112 Node* control_dependency_;
113 Node* effect_dependency_;
114 NodeVector values_;
115 Node* parameters_state_values_;
116 Node* generator_state_;
117 int register_base_;
118 int accumulator_base_;
119 };
120
121 // A helper for creating a temporary sub-environment for simple branches.
122 struct BytecodeGraphBuilder::SubEnvironment final {
123 public:
SubEnvironmentv8::internal::compiler::BytecodeGraphBuilder::SubEnvironment124 explicit SubEnvironment(BytecodeGraphBuilder* builder)
125 : builder_(builder), parent_(builder->environment()->Copy()) {}
126
~SubEnvironmentv8::internal::compiler::BytecodeGraphBuilder::SubEnvironment127 ~SubEnvironment() { builder_->set_environment(parent_); }
128
129 private:
130 BytecodeGraphBuilder* builder_;
131 BytecodeGraphBuilder::Environment* parent_;
132 };
133
134 // Issues:
135 // - Scopes - intimately tied to AST. Need to eval what is needed.
136 // - 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)137 BytecodeGraphBuilder::Environment::Environment(
138 BytecodeGraphBuilder* builder, int register_count, int parameter_count,
139 interpreter::Register incoming_new_target_or_generator,
140 Node* control_dependency)
141 : builder_(builder),
142 register_count_(register_count),
143 parameter_count_(parameter_count),
144 control_dependency_(control_dependency),
145 effect_dependency_(control_dependency),
146 values_(builder->local_zone()),
147 parameters_state_values_(nullptr),
148 generator_state_(nullptr) {
149 // The layout of values_ is:
150 //
151 // [receiver] [parameters] [registers] [accumulator]
152 //
153 // parameter[0] is the receiver (this), parameters 1..N are the
154 // parameters supplied to the method (arg0..argN-1). The accumulator
155 // is stored separately.
156
157 // Parameters including the receiver
158 for (int i = 0; i < parameter_count; i++) {
159 const char* debug_name = (i == 0) ? "%this" : nullptr;
160 const Operator* op = common()->Parameter(i, debug_name);
161 Node* parameter = builder->graph()->NewNode(op, graph()->start());
162 values()->push_back(parameter);
163 }
164
165 // Registers
166 register_base_ = static_cast<int>(values()->size());
167 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
168 values()->insert(values()->end(), register_count, undefined_constant);
169
170 // Accumulator
171 accumulator_base_ = static_cast<int>(values()->size());
172 values()->push_back(undefined_constant);
173
174 // Context
175 int context_index = Linkage::GetJSCallContextParamIndex(parameter_count);
176 const Operator* op = common()->Parameter(context_index, "%context");
177 context_ = builder->graph()->NewNode(op, graph()->start());
178
179 // Incoming new.target or generator register
180 if (incoming_new_target_or_generator.is_valid()) {
181 int new_target_index =
182 Linkage::GetJSCallNewTargetParamIndex(parameter_count);
183 const Operator* op = common()->Parameter(new_target_index, "%new.target");
184 Node* new_target_node = builder->graph()->NewNode(op, graph()->start());
185
186 int values_index = RegisterToValuesIndex(incoming_new_target_or_generator);
187 values()->at(values_index) = new_target_node;
188 }
189 }
190
Environment(const BytecodeGraphBuilder::Environment * other)191 BytecodeGraphBuilder::Environment::Environment(
192 const BytecodeGraphBuilder::Environment* other)
193 : builder_(other->builder_),
194 register_count_(other->register_count_),
195 parameter_count_(other->parameter_count_),
196 context_(other->context_),
197 control_dependency_(other->control_dependency_),
198 effect_dependency_(other->effect_dependency_),
199 values_(other->zone()),
200 parameters_state_values_(other->parameters_state_values_),
201 generator_state_(other->generator_state_),
202 register_base_(other->register_base_),
203 accumulator_base_(other->accumulator_base_) {
204 values_ = other->values_;
205 }
206
207
RegisterToValuesIndex(interpreter::Register the_register) const208 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
209 interpreter::Register the_register) const {
210 if (the_register.is_parameter()) {
211 return the_register.ToParameterIndex(parameter_count());
212 } else {
213 return the_register.index() + register_base();
214 }
215 }
216
LookupAccumulator() const217 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
218 return values()->at(accumulator_base_);
219 }
220
LookupGeneratorState() const221 Node* BytecodeGraphBuilder::Environment::LookupGeneratorState() const {
222 DCHECK_NOT_NULL(generator_state_);
223 return generator_state_;
224 }
225
LookupRegister(interpreter::Register the_register) const226 Node* BytecodeGraphBuilder::Environment::LookupRegister(
227 interpreter::Register the_register) const {
228 if (the_register.is_current_context()) {
229 return Context();
230 } else if (the_register.is_function_closure()) {
231 return builder()->GetFunctionClosure();
232 } else {
233 int values_index = RegisterToValuesIndex(the_register);
234 return values()->at(values_index);
235 }
236 }
237
BindAccumulator(Node * node,FrameStateAttachmentMode mode)238 void BytecodeGraphBuilder::Environment::BindAccumulator(
239 Node* node, FrameStateAttachmentMode mode) {
240 if (mode == FrameStateAttachmentMode::kAttachFrameState) {
241 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0));
242 }
243 values()->at(accumulator_base_) = node;
244 }
245
BindGeneratorState(Node * node)246 void BytecodeGraphBuilder::Environment::BindGeneratorState(Node* node) {
247 generator_state_ = node;
248 }
249
BindRegister(interpreter::Register the_register,Node * node,FrameStateAttachmentMode mode)250 void BytecodeGraphBuilder::Environment::BindRegister(
251 interpreter::Register the_register, Node* node,
252 FrameStateAttachmentMode mode) {
253 int values_index = RegisterToValuesIndex(the_register);
254 if (mode == FrameStateAttachmentMode::kAttachFrameState) {
255 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
256 accumulator_base_ - values_index));
257 }
258 values()->at(values_index) = node;
259 }
260
BindRegistersToProjections(interpreter::Register first_reg,Node * node,FrameStateAttachmentMode mode)261 void BytecodeGraphBuilder::Environment::BindRegistersToProjections(
262 interpreter::Register first_reg, Node* node,
263 FrameStateAttachmentMode mode) {
264 int values_index = RegisterToValuesIndex(first_reg);
265 if (mode == FrameStateAttachmentMode::kAttachFrameState) {
266 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
267 accumulator_base_ - values_index));
268 }
269 for (int i = 0; i < node->op()->ValueOutputCount(); i++) {
270 values()->at(values_index + i) =
271 builder()->NewNode(common()->Projection(i), node);
272 }
273 }
274
RecordAfterState(Node * node,FrameStateAttachmentMode mode)275 void BytecodeGraphBuilder::Environment::RecordAfterState(
276 Node* node, FrameStateAttachmentMode mode) {
277 if (mode == FrameStateAttachmentMode::kAttachFrameState) {
278 builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore());
279 }
280 }
281
Copy()282 BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::Environment::Copy() {
283 return new (zone()) Environment(this);
284 }
285
Merge(BytecodeGraphBuilder::Environment * other,const BytecodeLivenessState * liveness)286 void BytecodeGraphBuilder::Environment::Merge(
287 BytecodeGraphBuilder::Environment* other,
288 const BytecodeLivenessState* liveness) {
289 // Create a merge of the control dependencies of both environments and update
290 // the current environment's control dependency accordingly.
291 Node* control = builder()->MergeControl(GetControlDependency(),
292 other->GetControlDependency());
293 UpdateControlDependency(control);
294
295 // Create a merge of the effect dependencies of both environments and update
296 // the current environment's effect dependency accordingly.
297 Node* effect = builder()->MergeEffect(GetEffectDependency(),
298 other->GetEffectDependency(), control);
299 UpdateEffectDependency(effect);
300
301 // Introduce Phi nodes for values that are live and have differing inputs at
302 // the merge point, potentially extending an existing Phi node if possible.
303 context_ = builder()->MergeValue(context_, other->context_, control);
304 for (int i = 0; i < parameter_count(); i++) {
305 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control);
306 }
307 for (int i = 0; i < register_count(); i++) {
308 int index = register_base() + i;
309 if (liveness == nullptr || liveness->RegisterIsLive(i)) {
310 #if DEBUG
311 // We only do these DCHECKs when we are not in the resume path of a
312 // generator -- this is, when either there is no generator state at all,
313 // or the generator state is not the constant "executing" value.
314 if (generator_state_ == nullptr ||
315 NumberMatcher(generator_state_)
316 .Is(JSGeneratorObject::kGeneratorExecuting)) {
317 DCHECK_NE(values_[index], builder()->jsgraph()->OptimizedOutConstant());
318 DCHECK_NE(other->values_[index],
319 builder()->jsgraph()->OptimizedOutConstant());
320 }
321 #endif
322
323 values_[index] =
324 builder()->MergeValue(values_[index], other->values_[index], control);
325
326 } else {
327 values_[index] = builder()->jsgraph()->OptimizedOutConstant();
328 }
329 }
330
331 if (liveness == nullptr || liveness->AccumulatorIsLive()) {
332 DCHECK_NE(values_[accumulator_base()],
333 builder()->jsgraph()->OptimizedOutConstant());
334 DCHECK_NE(other->values_[accumulator_base()],
335 builder()->jsgraph()->OptimizedOutConstant());
336
337 values_[accumulator_base()] =
338 builder()->MergeValue(values_[accumulator_base()],
339 other->values_[accumulator_base()], control);
340 } else {
341 values_[accumulator_base()] = builder()->jsgraph()->OptimizedOutConstant();
342 }
343
344 if (generator_state_ != nullptr) {
345 DCHECK_NOT_NULL(other->generator_state_);
346 generator_state_ = builder()->MergeValue(generator_state_,
347 other->generator_state_, control);
348 }
349 }
350
PrepareForLoop(const BytecodeLoopAssignments & assignments,const BytecodeLivenessState * liveness)351 void BytecodeGraphBuilder::Environment::PrepareForLoop(
352 const BytecodeLoopAssignments& assignments,
353 const BytecodeLivenessState* liveness) {
354 // Create a control node for the loop header.
355 Node* control = builder()->NewLoop();
356
357 // Create a Phi for external effects.
358 Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control);
359 UpdateEffectDependency(effect);
360
361 // Create Phis for any values that are live on entry to the loop and may be
362 // updated by the end of the loop.
363 context_ = builder()->NewPhi(1, context_, control);
364 for (int i = 0; i < parameter_count(); i++) {
365 if (assignments.ContainsParameter(i)) {
366 values_[i] = builder()->NewPhi(1, values_[i], control);
367 }
368 }
369 for (int i = 0; i < register_count(); i++) {
370 if (assignments.ContainsLocal(i) &&
371 (liveness == nullptr || liveness->RegisterIsLive(i))) {
372 int index = register_base() + i;
373 values_[index] = builder()->NewPhi(1, values_[index], control);
374 }
375 }
376 // The accumulator should not be live on entry.
377 DCHECK_IMPLIES(liveness != nullptr, !liveness->AccumulatorIsLive());
378
379 if (generator_state_ != nullptr) {
380 generator_state_ = builder()->NewPhi(1, generator_state_, control);
381 }
382
383 // Connect to the loop end.
384 Node* terminate = builder()->graph()->NewNode(
385 builder()->common()->Terminate(), effect, control);
386 builder()->exit_controls_.push_back(terminate);
387 }
388
FillWithOsrValues()389 void BytecodeGraphBuilder::Environment::FillWithOsrValues() {
390 Node* start = graph()->start();
391
392 // Create OSR values for each environment value.
393 SetContext(graph()->NewNode(
394 common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), start));
395 int size = static_cast<int>(values()->size());
396 for (int i = 0; i < size; i++) {
397 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly.
398 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount;
399 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex;
400 values()->at(i) = graph()->NewNode(common()->OsrValue(idx), start);
401 }
402 }
403
StateValuesRequireUpdate(Node ** state_values,Node ** values,int count)404 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
405 Node** state_values, Node** values, int count) {
406 if (*state_values == nullptr) {
407 return true;
408 }
409 Node::Inputs inputs = (*state_values)->inputs();
410 if (inputs.count() != count) return true;
411 for (int i = 0; i < count; i++) {
412 if (inputs[i] != values[i]) {
413 return true;
414 }
415 }
416 return false;
417 }
418
PrepareForLoopExit(Node * loop,const BytecodeLoopAssignments & assignments,const BytecodeLivenessState * liveness)419 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(
420 Node* loop, const BytecodeLoopAssignments& assignments,
421 const BytecodeLivenessState* liveness) {
422 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);
423
424 Node* control = GetControlDependency();
425
426 // Create the loop exit node.
427 Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop);
428 UpdateControlDependency(loop_exit);
429
430 // Rename the effect.
431 Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
432 GetEffectDependency(), loop_exit);
433 UpdateEffectDependency(effect_rename);
434
435 // TODO(jarin) We should also rename context here. However, unconditional
436 // renaming confuses global object and native context specialization.
437 // We should only rename if the context is assigned in the loop.
438
439 // Rename the environment values if they were assigned in the loop and are
440 // live after exiting the loop.
441 for (int i = 0; i < parameter_count(); i++) {
442 if (assignments.ContainsParameter(i)) {
443 Node* rename =
444 graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit);
445 values_[i] = rename;
446 }
447 }
448 for (int i = 0; i < register_count(); i++) {
449 if (assignments.ContainsLocal(i) &&
450 (liveness == nullptr || liveness->RegisterIsLive(i))) {
451 Node* rename = graph()->NewNode(common()->LoopExitValue(),
452 values_[register_base() + i], loop_exit);
453 values_[register_base() + i] = rename;
454 }
455 }
456 if (liveness == nullptr || liveness->AccumulatorIsLive()) {
457 Node* rename = graph()->NewNode(common()->LoopExitValue(),
458 values_[accumulator_base()], loop_exit);
459 values_[accumulator_base()] = rename;
460 }
461
462 if (generator_state_ != nullptr) {
463 generator_state_ = graph()->NewNode(common()->LoopExitValue(),
464 generator_state_, loop_exit);
465 }
466 }
467
UpdateStateValues(Node ** state_values,Node ** values,int count)468 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
469 Node** values,
470 int count) {
471 if (StateValuesRequireUpdate(state_values, values, count)) {
472 const Operator* op = common()->StateValues(count, SparseInputMask::Dense());
473 (*state_values) = graph()->NewNode(op, count, values);
474 }
475 }
476
GetStateValuesFromCache(Node ** values,int count,const BitVector * liveness,int liveness_offset)477 Node* BytecodeGraphBuilder::Environment::GetStateValuesFromCache(
478 Node** values, int count, const BitVector* liveness, int liveness_offset) {
479 return builder_->state_values_cache_.GetNodeForValues(
480 values, static_cast<size_t>(count), liveness, liveness_offset);
481 }
482
Checkpoint(BailoutId bailout_id,OutputFrameStateCombine combine,const BytecodeLivenessState * liveness)483 Node* BytecodeGraphBuilder::Environment::Checkpoint(
484 BailoutId bailout_id, OutputFrameStateCombine combine,
485 const BytecodeLivenessState* liveness) {
486 if (parameter_count() == register_count()) {
487 // Re-use the state-value cache if the number of local registers happens
488 // to match the parameter count.
489 parameters_state_values_ = GetStateValuesFromCache(
490 &values()->at(0), parameter_count(), nullptr, 0);
491 } else {
492 UpdateStateValues(¶meters_state_values_, &values()->at(0),
493 parameter_count());
494 }
495
496 Node* registers_state_values =
497 GetStateValuesFromCache(&values()->at(register_base()), register_count(),
498 liveness ? &liveness->bit_vector() : nullptr, 0);
499
500 bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive();
501 Node* accumulator_state_value =
502 accumulator_is_live && combine != OutputFrameStateCombine::PokeAt(0)
503 ? values()->at(accumulator_base())
504 : builder()->jsgraph()->OptimizedOutConstant();
505
506 const Operator* op = common()->FrameState(
507 bailout_id, combine, builder()->frame_state_function_info());
508 Node* result = graph()->NewNode(
509 op, parameters_state_values_, registers_state_values,
510 accumulator_state_value, Context(), builder()->GetFunctionClosure(),
511 builder()->graph()->start());
512
513 return result;
514 }
515
BytecodeGraphBuilder(Zone * local_zone,Handle<SharedFunctionInfo> shared_info,Handle<FeedbackVector> feedback_vector,BailoutId osr_offset,JSGraph * jsgraph,CallFrequency & invocation_frequency,SourcePositionTable * source_positions,Handle<Context> native_context,int inlining_id,JSTypeHintLowering::Flags flags,bool stack_check,bool analyze_environment_liveness)516 BytecodeGraphBuilder::BytecodeGraphBuilder(
517 Zone* local_zone, Handle<SharedFunctionInfo> shared_info,
518 Handle<FeedbackVector> feedback_vector, BailoutId osr_offset,
519 JSGraph* jsgraph, CallFrequency& invocation_frequency,
520 SourcePositionTable* source_positions, Handle<Context> native_context,
521 int inlining_id, JSTypeHintLowering::Flags flags, bool stack_check,
522 bool analyze_environment_liveness)
523 : local_zone_(local_zone),
524 jsgraph_(jsgraph),
525 invocation_frequency_(invocation_frequency),
526 bytecode_array_(
527 handle(shared_info->GetBytecodeArray(), jsgraph->isolate())),
528 feedback_vector_(feedback_vector),
529 type_hint_lowering_(jsgraph, feedback_vector, flags),
530 frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
531 FrameStateType::kInterpretedFunction,
532 bytecode_array()->parameter_count(),
533 bytecode_array()->register_count(), shared_info)),
534 bytecode_iterator_(nullptr),
535 bytecode_analysis_(nullptr),
536 environment_(nullptr),
537 osr_offset_(osr_offset),
538 currently_peeled_loop_offset_(-1),
539 stack_check_(stack_check),
540 analyze_environment_liveness_(analyze_environment_liveness),
541 merge_environments_(local_zone),
542 generator_merge_environments_(local_zone),
543 exception_handlers_(local_zone),
544 current_exception_handler_(0),
545 input_buffer_size_(0),
546 input_buffer_(nullptr),
547 needs_eager_checkpoint_(true),
548 exit_controls_(local_zone),
549 state_values_cache_(jsgraph),
550 source_positions_(source_positions),
551 start_position_(shared_info->StartPosition(), inlining_id),
552 native_context_(native_context) {}
553
GetFunctionClosure()554 Node* BytecodeGraphBuilder::GetFunctionClosure() {
555 if (!function_closure_.is_set()) {
556 int index = Linkage::kJSCallClosureParamIndex;
557 const Operator* op = common()->Parameter(index, "%closure");
558 Node* node = NewNode(op, graph()->start());
559 function_closure_.set(node);
560 }
561 return function_closure_.get();
562 }
563
BuildLoadNativeContextField(int index)564 Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
565 const Operator* op =
566 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
567 Node* native_context = NewNode(op);
568 Node* result = NewNode(javascript()->LoadContext(0, index, true));
569 NodeProperties::ReplaceContextInput(result, native_context);
570 return result;
571 }
572
CreateVectorSlotPair(int slot_id)573 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
574 return VectorSlotPair(feedback_vector(), FeedbackVector::ToSlot(slot_id));
575 }
576
CreateGraph()577 void BytecodeGraphBuilder::CreateGraph() {
578 SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
579
580 // Set up the basic structure of the graph. Outputs for {Start} are the formal
581 // parameters (including the receiver) plus new target, number of arguments,
582 // context and closure.
583 int actual_parameter_count = bytecode_array()->parameter_count() + 4;
584 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
585
586 Environment env(this, bytecode_array()->register_count(),
587 bytecode_array()->parameter_count(),
588 bytecode_array()->incoming_new_target_or_generator_register(),
589 graph()->start());
590 set_environment(&env);
591
592 VisitBytecodes();
593
594 // Finish the basic structure of the graph.
595 DCHECK_NE(0u, exit_controls_.size());
596 int const input_count = static_cast<int>(exit_controls_.size());
597 Node** const inputs = &exit_controls_.front();
598 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
599 graph()->SetEnd(end);
600 }
601
PrepareEagerCheckpoint()602 void BytecodeGraphBuilder::PrepareEagerCheckpoint() {
603 if (needs_eager_checkpoint()) {
604 // Create an explicit checkpoint node for before the operation. This only
605 // needs to happen if we aren't effect-dominated by a {Checkpoint} already.
606 mark_as_needing_eager_checkpoint(false);
607 Node* node = NewNode(common()->Checkpoint());
608 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
609 DCHECK_EQ(IrOpcode::kDead,
610 NodeProperties::GetFrameStateInput(node)->opcode());
611 BailoutId bailout_id(bytecode_iterator().current_offset());
612
613 const BytecodeLivenessState* liveness_before =
614 bytecode_analysis()->GetInLivenessFor(
615 bytecode_iterator().current_offset());
616
617 Node* frame_state_before = environment()->Checkpoint(
618 bailout_id, OutputFrameStateCombine::Ignore(), liveness_before);
619 NodeProperties::ReplaceFrameStateInput(node, frame_state_before);
620 #ifdef DEBUG
621 } else {
622 // In case we skipped checkpoint creation above, we must be able to find an
623 // existing checkpoint that effect-dominates the nodes about to be created.
624 // Starting a search from the current effect-dependency has to succeed.
625 Node* effect = environment()->GetEffectDependency();
626 while (effect->opcode() != IrOpcode::kCheckpoint) {
627 DCHECK(effect->op()->HasProperty(Operator::kNoWrite));
628 DCHECK_EQ(1, effect->op()->EffectInputCount());
629 effect = NodeProperties::GetEffectInput(effect);
630 }
631 }
632 #else
633 }
634 #endif // DEBUG
635 }
636
PrepareFrameState(Node * node,OutputFrameStateCombine combine)637 void BytecodeGraphBuilder::PrepareFrameState(Node* node,
638 OutputFrameStateCombine combine) {
639 if (OperatorProperties::HasFrameStateInput(node->op())) {
640 // Add the frame state for after the operation. The node in question has
641 // already been created and had a {Dead} frame state input up until now.
642 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
643 DCHECK_EQ(IrOpcode::kDead,
644 NodeProperties::GetFrameStateInput(node)->opcode());
645 BailoutId bailout_id(bytecode_iterator().current_offset());
646
647 const BytecodeLivenessState* liveness_after =
648 bytecode_analysis()->GetOutLivenessFor(
649 bytecode_iterator().current_offset());
650
651 Node* frame_state_after =
652 environment()->Checkpoint(bailout_id, combine, liveness_after);
653 NodeProperties::ReplaceFrameStateInput(node, frame_state_after);
654 }
655 }
656
657 // Stores the state of the SourcePosition iterator, and the index to the
658 // current exception handlers stack. We need, during the OSR graph generation,
659 // to backup the states of these iterators at the LoopHeader offset of each
660 // outer loop which contains the OSR loop. The iterators are then restored when
661 // peeling the loops, so that both exception handling and synchronisation with
662 // the source position can be achieved.
663 class BytecodeGraphBuilder::OsrIteratorState {
664 public:
OsrIteratorState(interpreter::BytecodeArrayIterator * iterator,SourcePositionTableIterator * source_position_iterator,BytecodeGraphBuilder * graph_builder)665 OsrIteratorState(interpreter::BytecodeArrayIterator* iterator,
666 SourcePositionTableIterator* source_position_iterator,
667 BytecodeGraphBuilder* graph_builder)
668 : iterator_(iterator),
669 source_position_iterator_(source_position_iterator),
670 graph_builder_(graph_builder),
671 saved_states_(graph_builder->local_zone()) {}
672
ProcessOsrPrelude()673 void ProcessOsrPrelude() {
674 ZoneVector<int> outer_loop_offsets(graph_builder_->local_zone());
675
676 const BytecodeAnalysis& bytecode_analysis =
677 *(graph_builder_->bytecode_analysis());
678 int osr_offset = bytecode_analysis.osr_entry_point();
679
680 // We find here the outermost loop which contains the OSR loop.
681 int outermost_loop_offset = osr_offset;
682 while ((outermost_loop_offset =
683 bytecode_analysis.GetLoopInfoFor(outermost_loop_offset)
684 .parent_offset()) != -1) {
685 outer_loop_offsets.push_back(outermost_loop_offset);
686 }
687 outermost_loop_offset =
688 outer_loop_offsets.empty() ? osr_offset : outer_loop_offsets.back();
689
690 // We will not processs any bytecode before the outermost_loop_offset, but
691 // the source_position_iterator needs to be advanced step by step through
692 // the bytecode.
693 for (; iterator_->current_offset() != outermost_loop_offset;
694 iterator_->Advance()) {
695 graph_builder_->UpdateSourcePosition(source_position_iterator_,
696 iterator_->current_offset());
697 }
698
699 // We save some iterators states at the offsets of the loop headers of the
700 // outer loops (the ones containing the OSR loop). They will be used for
701 // jumping back in the bytecode.
702 for (ZoneVector<int>::const_reverse_iterator it =
703 outer_loop_offsets.crbegin();
704 it != outer_loop_offsets.crend(); ++it) {
705 int next_loop_offset = *it;
706 for (; iterator_->current_offset() != next_loop_offset;
707 iterator_->Advance()) {
708 graph_builder_->UpdateSourcePosition(source_position_iterator_,
709 iterator_->current_offset());
710 }
711 graph_builder_->ExitThenEnterExceptionHandlers(
712 iterator_->current_offset());
713 saved_states_.push(
714 IteratorsStates(graph_builder_->current_exception_handler(),
715 source_position_iterator_->GetState()));
716 }
717
718 // Finishing by advancing to the OSR entry
719 for (; iterator_->current_offset() != osr_offset; iterator_->Advance()) {
720 graph_builder_->UpdateSourcePosition(source_position_iterator_,
721 iterator_->current_offset());
722 }
723
724 // Enters all remaining exception handler which end before the OSR loop
725 // so that on next call of VisitSingleBytecode they will get popped from
726 // the exception handlers stack.
727 graph_builder_->ExitThenEnterExceptionHandlers(osr_offset);
728 graph_builder_->set_currently_peeled_loop_offset(
729 bytecode_analysis.GetLoopInfoFor(osr_offset).parent_offset());
730 }
731
RestoreState(int target_offset,int new_parent_offset)732 void RestoreState(int target_offset, int new_parent_offset) {
733 iterator_->SetOffset(target_offset);
734 // In case of a return, we must not build loop exits for
735 // not-yet-built outer loops.
736 graph_builder_->set_currently_peeled_loop_offset(new_parent_offset);
737 IteratorsStates saved_state = saved_states_.top();
738 source_position_iterator_->RestoreState(saved_state.source_iterator_state_);
739 graph_builder_->set_current_exception_handler(
740 saved_state.exception_handler_index_);
741 saved_states_.pop();
742 }
743
744 private:
745 struct IteratorsStates {
746 int exception_handler_index_;
747 SourcePositionTableIterator::IndexAndPosition source_iterator_state_;
748
IteratorsStatesv8::internal::compiler::BytecodeGraphBuilder::OsrIteratorState::IteratorsStates749 IteratorsStates(
750 int exception_handler_index,
751 SourcePositionTableIterator::IndexAndPosition source_iterator_state)
752 : exception_handler_index_(exception_handler_index),
753 source_iterator_state_(source_iterator_state) {}
754 };
755
756 interpreter::BytecodeArrayIterator* iterator_;
757 SourcePositionTableIterator* source_position_iterator_;
758 BytecodeGraphBuilder* graph_builder_;
759 ZoneStack<IteratorsStates> saved_states_;
760 };
761
RemoveMergeEnvironmentsBeforeOffset(int limit_offset)762 void BytecodeGraphBuilder::RemoveMergeEnvironmentsBeforeOffset(
763 int limit_offset) {
764 if (!merge_environments_.empty()) {
765 ZoneMap<int, Environment*>::iterator it = merge_environments_.begin();
766 ZoneMap<int, Environment*>::iterator stop_it = merge_environments_.end();
767 while (it != stop_it && it->first <= limit_offset) {
768 it = merge_environments_.erase(it);
769 }
770 }
771 }
772
773 // We will iterate through the OSR loop, then its parent, and so on
774 // until we have reached the outmost loop containing the OSR loop. We do
775 // not generate nodes for anything before the outermost loop.
AdvanceToOsrEntryAndPeelLoops(interpreter::BytecodeArrayIterator * iterator,SourcePositionTableIterator * source_position_iterator)776 void BytecodeGraphBuilder::AdvanceToOsrEntryAndPeelLoops(
777 interpreter::BytecodeArrayIterator* iterator,
778 SourcePositionTableIterator* source_position_iterator) {
779 const BytecodeAnalysis& analysis = *(bytecode_analysis());
780 int osr_offset = analysis.osr_entry_point();
781 OsrIteratorState iterator_states(iterator, source_position_iterator, this);
782
783 iterator_states.ProcessOsrPrelude();
784 DCHECK_EQ(iterator->current_offset(), osr_offset);
785
786 environment()->FillWithOsrValues();
787
788 // Suppose we have n nested loops, loop_0 being the outermost one, and
789 // loop_n being the OSR loop. We start iterating the bytecode at the header
790 // of loop_n (the OSR loop), and then we peel the part of the the body of
791 // loop_{n-1} following the end of loop_n. We then rewind the iterator to
792 // the header of loop_{n-1}, and so on until we have partly peeled loop 0.
793 // The full loop_0 body will be generating with the rest of the function,
794 // outside the OSR generation.
795
796 // To do so, if we are visiting a loop, we continue to visit what's left
797 // of its parent, and then when reaching the parent's JumpLoop, we do not
798 // create any jump for that but rewind the bytecode iterator to visit the
799 // parent loop entirely, and so on.
800
801 int current_parent_offset =
802 analysis.GetLoopInfoFor(osr_offset).parent_offset();
803 while (current_parent_offset != -1) {
804 LoopInfo current_parent_loop =
805 analysis.GetLoopInfoFor(current_parent_offset);
806 // We iterate until the back edge of the parent loop, which we detect by
807 // the offset that the JumpLoop targets.
808 for (; !iterator->done(); iterator->Advance()) {
809 if (iterator->current_bytecode() == interpreter::Bytecode::kJumpLoop &&
810 iterator->GetJumpTargetOffset() == current_parent_offset) {
811 // Reached the end of the current parent loop.
812 break;
813 }
814 VisitSingleBytecode(source_position_iterator);
815 }
816 DCHECK(!iterator->done()); // Should have found the loop's jump target.
817
818 // We also need to take care of the merge environments and exceptions
819 // handlers here because the omitted JumpLoop bytecode can still be the
820 // target of jumps or the first bytecode after a try block.
821 ExitThenEnterExceptionHandlers(iterator->current_offset());
822 SwitchToMergeEnvironment(iterator->current_offset());
823
824 // This jump is the jump of our parent loop, which is not yet created.
825 // So we do not build the jump nodes, but restore the bytecode and the
826 // SourcePosition iterators to the values they had when we were visiting
827 // the offset pointed at by the JumpLoop we've just reached.
828 // We have already built nodes for inner loops, but now we will
829 // iterate again over them and build new nodes corresponding to the same
830 // bytecode offsets. Any jump or reference to this inner loops must now
831 // point to the new nodes we will build, hence we clear the relevant part
832 // of the environment.
833 // Completely clearing the environment is not possible because merge
834 // environments for forward jumps out of the loop need to be preserved
835 // (e.g. a return or a labeled break in the middle of a loop).
836 RemoveMergeEnvironmentsBeforeOffset(iterator->current_offset());
837 iterator_states.RestoreState(current_parent_offset,
838 current_parent_loop.parent_offset());
839 current_parent_offset = current_parent_loop.parent_offset();
840 }
841 }
842
VisitSingleBytecode(SourcePositionTableIterator * source_position_iterator)843 void BytecodeGraphBuilder::VisitSingleBytecode(
844 SourcePositionTableIterator* source_position_iterator) {
845 const interpreter::BytecodeArrayIterator& iterator = bytecode_iterator();
846 int current_offset = iterator.current_offset();
847 UpdateSourcePosition(source_position_iterator, current_offset);
848 ExitThenEnterExceptionHandlers(current_offset);
849 DCHECK_GE(exception_handlers_.empty() ? current_offset
850 : exception_handlers_.top().end_offset_,
851 current_offset);
852 SwitchToMergeEnvironment(current_offset);
853
854 if (environment() != nullptr) {
855 BuildLoopHeaderEnvironment(current_offset);
856
857 // Skip the first stack check if stack_check is false
858 if (!stack_check() &&
859 iterator.current_bytecode() == interpreter::Bytecode::kStackCheck) {
860 set_stack_check(true);
861 return;
862 }
863
864 switch (iterator.current_bytecode()) {
865 #define BYTECODE_CASE(name, ...) \
866 case interpreter::Bytecode::k##name: \
867 Visit##name(); \
868 break;
869 BYTECODE_LIST(BYTECODE_CASE)
870 #undef BYTECODE_CODE
871 }
872 }
873 }
874
VisitBytecodes()875 void BytecodeGraphBuilder::VisitBytecodes() {
876 BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone(),
877 analyze_environment_liveness());
878 bytecode_analysis.Analyze(osr_offset_);
879 set_bytecode_analysis(&bytecode_analysis);
880
881 interpreter::BytecodeArrayIterator iterator(bytecode_array());
882 set_bytecode_iterator(&iterator);
883 SourcePositionTableIterator source_position_iterator(
884 handle(bytecode_array()->SourcePositionTable(), isolate()));
885
886 if (analyze_environment_liveness() && FLAG_trace_environment_liveness) {
887 StdoutStream of;
888 bytecode_analysis.PrintLivenessTo(of);
889 }
890
891 if (!bytecode_analysis.resume_jump_targets().empty()) {
892 environment()->BindGeneratorState(
893 jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting));
894 }
895
896 if (bytecode_analysis.HasOsrEntryPoint()) {
897 // We peel the OSR loop and any outer loop containing it except that we
898 // leave the nodes corresponding to the whole outermost loop (including
899 // the last copies of the loops it contains) to be generated by the normal
900 // bytecode iteration below.
901 AdvanceToOsrEntryAndPeelLoops(&iterator, &source_position_iterator);
902 }
903
904 for (; !iterator.done(); iterator.Advance()) {
905 VisitSingleBytecode(&source_position_iterator);
906 }
907 set_bytecode_analysis(nullptr);
908 set_bytecode_iterator(nullptr);
909 DCHECK(exception_handlers_.empty());
910 }
911
VisitLdaZero()912 void BytecodeGraphBuilder::VisitLdaZero() {
913 Node* node = jsgraph()->ZeroConstant();
914 environment()->BindAccumulator(node);
915 }
916
VisitLdaSmi()917 void BytecodeGraphBuilder::VisitLdaSmi() {
918 Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
919 environment()->BindAccumulator(node);
920 }
921
VisitLdaConstant()922 void BytecodeGraphBuilder::VisitLdaConstant() {
923 Node* node = jsgraph()->Constant(
924 handle(bytecode_iterator().GetConstantForIndexOperand(0), isolate()));
925 environment()->BindAccumulator(node);
926 }
927
VisitLdaUndefined()928 void BytecodeGraphBuilder::VisitLdaUndefined() {
929 Node* node = jsgraph()->UndefinedConstant();
930 environment()->BindAccumulator(node);
931 }
932
VisitLdaNull()933 void BytecodeGraphBuilder::VisitLdaNull() {
934 Node* node = jsgraph()->NullConstant();
935 environment()->BindAccumulator(node);
936 }
937
VisitLdaTheHole()938 void BytecodeGraphBuilder::VisitLdaTheHole() {
939 Node* node = jsgraph()->TheHoleConstant();
940 environment()->BindAccumulator(node);
941 }
942
VisitLdaTrue()943 void BytecodeGraphBuilder::VisitLdaTrue() {
944 Node* node = jsgraph()->TrueConstant();
945 environment()->BindAccumulator(node);
946 }
947
VisitLdaFalse()948 void BytecodeGraphBuilder::VisitLdaFalse() {
949 Node* node = jsgraph()->FalseConstant();
950 environment()->BindAccumulator(node);
951 }
952
VisitLdar()953 void BytecodeGraphBuilder::VisitLdar() {
954 Node* value =
955 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
956 environment()->BindAccumulator(value);
957 }
958
VisitStar()959 void BytecodeGraphBuilder::VisitStar() {
960 Node* value = environment()->LookupAccumulator();
961 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value);
962 }
963
VisitMov()964 void BytecodeGraphBuilder::VisitMov() {
965 Node* value =
966 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
967 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value);
968 }
969
BuildLoadGlobal(Handle<Name> name,uint32_t feedback_slot_index,TypeofMode typeof_mode)970 Node* BytecodeGraphBuilder::BuildLoadGlobal(Handle<Name> name,
971 uint32_t feedback_slot_index,
972 TypeofMode typeof_mode) {
973 VectorSlotPair feedback = CreateVectorSlotPair(feedback_slot_index);
974 DCHECK(IsLoadGlobalICKind(feedback_vector()->GetKind(feedback.slot())));
975 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
976 return NewNode(op);
977 }
978
VisitLdaGlobal()979 void BytecodeGraphBuilder::VisitLdaGlobal() {
980 PrepareEagerCheckpoint();
981 Handle<Name> name(
982 Name::cast(bytecode_iterator().GetConstantForIndexOperand(0)), isolate());
983 uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
984 Node* node =
985 BuildLoadGlobal(name, feedback_slot_index, TypeofMode::NOT_INSIDE_TYPEOF);
986 environment()->BindAccumulator(node, Environment::kAttachFrameState);
987 }
988
VisitLdaGlobalInsideTypeof()989 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() {
990 PrepareEagerCheckpoint();
991 Handle<Name> name(
992 Name::cast(bytecode_iterator().GetConstantForIndexOperand(0)), isolate());
993 uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
994 Node* node =
995 BuildLoadGlobal(name, feedback_slot_index, TypeofMode::INSIDE_TYPEOF);
996 environment()->BindAccumulator(node, Environment::kAttachFrameState);
997 }
998
VisitStaGlobal()999 void BytecodeGraphBuilder::VisitStaGlobal() {
1000 PrepareEagerCheckpoint();
1001 Handle<Name> name(
1002 Name::cast(bytecode_iterator().GetConstantForIndexOperand(0)), isolate());
1003 VectorSlotPair feedback =
1004 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
1005 Node* value = environment()->LookupAccumulator();
1006
1007 LanguageMode language_mode =
1008 feedback.vector()->GetLanguageMode(feedback.slot());
1009 const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback);
1010 Node* node = NewNode(op, value);
1011 environment()->RecordAfterState(node, Environment::kAttachFrameState);
1012 }
1013
VisitStaInArrayLiteral()1014 void BytecodeGraphBuilder::VisitStaInArrayLiteral() {
1015 PrepareEagerCheckpoint();
1016 Node* value = environment()->LookupAccumulator();
1017 Node* array =
1018 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1019 Node* index =
1020 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1021 VectorSlotPair feedback =
1022 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1023 const Operator* op = javascript()->StoreInArrayLiteral(feedback);
1024
1025 JSTypeHintLowering::LoweringResult lowering =
1026 TryBuildSimplifiedStoreKeyed(op, array, index, value, feedback.slot());
1027 if (lowering.IsExit()) return;
1028
1029 Node* node = nullptr;
1030 if (lowering.IsSideEffectFree()) {
1031 node = lowering.value();
1032 } else {
1033 DCHECK(!lowering.Changed());
1034 node = NewNode(op, array, index, value);
1035 }
1036
1037 environment()->RecordAfterState(node, Environment::kAttachFrameState);
1038 }
1039
VisitStaDataPropertyInLiteral()1040 void BytecodeGraphBuilder::VisitStaDataPropertyInLiteral() {
1041 PrepareEagerCheckpoint();
1042
1043 Node* object =
1044 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1045 Node* name =
1046 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1047 Node* value = environment()->LookupAccumulator();
1048 int flags = bytecode_iterator().GetFlagOperand(2);
1049 VectorSlotPair feedback =
1050 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(3));
1051
1052 const Operator* op = javascript()->StoreDataPropertyInLiteral(feedback);
1053 Node* node = NewNode(op, object, name, value, jsgraph()->Constant(flags));
1054 environment()->RecordAfterState(node, Environment::kAttachFrameState);
1055 }
1056
VisitCollectTypeProfile()1057 void BytecodeGraphBuilder::VisitCollectTypeProfile() {
1058 PrepareEagerCheckpoint();
1059
1060 Node* position =
1061 jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
1062 Node* value = environment()->LookupAccumulator();
1063 Node* vector = jsgraph()->Constant(feedback_vector());
1064
1065 const Operator* op = javascript()->CallRuntime(Runtime::kCollectTypeProfile);
1066
1067 Node* node = NewNode(op, position, value, vector);
1068 environment()->RecordAfterState(node, Environment::kAttachFrameState);
1069 }
1070
VisitLdaContextSlot()1071 void BytecodeGraphBuilder::VisitLdaContextSlot() {
1072 const Operator* op = javascript()->LoadContext(
1073 bytecode_iterator().GetUnsignedImmediateOperand(2),
1074 bytecode_iterator().GetIndexOperand(1), false);
1075 Node* node = NewNode(op);
1076 Node* context =
1077 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1078 NodeProperties::ReplaceContextInput(node, context);
1079 environment()->BindAccumulator(node);
1080 }
1081
VisitLdaImmutableContextSlot()1082 void BytecodeGraphBuilder::VisitLdaImmutableContextSlot() {
1083 const Operator* op = javascript()->LoadContext(
1084 bytecode_iterator().GetUnsignedImmediateOperand(2),
1085 bytecode_iterator().GetIndexOperand(1), true);
1086 Node* node = NewNode(op);
1087 Node* context =
1088 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1089 NodeProperties::ReplaceContextInput(node, context);
1090 environment()->BindAccumulator(node);
1091 }
1092
VisitLdaCurrentContextSlot()1093 void BytecodeGraphBuilder::VisitLdaCurrentContextSlot() {
1094 const Operator* op = javascript()->LoadContext(
1095 0, bytecode_iterator().GetIndexOperand(0), false);
1096 Node* node = NewNode(op);
1097 environment()->BindAccumulator(node);
1098 }
1099
VisitLdaImmutableCurrentContextSlot()1100 void BytecodeGraphBuilder::VisitLdaImmutableCurrentContextSlot() {
1101 const Operator* op = javascript()->LoadContext(
1102 0, bytecode_iterator().GetIndexOperand(0), true);
1103 Node* node = NewNode(op);
1104 environment()->BindAccumulator(node);
1105 }
1106
VisitStaContextSlot()1107 void BytecodeGraphBuilder::VisitStaContextSlot() {
1108 const Operator* op = javascript()->StoreContext(
1109 bytecode_iterator().GetUnsignedImmediateOperand(2),
1110 bytecode_iterator().GetIndexOperand(1));
1111 Node* value = environment()->LookupAccumulator();
1112 Node* node = NewNode(op, value);
1113 Node* context =
1114 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1115 NodeProperties::ReplaceContextInput(node, context);
1116 }
1117
VisitStaCurrentContextSlot()1118 void BytecodeGraphBuilder::VisitStaCurrentContextSlot() {
1119 const Operator* op =
1120 javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(0));
1121 Node* value = environment()->LookupAccumulator();
1122 NewNode(op, value);
1123 }
1124
BuildLdaLookupSlot(TypeofMode typeof_mode)1125 void BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) {
1126 PrepareEagerCheckpoint();
1127 Node* name = jsgraph()->Constant(
1128 handle(bytecode_iterator().GetConstantForIndexOperand(0), isolate()));
1129 const Operator* op =
1130 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
1131 ? Runtime::kLoadLookupSlot
1132 : Runtime::kLoadLookupSlotInsideTypeof);
1133 Node* value = NewNode(op, name);
1134 environment()->BindAccumulator(value, Environment::kAttachFrameState);
1135 }
1136
VisitLdaLookupSlot()1137 void BytecodeGraphBuilder::VisitLdaLookupSlot() {
1138 BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF);
1139 }
1140
VisitLdaLookupSlotInsideTypeof()1141 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
1142 BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF);
1143 }
1144
CheckContextExtensions(uint32_t depth)1145 BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions(
1146 uint32_t depth) {
1147 // Output environment where the context has an extension
1148 Environment* slow_environment = nullptr;
1149
1150 // We only need to check up to the last-but-one depth, because the an eval
1151 // in the same scope as the variable itself has no way of shadowing it.
1152 for (uint32_t d = 0; d < depth; d++) {
1153 Node* extension_slot =
1154 NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false));
1155
1156 Node* check_no_extension =
1157 NewNode(simplified()->ReferenceEqual(), extension_slot,
1158 jsgraph()->TheHoleConstant());
1159
1160 NewBranch(check_no_extension);
1161
1162 {
1163 SubEnvironment sub_environment(this);
1164
1165 NewIfFalse();
1166 // If there is an extension, merge into the slow path.
1167 if (slow_environment == nullptr) {
1168 slow_environment = environment();
1169 NewMerge();
1170 } else {
1171 slow_environment->Merge(environment(),
1172 bytecode_analysis()->GetInLivenessFor(
1173 bytecode_iterator().current_offset()));
1174 }
1175 }
1176
1177 NewIfTrue();
1178 // Do nothing on if there is no extension, eventually falling through to
1179 // the fast path.
1180 }
1181
1182 // The depth can be zero, in which case no slow-path checks are built, and
1183 // the slow path environment can be null.
1184 DCHECK(depth == 0 || slow_environment != nullptr);
1185
1186 return slow_environment;
1187 }
1188
BuildLdaLookupContextSlot(TypeofMode typeof_mode)1189 void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) {
1190 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
1191
1192 // Check if any context in the depth has an extension.
1193 Environment* slow_environment = CheckContextExtensions(depth);
1194
1195 // Fast path, do a context load.
1196 {
1197 uint32_t slot_index = bytecode_iterator().GetIndexOperand(1);
1198
1199 const Operator* op = javascript()->LoadContext(depth, slot_index, false);
1200 environment()->BindAccumulator(NewNode(op));
1201 }
1202
1203 // Only build the slow path if there were any slow-path checks.
1204 if (slow_environment != nullptr) {
1205 // Add a merge to the fast environment.
1206 NewMerge();
1207 Environment* fast_environment = environment();
1208
1209 // Slow path, do a runtime load lookup.
1210 set_environment(slow_environment);
1211 {
1212 Node* name = jsgraph()->Constant(
1213 handle(bytecode_iterator().GetConstantForIndexOperand(0), isolate()));
1214
1215 const Operator* op =
1216 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
1217 ? Runtime::kLoadLookupSlot
1218 : Runtime::kLoadLookupSlotInsideTypeof);
1219 Node* value = NewNode(op, name);
1220 environment()->BindAccumulator(value, Environment::kAttachFrameState);
1221 }
1222
1223 fast_environment->Merge(environment(),
1224 bytecode_analysis()->GetOutLivenessFor(
1225 bytecode_iterator().current_offset()));
1226 set_environment(fast_environment);
1227 mark_as_needing_eager_checkpoint(true);
1228 }
1229 }
1230
VisitLdaLookupContextSlot()1231 void BytecodeGraphBuilder::VisitLdaLookupContextSlot() {
1232 BuildLdaLookupContextSlot(TypeofMode::NOT_INSIDE_TYPEOF);
1233 }
1234
VisitLdaLookupContextSlotInsideTypeof()1235 void BytecodeGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() {
1236 BuildLdaLookupContextSlot(TypeofMode::INSIDE_TYPEOF);
1237 }
1238
BuildLdaLookupGlobalSlot(TypeofMode typeof_mode)1239 void BytecodeGraphBuilder::BuildLdaLookupGlobalSlot(TypeofMode typeof_mode) {
1240 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
1241
1242 // Check if any context in the depth has an extension.
1243 Environment* slow_environment = CheckContextExtensions(depth);
1244
1245 // Fast path, do a global load.
1246 {
1247 PrepareEagerCheckpoint();
1248 Handle<Name> name(
1249 Name::cast(bytecode_iterator().GetConstantForIndexOperand(0)),
1250 isolate());
1251 uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
1252 Node* node = BuildLoadGlobal(name, feedback_slot_index, typeof_mode);
1253 environment()->BindAccumulator(node, Environment::kAttachFrameState);
1254 }
1255
1256 // Only build the slow path if there were any slow-path checks.
1257 if (slow_environment != nullptr) {
1258 // Add a merge to the fast environment.
1259 NewMerge();
1260 Environment* fast_environment = environment();
1261
1262 // Slow path, do a runtime load lookup.
1263 set_environment(slow_environment);
1264 {
1265 Node* name = jsgraph()->Constant(
1266 handle(bytecode_iterator().GetConstantForIndexOperand(0), isolate()));
1267
1268 const Operator* op =
1269 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
1270 ? Runtime::kLoadLookupSlot
1271 : Runtime::kLoadLookupSlotInsideTypeof);
1272 Node* value = NewNode(op, name);
1273 environment()->BindAccumulator(value, Environment::kAttachFrameState);
1274 }
1275
1276 fast_environment->Merge(environment(),
1277 bytecode_analysis()->GetOutLivenessFor(
1278 bytecode_iterator().current_offset()));
1279 set_environment(fast_environment);
1280 mark_as_needing_eager_checkpoint(true);
1281 }
1282 }
1283
VisitLdaLookupGlobalSlot()1284 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlot() {
1285 BuildLdaLookupGlobalSlot(TypeofMode::NOT_INSIDE_TYPEOF);
1286 }
1287
VisitLdaLookupGlobalSlotInsideTypeof()1288 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() {
1289 BuildLdaLookupGlobalSlot(TypeofMode::INSIDE_TYPEOF);
1290 }
1291
VisitStaLookupSlot()1292 void BytecodeGraphBuilder::VisitStaLookupSlot() {
1293 PrepareEagerCheckpoint();
1294 Node* value = environment()->LookupAccumulator();
1295 Node* name = jsgraph()->Constant(
1296 handle(bytecode_iterator().GetConstantForIndexOperand(0), isolate()));
1297 int bytecode_flags = bytecode_iterator().GetFlagOperand(1);
1298 LanguageMode language_mode = static_cast<LanguageMode>(
1299 interpreter::StoreLookupSlotFlags::LanguageModeBit::decode(
1300 bytecode_flags));
1301 LookupHoistingMode lookup_hoisting_mode = static_cast<LookupHoistingMode>(
1302 interpreter::StoreLookupSlotFlags::LookupHoistingModeBit::decode(
1303 bytecode_flags));
1304 DCHECK_IMPLIES(lookup_hoisting_mode == LookupHoistingMode::kLegacySloppy,
1305 is_sloppy(language_mode));
1306 const Operator* op = javascript()->CallRuntime(
1307 is_strict(language_mode)
1308 ? Runtime::kStoreLookupSlot_Strict
1309 : lookup_hoisting_mode == LookupHoistingMode::kLegacySloppy
1310 ? Runtime::kStoreLookupSlot_SloppyHoisting
1311 : Runtime::kStoreLookupSlot_Sloppy);
1312 Node* store = NewNode(op, name, value);
1313 environment()->BindAccumulator(store, Environment::kAttachFrameState);
1314 }
1315
VisitLdaNamedProperty()1316 void BytecodeGraphBuilder::VisitLdaNamedProperty() {
1317 PrepareEagerCheckpoint();
1318 Node* object =
1319 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1320 Handle<Name> name(
1321 Name::cast(bytecode_iterator().GetConstantForIndexOperand(1)), isolate());
1322 VectorSlotPair feedback =
1323 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1324 const Operator* op = javascript()->LoadNamed(name, feedback);
1325
1326 JSTypeHintLowering::LoweringResult lowering =
1327 TryBuildSimplifiedLoadNamed(op, object, feedback.slot());
1328 if (lowering.IsExit()) return;
1329
1330 Node* node = nullptr;
1331 if (lowering.IsSideEffectFree()) {
1332 node = lowering.value();
1333 } else {
1334 DCHECK(!lowering.Changed());
1335 node = NewNode(op, object);
1336 }
1337 environment()->BindAccumulator(node, Environment::kAttachFrameState);
1338 }
1339
VisitLdaKeyedProperty()1340 void BytecodeGraphBuilder::VisitLdaKeyedProperty() {
1341 PrepareEagerCheckpoint();
1342 Node* key = environment()->LookupAccumulator();
1343 Node* object =
1344 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1345 VectorSlotPair feedback =
1346 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
1347 const Operator* op = javascript()->LoadProperty(feedback);
1348
1349 JSTypeHintLowering::LoweringResult lowering =
1350 TryBuildSimplifiedLoadKeyed(op, object, key, feedback.slot());
1351 if (lowering.IsExit()) return;
1352
1353 Node* node = nullptr;
1354 if (lowering.IsSideEffectFree()) {
1355 node = lowering.value();
1356 } else {
1357 DCHECK(!lowering.Changed());
1358 node = NewNode(op, object, key);
1359 }
1360 environment()->BindAccumulator(node, Environment::kAttachFrameState);
1361 }
1362
BuildNamedStore(StoreMode store_mode)1363 void BytecodeGraphBuilder::BuildNamedStore(StoreMode store_mode) {
1364 PrepareEagerCheckpoint();
1365 Node* value = environment()->LookupAccumulator();
1366 Node* object =
1367 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1368 Handle<Name> name(
1369 Name::cast(bytecode_iterator().GetConstantForIndexOperand(1)), isolate());
1370 VectorSlotPair feedback =
1371 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1372
1373 const Operator* op;
1374 if (store_mode == StoreMode::kOwn) {
1375 DCHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
1376 feedback.vector()->GetKind(feedback.slot()));
1377 op = javascript()->StoreNamedOwn(name, feedback);
1378 } else {
1379 DCHECK_EQ(StoreMode::kNormal, store_mode);
1380 LanguageMode language_mode =
1381 feedback.vector()->GetLanguageMode(feedback.slot());
1382 op = javascript()->StoreNamed(language_mode, name, feedback);
1383 }
1384
1385 JSTypeHintLowering::LoweringResult lowering =
1386 TryBuildSimplifiedStoreNamed(op, object, value, feedback.slot());
1387 if (lowering.IsExit()) return;
1388
1389 Node* node = nullptr;
1390 if (lowering.IsSideEffectFree()) {
1391 node = lowering.value();
1392 } else {
1393 DCHECK(!lowering.Changed());
1394 node = NewNode(op, object, value);
1395 }
1396 environment()->RecordAfterState(node, Environment::kAttachFrameState);
1397 }
1398
VisitStaNamedProperty()1399 void BytecodeGraphBuilder::VisitStaNamedProperty() {
1400 BuildNamedStore(StoreMode::kNormal);
1401 }
1402
VisitStaNamedOwnProperty()1403 void BytecodeGraphBuilder::VisitStaNamedOwnProperty() {
1404 BuildNamedStore(StoreMode::kOwn);
1405 }
1406
VisitStaKeyedProperty()1407 void BytecodeGraphBuilder::VisitStaKeyedProperty() {
1408 PrepareEagerCheckpoint();
1409 Node* value = environment()->LookupAccumulator();
1410 Node* object =
1411 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1412 Node* key =
1413 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1414 VectorSlotPair feedback =
1415 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1416 LanguageMode language_mode =
1417 feedback.vector()->GetLanguageMode(feedback.slot());
1418 const Operator* op = javascript()->StoreProperty(language_mode, feedback);
1419
1420 JSTypeHintLowering::LoweringResult lowering =
1421 TryBuildSimplifiedStoreKeyed(op, object, key, value, feedback.slot());
1422 if (lowering.IsExit()) return;
1423
1424 Node* node = nullptr;
1425 if (lowering.IsSideEffectFree()) {
1426 node = lowering.value();
1427 } else {
1428 DCHECK(!lowering.Changed());
1429 node = NewNode(op, object, key, value);
1430 }
1431
1432 environment()->RecordAfterState(node, Environment::kAttachFrameState);
1433 }
1434
VisitLdaModuleVariable()1435 void BytecodeGraphBuilder::VisitLdaModuleVariable() {
1436 int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
1437 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
1438 Node* module =
1439 NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true));
1440 Node* value = NewNode(javascript()->LoadModule(cell_index), module);
1441 environment()->BindAccumulator(value);
1442 }
1443
VisitStaModuleVariable()1444 void BytecodeGraphBuilder::VisitStaModuleVariable() {
1445 int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
1446 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
1447 Node* module =
1448 NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true));
1449 Node* value = environment()->LookupAccumulator();
1450 NewNode(javascript()->StoreModule(cell_index), module, value);
1451 }
1452
VisitPushContext()1453 void BytecodeGraphBuilder::VisitPushContext() {
1454 Node* new_context = environment()->LookupAccumulator();
1455 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0),
1456 environment()->Context());
1457 environment()->SetContext(new_context);
1458 }
1459
VisitPopContext()1460 void BytecodeGraphBuilder::VisitPopContext() {
1461 Node* context =
1462 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1463 environment()->SetContext(context);
1464 }
1465
VisitCreateClosure()1466 void BytecodeGraphBuilder::VisitCreateClosure() {
1467 Handle<SharedFunctionInfo> shared_info(
1468 SharedFunctionInfo::cast(
1469 bytecode_iterator().GetConstantForIndexOperand(0)),
1470 isolate());
1471 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
1472 FeedbackNexus nexus(feedback_vector(), slot);
1473 PretenureFlag tenured =
1474 interpreter::CreateClosureFlags::PretenuredBit::decode(
1475 bytecode_iterator().GetFlagOperand(2))
1476 ? TENURED
1477 : NOT_TENURED;
1478 const Operator* op = javascript()->CreateClosure(
1479 shared_info, nexus.GetFeedbackCell(),
1480 handle(jsgraph()->isolate()->builtins()->builtin(Builtins::kCompileLazy),
1481 isolate()),
1482 tenured);
1483 Node* closure = NewNode(op);
1484 environment()->BindAccumulator(closure);
1485 }
1486
VisitCreateBlockContext()1487 void BytecodeGraphBuilder::VisitCreateBlockContext() {
1488 Handle<ScopeInfo> scope_info(
1489 ScopeInfo::cast(bytecode_iterator().GetConstantForIndexOperand(0)),
1490 isolate());
1491
1492 const Operator* op = javascript()->CreateBlockContext(scope_info);
1493 Node* context = NewNode(op);
1494 environment()->BindAccumulator(context);
1495 }
1496
VisitCreateFunctionContext()1497 void BytecodeGraphBuilder::VisitCreateFunctionContext() {
1498 Handle<ScopeInfo> scope_info(
1499 ScopeInfo::cast(bytecode_iterator().GetConstantForIndexOperand(0)),
1500 isolate());
1501 uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(1);
1502 const Operator* op =
1503 javascript()->CreateFunctionContext(scope_info, slots, FUNCTION_SCOPE);
1504 Node* context = NewNode(op);
1505 environment()->BindAccumulator(context);
1506 }
1507
VisitCreateEvalContext()1508 void BytecodeGraphBuilder::VisitCreateEvalContext() {
1509 Handle<ScopeInfo> scope_info(
1510 ScopeInfo::cast(bytecode_iterator().GetConstantForIndexOperand(0)),
1511 isolate());
1512 uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(1);
1513 const Operator* op =
1514 javascript()->CreateFunctionContext(scope_info, slots, EVAL_SCOPE);
1515 Node* context = NewNode(op);
1516 environment()->BindAccumulator(context);
1517 }
1518
VisitCreateCatchContext()1519 void BytecodeGraphBuilder::VisitCreateCatchContext() {
1520 interpreter::Register reg = bytecode_iterator().GetRegisterOperand(0);
1521 Node* exception = environment()->LookupRegister(reg);
1522 Handle<ScopeInfo> scope_info(
1523 ScopeInfo::cast(bytecode_iterator().GetConstantForIndexOperand(1)),
1524 isolate());
1525
1526 const Operator* op = javascript()->CreateCatchContext(scope_info);
1527 Node* context = NewNode(op, exception);
1528 environment()->BindAccumulator(context);
1529 }
1530
VisitCreateWithContext()1531 void BytecodeGraphBuilder::VisitCreateWithContext() {
1532 Node* object =
1533 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1534 Handle<ScopeInfo> scope_info(
1535 ScopeInfo::cast(bytecode_iterator().GetConstantForIndexOperand(1)),
1536 isolate());
1537
1538 const Operator* op = javascript()->CreateWithContext(scope_info);
1539 Node* context = NewNode(op, object);
1540 environment()->BindAccumulator(context);
1541 }
1542
BuildCreateArguments(CreateArgumentsType type)1543 void BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) {
1544 const Operator* op = javascript()->CreateArguments(type);
1545 Node* object = NewNode(op, GetFunctionClosure());
1546 environment()->BindAccumulator(object, Environment::kAttachFrameState);
1547 }
1548
VisitCreateMappedArguments()1549 void BytecodeGraphBuilder::VisitCreateMappedArguments() {
1550 BuildCreateArguments(CreateArgumentsType::kMappedArguments);
1551 }
1552
VisitCreateUnmappedArguments()1553 void BytecodeGraphBuilder::VisitCreateUnmappedArguments() {
1554 BuildCreateArguments(CreateArgumentsType::kUnmappedArguments);
1555 }
1556
VisitCreateRestParameter()1557 void BytecodeGraphBuilder::VisitCreateRestParameter() {
1558 BuildCreateArguments(CreateArgumentsType::kRestParameter);
1559 }
1560
VisitCreateRegExpLiteral()1561 void BytecodeGraphBuilder::VisitCreateRegExpLiteral() {
1562 Handle<String> constant_pattern(
1563 String::cast(bytecode_iterator().GetConstantForIndexOperand(0)),
1564 isolate());
1565 int const slot_id = bytecode_iterator().GetIndexOperand(1);
1566 VectorSlotPair pair = CreateVectorSlotPair(slot_id);
1567 int literal_flags = bytecode_iterator().GetFlagOperand(2);
1568 Node* literal = NewNode(
1569 javascript()->CreateLiteralRegExp(constant_pattern, pair, literal_flags));
1570 environment()->BindAccumulator(literal, Environment::kAttachFrameState);
1571 }
1572
VisitCreateArrayLiteral()1573 void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
1574 Handle<ArrayBoilerplateDescription> array_boilerplate_description(
1575 ArrayBoilerplateDescription::cast(
1576 bytecode_iterator().GetConstantForIndexOperand(0)),
1577 isolate());
1578 int const slot_id = bytecode_iterator().GetIndexOperand(1);
1579 VectorSlotPair pair = CreateVectorSlotPair(slot_id);
1580 int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
1581 int literal_flags =
1582 interpreter::CreateArrayLiteralFlags::FlagsBits::decode(bytecode_flags);
1583 // Disable allocation site mementos. Only unoptimized code will collect
1584 // feedback about allocation site. Once the code is optimized we expect the
1585 // data to converge. So, we disable allocation site mementos in optimized
1586 // code. We can revisit this when we have data to the contrary.
1587 literal_flags |= ArrayLiteral::kDisableMementos;
1588 // TODO(mstarzinger): Thread through number of elements. The below number is
1589 // only an estimate and does not match {ArrayLiteral::values::length}.
1590 int number_of_elements =
1591 array_boilerplate_description->constant_elements()->length();
1592 Node* literal = NewNode(javascript()->CreateLiteralArray(
1593 array_boilerplate_description, pair, literal_flags, number_of_elements));
1594 environment()->BindAccumulator(literal, Environment::kAttachFrameState);
1595 }
1596
VisitCreateEmptyArrayLiteral()1597 void BytecodeGraphBuilder::VisitCreateEmptyArrayLiteral() {
1598 int const slot_id = bytecode_iterator().GetIndexOperand(0);
1599 VectorSlotPair pair = CreateVectorSlotPair(slot_id);
1600 Node* literal = NewNode(javascript()->CreateEmptyLiteralArray(pair));
1601 environment()->BindAccumulator(literal);
1602 }
1603
VisitCreateObjectLiteral()1604 void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
1605 Handle<ObjectBoilerplateDescription> constant_properties(
1606 ObjectBoilerplateDescription::cast(
1607 bytecode_iterator().GetConstantForIndexOperand(0)),
1608 isolate());
1609 int const slot_id = bytecode_iterator().GetIndexOperand(1);
1610 VectorSlotPair pair = CreateVectorSlotPair(slot_id);
1611 int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
1612 int literal_flags =
1613 interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
1614 // TODO(mstarzinger): Thread through number of properties. The below number is
1615 // only an estimate and does not match {ObjectLiteral::properties_count}.
1616 int number_of_properties = constant_properties->size();
1617 Node* literal = NewNode(javascript()->CreateLiteralObject(
1618 constant_properties, pair, literal_flags, number_of_properties));
1619 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(3),
1620 literal, Environment::kAttachFrameState);
1621 }
1622
VisitCreateEmptyObjectLiteral()1623 void BytecodeGraphBuilder::VisitCreateEmptyObjectLiteral() {
1624 Node* literal =
1625 NewNode(javascript()->CreateEmptyLiteralObject(), GetFunctionClosure());
1626 environment()->BindAccumulator(literal);
1627 }
1628
VisitCloneObject()1629 void BytecodeGraphBuilder::VisitCloneObject() {
1630 PrepareEagerCheckpoint();
1631 Node* source =
1632 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1633 int flags = bytecode_iterator().GetFlagOperand(1);
1634 int slot = bytecode_iterator().GetIndexOperand(2);
1635 const Operator* op =
1636 javascript()->CloneObject(CreateVectorSlotPair(slot), flags);
1637 Node* value = NewNode(op, source);
1638 environment()->BindAccumulator(value, Environment::kAttachFrameState);
1639 }
1640
VisitGetTemplateObject()1641 void BytecodeGraphBuilder::VisitGetTemplateObject() {
1642 Handle<TemplateObjectDescription> description(
1643 TemplateObjectDescription::cast(
1644 bytecode_iterator().GetConstantForIndexOperand(0)),
1645 isolate());
1646 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
1647 FeedbackNexus nexus(feedback_vector(), slot);
1648
1649 Handle<JSArray> cached_value;
1650 if (nexus.GetFeedback() == MaybeObject::FromSmi(Smi::kZero)) {
1651 // It's not observable when the template object is created, so we
1652 // can just create it eagerly during graph building and bake in
1653 // the JSArray constant here.
1654 cached_value =
1655 TemplateObjectDescription::CreateTemplateObject(isolate(), description);
1656 nexus.vector()->Set(slot, *cached_value);
1657 } else {
1658 cached_value = handle(
1659 JSArray::cast(nexus.GetFeedback()->ToStrongHeapObject()), isolate());
1660 }
1661
1662 Node* template_object = jsgraph()->HeapConstant(cached_value);
1663 environment()->BindAccumulator(template_object);
1664 }
1665
GetCallArgumentsFromRegisters(Node * callee,Node * receiver,interpreter::Register first_arg,int arg_count)1666 Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegisters(
1667 Node* callee, Node* receiver, interpreter::Register first_arg,
1668 int arg_count) {
1669 // The arity of the Call node -- includes the callee, receiver and function
1670 // arguments.
1671 int arity = 2 + arg_count;
1672
1673 Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
1674
1675 all[0] = callee;
1676 all[1] = receiver;
1677
1678 // The function arguments are in consecutive registers.
1679 int arg_base = first_arg.index();
1680 for (int i = 0; i < arg_count; ++i) {
1681 all[2 + i] =
1682 environment()->LookupRegister(interpreter::Register(arg_base + i));
1683 }
1684
1685 return all;
1686 }
1687
ProcessCallArguments(const Operator * call_op,Node * const * args,int arg_count)1688 Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
1689 Node* const* args,
1690 int arg_count) {
1691 return MakeNode(call_op, arg_count, args, false);
1692 }
1693
ProcessCallArguments(const Operator * call_op,Node * callee,interpreter::Register receiver,size_t reg_count)1694 Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
1695 Node* callee,
1696 interpreter::Register receiver,
1697 size_t reg_count) {
1698 Node* receiver_node = environment()->LookupRegister(receiver);
1699 // The receiver is followed by the arguments in the consecutive registers.
1700 DCHECK_GE(reg_count, 1);
1701 interpreter::Register first_arg = interpreter::Register(receiver.index() + 1);
1702 int arg_count = static_cast<int>(reg_count) - 1;
1703
1704 Node* const* call_args = GetCallArgumentsFromRegisters(callee, receiver_node,
1705 first_arg, arg_count);
1706 return ProcessCallArguments(call_op, call_args, 2 + arg_count);
1707 }
1708
BuildCall(ConvertReceiverMode receiver_mode,Node * const * args,size_t arg_count,int slot_id)1709 void BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode,
1710 Node* const* args, size_t arg_count,
1711 int slot_id) {
1712 DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode(
1713 bytecode_iterator().current_bytecode()),
1714 receiver_mode);
1715 PrepareEagerCheckpoint();
1716
1717 VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1718
1719 CallFrequency frequency = ComputeCallFrequency(slot_id);
1720 const Operator* op =
1721 javascript()->Call(arg_count, frequency, feedback, receiver_mode,
1722 GetSpeculationMode(slot_id));
1723 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall(
1724 op, args, static_cast<int>(arg_count), feedback.slot());
1725 if (lowering.IsExit()) return;
1726
1727 Node* node = nullptr;
1728 if (lowering.IsSideEffectFree()) {
1729 node = lowering.value();
1730 } else {
1731 DCHECK(!lowering.Changed());
1732 node = ProcessCallArguments(op, args, static_cast<int>(arg_count));
1733 }
1734 environment()->BindAccumulator(node, Environment::kAttachFrameState);
1735 }
1736
ProcessCallVarArgs(ConvertReceiverMode receiver_mode,Node * callee,interpreter::Register first_reg,int arg_count)1737 Node* const* BytecodeGraphBuilder::ProcessCallVarArgs(
1738 ConvertReceiverMode receiver_mode, Node* callee,
1739 interpreter::Register first_reg, int arg_count) {
1740 DCHECK_GE(arg_count, 0);
1741 Node* receiver_node;
1742 interpreter::Register first_arg;
1743
1744 if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
1745 // The receiver is implicit (and undefined), the arguments are in
1746 // consecutive registers.
1747 receiver_node = jsgraph()->UndefinedConstant();
1748 first_arg = first_reg;
1749 } else {
1750 // The receiver is the first register, followed by the arguments in the
1751 // consecutive registers.
1752 receiver_node = environment()->LookupRegister(first_reg);
1753 first_arg = interpreter::Register(first_reg.index() + 1);
1754 }
1755
1756 Node* const* call_args = GetCallArgumentsFromRegisters(callee, receiver_node,
1757 first_arg, arg_count);
1758 return call_args;
1759 }
1760
BuildCallVarArgs(ConvertReceiverMode receiver_mode)1761 void BytecodeGraphBuilder::BuildCallVarArgs(ConvertReceiverMode receiver_mode) {
1762 DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode(
1763 bytecode_iterator().current_bytecode()),
1764 receiver_mode);
1765 Node* callee =
1766 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1767 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
1768 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1769 int const slot_id = bytecode_iterator().GetIndexOperand(3);
1770
1771 int arg_count = receiver_mode == ConvertReceiverMode::kNullOrUndefined
1772 ? static_cast<int>(reg_count)
1773 : static_cast<int>(reg_count) - 1;
1774 Node* const* call_args =
1775 ProcessCallVarArgs(receiver_mode, callee, first_reg, arg_count);
1776 BuildCall(receiver_mode, call_args, static_cast<size_t>(2 + arg_count),
1777 slot_id);
1778 }
1779
VisitCallAnyReceiver()1780 void BytecodeGraphBuilder::VisitCallAnyReceiver() {
1781 BuildCallVarArgs(ConvertReceiverMode::kAny);
1782 }
1783
VisitCallProperty()1784 void BytecodeGraphBuilder::VisitCallProperty() {
1785 BuildCallVarArgs(ConvertReceiverMode::kNotNullOrUndefined);
1786 }
1787
VisitCallProperty0()1788 void BytecodeGraphBuilder::VisitCallProperty0() {
1789 Node* callee =
1790 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1791 Node* receiver =
1792 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1793 int const slot_id = bytecode_iterator().GetIndexOperand(2);
1794 BuildCall(ConvertReceiverMode::kNotNullOrUndefined, {callee, receiver},
1795 slot_id);
1796 }
1797
VisitCallProperty1()1798 void BytecodeGraphBuilder::VisitCallProperty1() {
1799 Node* callee =
1800 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1801 Node* receiver =
1802 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1803 Node* arg0 =
1804 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
1805 int const slot_id = bytecode_iterator().GetIndexOperand(3);
1806 BuildCall(ConvertReceiverMode::kNotNullOrUndefined, {callee, receiver, arg0},
1807 slot_id);
1808 }
1809
VisitCallProperty2()1810 void BytecodeGraphBuilder::VisitCallProperty2() {
1811 Node* callee =
1812 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1813 Node* receiver =
1814 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1815 Node* arg0 =
1816 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
1817 Node* arg1 =
1818 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(3));
1819 int const slot_id = bytecode_iterator().GetIndexOperand(4);
1820 BuildCall(ConvertReceiverMode::kNotNullOrUndefined,
1821 {callee, receiver, arg0, arg1}, slot_id);
1822 }
1823
VisitCallUndefinedReceiver()1824 void BytecodeGraphBuilder::VisitCallUndefinedReceiver() {
1825 BuildCallVarArgs(ConvertReceiverMode::kNullOrUndefined);
1826 }
1827
VisitCallUndefinedReceiver0()1828 void BytecodeGraphBuilder::VisitCallUndefinedReceiver0() {
1829 Node* callee =
1830 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1831 Node* receiver = jsgraph()->UndefinedConstant();
1832 int const slot_id = bytecode_iterator().GetIndexOperand(1);
1833 BuildCall(ConvertReceiverMode::kNullOrUndefined, {callee, receiver}, slot_id);
1834 }
1835
VisitCallUndefinedReceiver1()1836 void BytecodeGraphBuilder::VisitCallUndefinedReceiver1() {
1837 Node* callee =
1838 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1839 Node* receiver = jsgraph()->UndefinedConstant();
1840 Node* arg0 =
1841 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1842 int const slot_id = bytecode_iterator().GetIndexOperand(2);
1843 BuildCall(ConvertReceiverMode::kNullOrUndefined, {callee, receiver, arg0},
1844 slot_id);
1845 }
1846
VisitCallUndefinedReceiver2()1847 void BytecodeGraphBuilder::VisitCallUndefinedReceiver2() {
1848 Node* callee =
1849 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1850 Node* receiver = jsgraph()->UndefinedConstant();
1851 Node* arg0 =
1852 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1853 Node* arg1 =
1854 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
1855 int const slot_id = bytecode_iterator().GetIndexOperand(3);
1856 BuildCall(ConvertReceiverMode::kNullOrUndefined,
1857 {callee, receiver, arg0, arg1}, slot_id);
1858 }
1859
VisitCallWithSpread()1860 void BytecodeGraphBuilder::VisitCallWithSpread() {
1861 PrepareEagerCheckpoint();
1862 Node* callee =
1863 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1864 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1865 Node* receiver_node = environment()->LookupRegister(receiver);
1866 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1867 interpreter::Register first_arg = interpreter::Register(receiver.index() + 1);
1868 int arg_count = static_cast<int>(reg_count) - 1;
1869 Node* const* args = GetCallArgumentsFromRegisters(callee, receiver_node,
1870 first_arg, arg_count);
1871 int const slot_id = bytecode_iterator().GetIndexOperand(3);
1872 VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1873
1874 CallFrequency frequency = ComputeCallFrequency(slot_id);
1875 const Operator* op = javascript()->CallWithSpread(
1876 static_cast<int>(reg_count + 1), frequency, feedback);
1877
1878 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall(
1879 op, args, static_cast<int>(arg_count), feedback.slot());
1880 if (lowering.IsExit()) return;
1881
1882 Node* node = nullptr;
1883 if (lowering.IsSideEffectFree()) {
1884 node = lowering.value();
1885 } else {
1886 DCHECK(!lowering.Changed());
1887 node = ProcessCallArguments(op, args, 2 + arg_count);
1888 }
1889 environment()->BindAccumulator(node, Environment::kAttachFrameState);
1890 }
1891
VisitCallJSRuntime()1892 void BytecodeGraphBuilder::VisitCallJSRuntime() {
1893 PrepareEagerCheckpoint();
1894 Node* callee = BuildLoadNativeContextField(
1895 bytecode_iterator().GetNativeContextIndexOperand(0));
1896 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
1897 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1898 int arg_count = static_cast<int>(reg_count);
1899
1900 const Operator* call = javascript()->Call(2 + arg_count);
1901 Node* const* call_args = ProcessCallVarArgs(
1902 ConvertReceiverMode::kNullOrUndefined, callee, first_reg, arg_count);
1903 Node* value = ProcessCallArguments(call, call_args, 2 + arg_count);
1904 environment()->BindAccumulator(value, Environment::kAttachFrameState);
1905 }
1906
ProcessCallRuntimeArguments(const Operator * call_runtime_op,interpreter::Register receiver,size_t reg_count)1907 Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
1908 const Operator* call_runtime_op, interpreter::Register receiver,
1909 size_t reg_count) {
1910 int arg_count = static_cast<int>(reg_count);
1911 // arity is args.
1912 int arity = arg_count;
1913 Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
1914 int first_arg_index = receiver.index();
1915 for (int i = 0; i < static_cast<int>(reg_count); ++i) {
1916 all[i] = environment()->LookupRegister(
1917 interpreter::Register(first_arg_index + i));
1918 }
1919 Node* value = MakeNode(call_runtime_op, arity, all, false);
1920 return value;
1921 }
1922
VisitCallRuntime()1923 void BytecodeGraphBuilder::VisitCallRuntime() {
1924 PrepareEagerCheckpoint();
1925 Runtime::FunctionId function_id = bytecode_iterator().GetRuntimeIdOperand(0);
1926 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1927 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1928
1929 // Create node to perform the runtime call.
1930 const Operator* call = javascript()->CallRuntime(function_id, reg_count);
1931 Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count);
1932 environment()->BindAccumulator(value, Environment::kAttachFrameState);
1933
1934 // Connect to the end if {function_id} is non-returning.
1935 if (Runtime::IsNonReturning(function_id)) {
1936 // TODO(7099): Investigate if we need LoopExit node here.
1937 Node* control = NewNode(common()->Throw());
1938 MergeControlToLeaveFunction(control);
1939 }
1940 }
1941
VisitCallRuntimeForPair()1942 void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
1943 PrepareEagerCheckpoint();
1944 Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
1945 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1946 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1947 interpreter::Register first_return =
1948 bytecode_iterator().GetRegisterOperand(3);
1949
1950 // Create node to perform the runtime call.
1951 const Operator* call = javascript()->CallRuntime(functionId, reg_count);
1952 Node* return_pair = ProcessCallRuntimeArguments(call, receiver, reg_count);
1953 environment()->BindRegistersToProjections(first_return, return_pair,
1954 Environment::kAttachFrameState);
1955 }
1956
GetConstructArgumentsFromRegister(Node * target,Node * new_target,interpreter::Register first_arg,int arg_count)1957 Node* const* BytecodeGraphBuilder::GetConstructArgumentsFromRegister(
1958 Node* target, Node* new_target, interpreter::Register first_arg,
1959 int arg_count) {
1960 // arity is args + callee and new target.
1961 int arity = arg_count + 2;
1962 Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
1963 all[0] = target;
1964 int first_arg_index = first_arg.index();
1965 for (int i = 0; i < arg_count; ++i) {
1966 all[1 + i] = environment()->LookupRegister(
1967 interpreter::Register(first_arg_index + i));
1968 }
1969 all[arity - 1] = new_target;
1970 return all;
1971 }
1972
ProcessConstructArguments(const Operator * op,Node * const * args,int arg_count)1973 Node* BytecodeGraphBuilder::ProcessConstructArguments(const Operator* op,
1974 Node* const* args,
1975 int arg_count) {
1976 return MakeNode(op, arg_count, args, false);
1977 }
1978
VisitConstruct()1979 void BytecodeGraphBuilder::VisitConstruct() {
1980 PrepareEagerCheckpoint();
1981 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
1982 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
1983 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1984 int const slot_id = bytecode_iterator().GetIndexOperand(3);
1985 VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1986
1987 Node* new_target = environment()->LookupAccumulator();
1988 Node* callee = environment()->LookupRegister(callee_reg);
1989
1990 CallFrequency frequency = ComputeCallFrequency(slot_id);
1991 const Operator* op = javascript()->Construct(
1992 static_cast<uint32_t>(reg_count + 2), frequency, feedback);
1993 int arg_count = static_cast<int>(reg_count);
1994 Node* const* args = GetConstructArgumentsFromRegister(callee, new_target,
1995 first_reg, arg_count);
1996 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedConstruct(
1997 op, args, static_cast<int>(arg_count), feedback.slot());
1998 if (lowering.IsExit()) return;
1999
2000 Node* node = nullptr;
2001 if (lowering.IsSideEffectFree()) {
2002 node = lowering.value();
2003 } else {
2004 DCHECK(!lowering.Changed());
2005 node = ProcessConstructArguments(op, args, 2 + arg_count);
2006 }
2007 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2008 }
2009
VisitConstructWithSpread()2010 void BytecodeGraphBuilder::VisitConstructWithSpread() {
2011 PrepareEagerCheckpoint();
2012 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
2013 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
2014 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
2015 int const slot_id = bytecode_iterator().GetIndexOperand(3);
2016 VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
2017
2018 Node* new_target = environment()->LookupAccumulator();
2019 Node* callee = environment()->LookupRegister(callee_reg);
2020
2021 CallFrequency frequency = ComputeCallFrequency(slot_id);
2022 const Operator* op = javascript()->ConstructWithSpread(
2023 static_cast<uint32_t>(reg_count + 2), frequency, feedback);
2024 int arg_count = static_cast<int>(reg_count);
2025 Node* const* args = GetConstructArgumentsFromRegister(callee, new_target,
2026 first_reg, arg_count);
2027 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedConstruct(
2028 op, args, static_cast<int>(arg_count), feedback.slot());
2029 if (lowering.IsExit()) return;
2030
2031 Node* node = nullptr;
2032 if (lowering.IsSideEffectFree()) {
2033 node = lowering.value();
2034 } else {
2035 DCHECK(!lowering.Changed());
2036 node = ProcessConstructArguments(op, args, 2 + arg_count);
2037 }
2038 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2039 }
2040
VisitInvokeIntrinsic()2041 void BytecodeGraphBuilder::VisitInvokeIntrinsic() {
2042 PrepareEagerCheckpoint();
2043 Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0);
2044 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
2045 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
2046
2047 // Create node to perform the runtime call. Turbofan will take care of the
2048 // lowering.
2049 const Operator* call = javascript()->CallRuntime(functionId, reg_count);
2050 Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count);
2051 environment()->BindAccumulator(value, Environment::kAttachFrameState);
2052 }
2053
VisitThrow()2054 void BytecodeGraphBuilder::VisitThrow() {
2055 BuildLoopExitsForFunctionExit(bytecode_analysis()->GetInLivenessFor(
2056 bytecode_iterator().current_offset()));
2057 Node* value = environment()->LookupAccumulator();
2058 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value);
2059 environment()->BindAccumulator(call, Environment::kAttachFrameState);
2060 Node* control = NewNode(common()->Throw());
2061 MergeControlToLeaveFunction(control);
2062 }
2063
VisitAbort()2064 void BytecodeGraphBuilder::VisitAbort() {
2065 BuildLoopExitsForFunctionExit(bytecode_analysis()->GetInLivenessFor(
2066 bytecode_iterator().current_offset()));
2067 AbortReason reason =
2068 static_cast<AbortReason>(bytecode_iterator().GetIndexOperand(0));
2069 NewNode(simplified()->RuntimeAbort(reason));
2070 Node* control = NewNode(common()->Throw());
2071 MergeControlToLeaveFunction(control);
2072 }
2073
VisitReThrow()2074 void BytecodeGraphBuilder::VisitReThrow() {
2075 BuildLoopExitsForFunctionExit(bytecode_analysis()->GetInLivenessFor(
2076 bytecode_iterator().current_offset()));
2077 Node* value = environment()->LookupAccumulator();
2078 NewNode(javascript()->CallRuntime(Runtime::kReThrow), value);
2079 Node* control = NewNode(common()->Throw());
2080 MergeControlToLeaveFunction(control);
2081 }
2082
BuildHoleCheckAndThrow(Node * condition,Runtime::FunctionId runtime_id,Node * name)2083 void BytecodeGraphBuilder::BuildHoleCheckAndThrow(
2084 Node* condition, Runtime::FunctionId runtime_id, Node* name) {
2085 Node* accumulator = environment()->LookupAccumulator();
2086 NewBranch(condition, BranchHint::kFalse);
2087 {
2088 SubEnvironment sub_environment(this);
2089
2090 NewIfTrue();
2091 BuildLoopExitsForFunctionExit(bytecode_analysis()->GetInLivenessFor(
2092 bytecode_iterator().current_offset()));
2093 Node* node;
2094 const Operator* op = javascript()->CallRuntime(runtime_id);
2095 if (runtime_id == Runtime::kThrowReferenceError) {
2096 DCHECK_NOT_NULL(name);
2097 node = NewNode(op, name);
2098 } else {
2099 DCHECK(runtime_id == Runtime::kThrowSuperAlreadyCalledError ||
2100 runtime_id == Runtime::kThrowSuperNotCalled);
2101 node = NewNode(op);
2102 }
2103 environment()->RecordAfterState(node, Environment::kAttachFrameState);
2104 Node* control = NewNode(common()->Throw());
2105 MergeControlToLeaveFunction(control);
2106 }
2107 NewIfFalse();
2108 environment()->BindAccumulator(accumulator);
2109 }
2110
VisitThrowReferenceErrorIfHole()2111 void BytecodeGraphBuilder::VisitThrowReferenceErrorIfHole() {
2112 Node* accumulator = environment()->LookupAccumulator();
2113 Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator,
2114 jsgraph()->TheHoleConstant());
2115 Node* name = jsgraph()->Constant(
2116 handle(bytecode_iterator().GetConstantForIndexOperand(0), isolate()));
2117 BuildHoleCheckAndThrow(check_for_hole, Runtime::kThrowReferenceError, name);
2118 }
2119
VisitThrowSuperNotCalledIfHole()2120 void BytecodeGraphBuilder::VisitThrowSuperNotCalledIfHole() {
2121 Node* accumulator = environment()->LookupAccumulator();
2122 Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator,
2123 jsgraph()->TheHoleConstant());
2124 BuildHoleCheckAndThrow(check_for_hole, Runtime::kThrowSuperNotCalled);
2125 }
2126
VisitThrowSuperAlreadyCalledIfNotHole()2127 void BytecodeGraphBuilder::VisitThrowSuperAlreadyCalledIfNotHole() {
2128 Node* accumulator = environment()->LookupAccumulator();
2129 Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator,
2130 jsgraph()->TheHoleConstant());
2131 Node* check_for_not_hole =
2132 NewNode(simplified()->BooleanNot(), check_for_hole);
2133 BuildHoleCheckAndThrow(check_for_not_hole,
2134 Runtime::kThrowSuperAlreadyCalledError);
2135 }
2136
BuildUnaryOp(const Operator * op)2137 void BytecodeGraphBuilder::BuildUnaryOp(const Operator* op) {
2138 PrepareEagerCheckpoint();
2139 Node* operand = environment()->LookupAccumulator();
2140
2141 FeedbackSlot slot =
2142 bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex);
2143 JSTypeHintLowering::LoweringResult lowering =
2144 TryBuildSimplifiedUnaryOp(op, operand, slot);
2145 if (lowering.IsExit()) return;
2146
2147 Node* node = nullptr;
2148 if (lowering.IsSideEffectFree()) {
2149 node = lowering.value();
2150 } else {
2151 DCHECK(!lowering.Changed());
2152 node = NewNode(op, operand);
2153 }
2154
2155 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2156 }
2157
BuildBinaryOp(const Operator * op)2158 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) {
2159 PrepareEagerCheckpoint();
2160 Node* left =
2161 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2162 Node* right = environment()->LookupAccumulator();
2163
2164 FeedbackSlot slot =
2165 bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex);
2166 JSTypeHintLowering::LoweringResult lowering =
2167 TryBuildSimplifiedBinaryOp(op, left, right, slot);
2168 if (lowering.IsExit()) return;
2169
2170 Node* node = nullptr;
2171 if (lowering.IsSideEffectFree()) {
2172 node = lowering.value();
2173 } else {
2174 DCHECK(!lowering.Changed());
2175 node = NewNode(op, left, right);
2176 }
2177
2178 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2179 }
2180
2181 // Helper function to create binary operation hint from the recorded type
2182 // feedback.
GetBinaryOperationHint(int operand_index)2183 BinaryOperationHint BytecodeGraphBuilder::GetBinaryOperationHint(
2184 int operand_index) {
2185 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(operand_index);
2186 FeedbackNexus nexus(feedback_vector(), slot);
2187 return nexus.GetBinaryOperationFeedback();
2188 }
2189
2190 // Helper function to create compare operation hint from the recorded type
2191 // feedback.
GetCompareOperationHint()2192 CompareOperationHint BytecodeGraphBuilder::GetCompareOperationHint() {
2193 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
2194 FeedbackNexus nexus(feedback_vector(), slot);
2195 return nexus.GetCompareOperationFeedback();
2196 }
2197
2198 // Helper function to create for-in mode from the recorded type feedback.
GetForInMode(int operand_index)2199 ForInMode BytecodeGraphBuilder::GetForInMode(int operand_index) {
2200 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(operand_index);
2201 FeedbackNexus nexus(feedback_vector(), slot);
2202 switch (nexus.GetForInFeedback()) {
2203 case ForInHint::kNone:
2204 case ForInHint::kEnumCacheKeysAndIndices:
2205 return ForInMode::kUseEnumCacheKeysAndIndices;
2206 case ForInHint::kEnumCacheKeys:
2207 return ForInMode::kUseEnumCacheKeys;
2208 case ForInHint::kAny:
2209 return ForInMode::kGeneric;
2210 }
2211 UNREACHABLE();
2212 }
2213
ComputeCallFrequency(int slot_id) const2214 CallFrequency BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const {
2215 if (invocation_frequency_.IsUnknown()) return CallFrequency();
2216 FeedbackNexus nexus(feedback_vector(), FeedbackVector::ToSlot(slot_id));
2217 return CallFrequency(nexus.ComputeCallFrequency() *
2218 invocation_frequency_.value());
2219 }
2220
GetSpeculationMode(int slot_id) const2221 SpeculationMode BytecodeGraphBuilder::GetSpeculationMode(int slot_id) const {
2222 FeedbackNexus nexus(feedback_vector(), FeedbackVector::ToSlot(slot_id));
2223 return nexus.GetSpeculationMode();
2224 }
2225
VisitBitwiseNot()2226 void BytecodeGraphBuilder::VisitBitwiseNot() {
2227 BuildUnaryOp(javascript()->BitwiseNot());
2228 }
2229
VisitDec()2230 void BytecodeGraphBuilder::VisitDec() {
2231 BuildUnaryOp(javascript()->Decrement());
2232 }
2233
VisitInc()2234 void BytecodeGraphBuilder::VisitInc() {
2235 BuildUnaryOp(javascript()->Increment());
2236 }
2237
VisitNegate()2238 void BytecodeGraphBuilder::VisitNegate() {
2239 BuildUnaryOp(javascript()->Negate());
2240 }
2241
VisitAdd()2242 void BytecodeGraphBuilder::VisitAdd() {
2243 BuildBinaryOp(
2244 javascript()->Add(GetBinaryOperationHint(kBinaryOperationHintIndex)));
2245 }
2246
VisitSub()2247 void BytecodeGraphBuilder::VisitSub() {
2248 BuildBinaryOp(javascript()->Subtract());
2249 }
2250
VisitMul()2251 void BytecodeGraphBuilder::VisitMul() {
2252 BuildBinaryOp(javascript()->Multiply());
2253 }
2254
VisitDiv()2255 void BytecodeGraphBuilder::VisitDiv() { BuildBinaryOp(javascript()->Divide()); }
2256
VisitMod()2257 void BytecodeGraphBuilder::VisitMod() {
2258 BuildBinaryOp(javascript()->Modulus());
2259 }
2260
VisitExp()2261 void BytecodeGraphBuilder::VisitExp() {
2262 BuildBinaryOp(javascript()->Exponentiate());
2263 }
2264
VisitBitwiseOr()2265 void BytecodeGraphBuilder::VisitBitwiseOr() {
2266 BuildBinaryOp(javascript()->BitwiseOr());
2267 }
2268
VisitBitwiseXor()2269 void BytecodeGraphBuilder::VisitBitwiseXor() {
2270 BuildBinaryOp(javascript()->BitwiseXor());
2271 }
2272
VisitBitwiseAnd()2273 void BytecodeGraphBuilder::VisitBitwiseAnd() {
2274 BuildBinaryOp(javascript()->BitwiseAnd());
2275 }
2276
VisitShiftLeft()2277 void BytecodeGraphBuilder::VisitShiftLeft() {
2278 BuildBinaryOp(javascript()->ShiftLeft());
2279 }
2280
VisitShiftRight()2281 void BytecodeGraphBuilder::VisitShiftRight() {
2282 BuildBinaryOp(javascript()->ShiftRight());
2283 }
2284
VisitShiftRightLogical()2285 void BytecodeGraphBuilder::VisitShiftRightLogical() {
2286 BuildBinaryOp(javascript()->ShiftRightLogical());
2287 }
2288
BuildBinaryOpWithImmediate(const Operator * op)2289 void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) {
2290 PrepareEagerCheckpoint();
2291 Node* left = environment()->LookupAccumulator();
2292 Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
2293
2294 FeedbackSlot slot =
2295 bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex);
2296 JSTypeHintLowering::LoweringResult lowering =
2297 TryBuildSimplifiedBinaryOp(op, left, right, slot);
2298 if (lowering.IsExit()) return;
2299
2300 Node* node = nullptr;
2301 if (lowering.IsSideEffectFree()) {
2302 node = lowering.value();
2303 } else {
2304 DCHECK(!lowering.Changed());
2305 node = NewNode(op, left, right);
2306 }
2307 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2308 }
2309
VisitAddSmi()2310 void BytecodeGraphBuilder::VisitAddSmi() {
2311 BuildBinaryOpWithImmediate(
2312 javascript()->Add(GetBinaryOperationHint(kBinaryOperationSmiHintIndex)));
2313 }
2314
VisitSubSmi()2315 void BytecodeGraphBuilder::VisitSubSmi() {
2316 BuildBinaryOpWithImmediate(javascript()->Subtract());
2317 }
2318
VisitMulSmi()2319 void BytecodeGraphBuilder::VisitMulSmi() {
2320 BuildBinaryOpWithImmediate(javascript()->Multiply());
2321 }
2322
VisitDivSmi()2323 void BytecodeGraphBuilder::VisitDivSmi() {
2324 BuildBinaryOpWithImmediate(javascript()->Divide());
2325 }
2326
VisitModSmi()2327 void BytecodeGraphBuilder::VisitModSmi() {
2328 BuildBinaryOpWithImmediate(javascript()->Modulus());
2329 }
2330
VisitExpSmi()2331 void BytecodeGraphBuilder::VisitExpSmi() {
2332 BuildBinaryOpWithImmediate(javascript()->Exponentiate());
2333 }
2334
VisitBitwiseOrSmi()2335 void BytecodeGraphBuilder::VisitBitwiseOrSmi() {
2336 BuildBinaryOpWithImmediate(javascript()->BitwiseOr());
2337 }
2338
VisitBitwiseXorSmi()2339 void BytecodeGraphBuilder::VisitBitwiseXorSmi() {
2340 BuildBinaryOpWithImmediate(javascript()->BitwiseXor());
2341 }
2342
VisitBitwiseAndSmi()2343 void BytecodeGraphBuilder::VisitBitwiseAndSmi() {
2344 BuildBinaryOpWithImmediate(javascript()->BitwiseAnd());
2345 }
2346
VisitShiftLeftSmi()2347 void BytecodeGraphBuilder::VisitShiftLeftSmi() {
2348 BuildBinaryOpWithImmediate(javascript()->ShiftLeft());
2349 }
2350
VisitShiftRightSmi()2351 void BytecodeGraphBuilder::VisitShiftRightSmi() {
2352 BuildBinaryOpWithImmediate(javascript()->ShiftRight());
2353 }
2354
VisitShiftRightLogicalSmi()2355 void BytecodeGraphBuilder::VisitShiftRightLogicalSmi() {
2356 BuildBinaryOpWithImmediate(javascript()->ShiftRightLogical());
2357 }
2358
VisitLogicalNot()2359 void BytecodeGraphBuilder::VisitLogicalNot() {
2360 Node* value = environment()->LookupAccumulator();
2361 Node* node = NewNode(simplified()->BooleanNot(), value);
2362 environment()->BindAccumulator(node);
2363 }
2364
VisitToBooleanLogicalNot()2365 void BytecodeGraphBuilder::VisitToBooleanLogicalNot() {
2366 Node* value =
2367 NewNode(simplified()->ToBoolean(), environment()->LookupAccumulator());
2368 Node* node = NewNode(simplified()->BooleanNot(), value);
2369 environment()->BindAccumulator(node);
2370 }
2371
VisitTypeOf()2372 void BytecodeGraphBuilder::VisitTypeOf() {
2373 Node* node =
2374 NewNode(simplified()->TypeOf(), environment()->LookupAccumulator());
2375 environment()->BindAccumulator(node);
2376 }
2377
BuildDelete(LanguageMode language_mode)2378 void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) {
2379 PrepareEagerCheckpoint();
2380 Node* key = environment()->LookupAccumulator();
2381 Node* object =
2382 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2383 Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode));
2384 Node* node = NewNode(javascript()->DeleteProperty(), object, key, mode);
2385 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2386 }
2387
VisitDeletePropertyStrict()2388 void BytecodeGraphBuilder::VisitDeletePropertyStrict() {
2389 BuildDelete(LanguageMode::kStrict);
2390 }
2391
VisitDeletePropertySloppy()2392 void BytecodeGraphBuilder::VisitDeletePropertySloppy() {
2393 BuildDelete(LanguageMode::kSloppy);
2394 }
2395
VisitGetSuperConstructor()2396 void BytecodeGraphBuilder::VisitGetSuperConstructor() {
2397 Node* node = NewNode(javascript()->GetSuperConstructor(),
2398 environment()->LookupAccumulator());
2399 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node,
2400 Environment::kAttachFrameState);
2401 }
2402
BuildCompareOp(const Operator * op)2403 void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) {
2404 PrepareEagerCheckpoint();
2405 Node* left =
2406 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2407 Node* right = environment()->LookupAccumulator();
2408
2409 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
2410 JSTypeHintLowering::LoweringResult lowering =
2411 TryBuildSimplifiedBinaryOp(op, left, right, slot);
2412 if (lowering.IsExit()) return;
2413
2414 Node* node = nullptr;
2415 if (lowering.IsSideEffectFree()) {
2416 node = lowering.value();
2417 } else {
2418 DCHECK(!lowering.Changed());
2419 node = NewNode(op, left, right);
2420 }
2421 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2422 }
2423
VisitTestEqual()2424 void BytecodeGraphBuilder::VisitTestEqual() {
2425 BuildCompareOp(javascript()->Equal(GetCompareOperationHint()));
2426 }
2427
VisitTestEqualStrict()2428 void BytecodeGraphBuilder::VisitTestEqualStrict() {
2429 BuildCompareOp(javascript()->StrictEqual(GetCompareOperationHint()));
2430 }
2431
VisitTestLessThan()2432 void BytecodeGraphBuilder::VisitTestLessThan() {
2433 BuildCompareOp(javascript()->LessThan(GetCompareOperationHint()));
2434 }
2435
VisitTestGreaterThan()2436 void BytecodeGraphBuilder::VisitTestGreaterThan() {
2437 BuildCompareOp(javascript()->GreaterThan(GetCompareOperationHint()));
2438 }
2439
VisitTestLessThanOrEqual()2440 void BytecodeGraphBuilder::VisitTestLessThanOrEqual() {
2441 BuildCompareOp(javascript()->LessThanOrEqual(GetCompareOperationHint()));
2442 }
2443
VisitTestGreaterThanOrEqual()2444 void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() {
2445 BuildCompareOp(javascript()->GreaterThanOrEqual(GetCompareOperationHint()));
2446 }
2447
VisitTestReferenceEqual()2448 void BytecodeGraphBuilder::VisitTestReferenceEqual() {
2449 Node* left =
2450 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2451 Node* right = environment()->LookupAccumulator();
2452 Node* result = NewNode(simplified()->ReferenceEqual(), left, right);
2453 environment()->BindAccumulator(result);
2454 }
2455
VisitTestIn()2456 void BytecodeGraphBuilder::VisitTestIn() {
2457 PrepareEagerCheckpoint();
2458 Node* object = environment()->LookupAccumulator();
2459 Node* key =
2460 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2461 Node* node = NewNode(javascript()->HasProperty(), object, key);
2462 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2463 }
2464
VisitTestInstanceOf()2465 void BytecodeGraphBuilder::VisitTestInstanceOf() {
2466 int const slot_index = bytecode_iterator().GetIndexOperand(1);
2467 BuildCompareOp(javascript()->InstanceOf(CreateVectorSlotPair(slot_index)));
2468 }
2469
VisitTestUndetectable()2470 void BytecodeGraphBuilder::VisitTestUndetectable() {
2471 Node* object = environment()->LookupAccumulator();
2472 Node* node = NewNode(jsgraph()->simplified()->ObjectIsUndetectable(), object);
2473 environment()->BindAccumulator(node);
2474 }
2475
VisitTestNull()2476 void BytecodeGraphBuilder::VisitTestNull() {
2477 Node* object = environment()->LookupAccumulator();
2478 Node* result = NewNode(simplified()->ReferenceEqual(), object,
2479 jsgraph()->NullConstant());
2480 environment()->BindAccumulator(result);
2481 }
2482
VisitTestUndefined()2483 void BytecodeGraphBuilder::VisitTestUndefined() {
2484 Node* object = environment()->LookupAccumulator();
2485 Node* result = NewNode(simplified()->ReferenceEqual(), object,
2486 jsgraph()->UndefinedConstant());
2487 environment()->BindAccumulator(result);
2488 }
2489
VisitTestTypeOf()2490 void BytecodeGraphBuilder::VisitTestTypeOf() {
2491 Node* object = environment()->LookupAccumulator();
2492 auto literal_flag = interpreter::TestTypeOfFlags::Decode(
2493 bytecode_iterator().GetFlagOperand(0));
2494 Node* result;
2495 switch (literal_flag) {
2496 case interpreter::TestTypeOfFlags::LiteralFlag::kNumber:
2497 result = NewNode(simplified()->ObjectIsNumber(), object);
2498 break;
2499 case interpreter::TestTypeOfFlags::LiteralFlag::kString:
2500 result = NewNode(simplified()->ObjectIsString(), object);
2501 break;
2502 case interpreter::TestTypeOfFlags::LiteralFlag::kSymbol:
2503 result = NewNode(simplified()->ObjectIsSymbol(), object);
2504 break;
2505 case interpreter::TestTypeOfFlags::LiteralFlag::kBigInt:
2506 result = NewNode(simplified()->ObjectIsBigInt(), object);
2507 break;
2508 case interpreter::TestTypeOfFlags::LiteralFlag::kBoolean:
2509 result = NewNode(common()->Select(MachineRepresentation::kTagged),
2510 NewNode(simplified()->ReferenceEqual(), object,
2511 jsgraph()->TrueConstant()),
2512 jsgraph()->TrueConstant(),
2513 NewNode(simplified()->ReferenceEqual(), object,
2514 jsgraph()->FalseConstant()));
2515 break;
2516 case interpreter::TestTypeOfFlags::LiteralFlag::kUndefined:
2517 result = graph()->NewNode(
2518 common()->Select(MachineRepresentation::kTagged),
2519 graph()->NewNode(simplified()->ReferenceEqual(), object,
2520 jsgraph()->NullConstant()),
2521 jsgraph()->FalseConstant(),
2522 graph()->NewNode(simplified()->ObjectIsUndetectable(), object));
2523 break;
2524 case interpreter::TestTypeOfFlags::LiteralFlag::kFunction:
2525 result =
2526 graph()->NewNode(simplified()->ObjectIsDetectableCallable(), object);
2527 break;
2528 case interpreter::TestTypeOfFlags::LiteralFlag::kObject:
2529 result = graph()->NewNode(
2530 common()->Select(MachineRepresentation::kTagged),
2531 graph()->NewNode(simplified()->ObjectIsNonCallable(), object),
2532 jsgraph()->TrueConstant(),
2533 graph()->NewNode(simplified()->ReferenceEqual(), object,
2534 jsgraph()->NullConstant()));
2535 break;
2536 case interpreter::TestTypeOfFlags::LiteralFlag::kOther:
2537 UNREACHABLE(); // Should never be emitted.
2538 break;
2539 }
2540 environment()->BindAccumulator(result);
2541 }
2542
BuildCastOperator(const Operator * js_op)2543 void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) {
2544 Node* value = NewNode(js_op, environment()->LookupAccumulator());
2545 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value,
2546 Environment::kAttachFrameState);
2547 }
2548
VisitToName()2549 void BytecodeGraphBuilder::VisitToName() {
2550 BuildCastOperator(javascript()->ToName());
2551 }
2552
VisitToObject()2553 void BytecodeGraphBuilder::VisitToObject() {
2554 BuildCastOperator(javascript()->ToObject());
2555 }
2556
VisitToString()2557 void BytecodeGraphBuilder::VisitToString() {
2558 Node* value =
2559 NewNode(javascript()->ToString(), environment()->LookupAccumulator());
2560 environment()->BindAccumulator(value, Environment::kAttachFrameState);
2561 }
2562
VisitToNumber()2563 void BytecodeGraphBuilder::VisitToNumber() {
2564 PrepareEagerCheckpoint();
2565 Node* object = environment()->LookupAccumulator();
2566
2567 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(0);
2568 JSTypeHintLowering::LoweringResult lowering =
2569 TryBuildSimplifiedToNumber(object, slot);
2570
2571 Node* node = nullptr;
2572 if (lowering.IsSideEffectFree()) {
2573 node = lowering.value();
2574 } else {
2575 DCHECK(!lowering.Changed());
2576 node = NewNode(javascript()->ToNumber(), object);
2577 }
2578
2579 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2580 }
2581
VisitToNumeric()2582 void BytecodeGraphBuilder::VisitToNumeric() {
2583 PrepareEagerCheckpoint();
2584 Node* object = environment()->LookupAccumulator();
2585
2586 // If we have some kind of Number feedback, we do the same lowering as for
2587 // ToNumber.
2588 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(0);
2589 JSTypeHintLowering::LoweringResult lowering =
2590 TryBuildSimplifiedToNumber(object, slot);
2591
2592 Node* node = nullptr;
2593 if (lowering.IsSideEffectFree()) {
2594 node = lowering.value();
2595 } else {
2596 DCHECK(!lowering.Changed());
2597 node = NewNode(javascript()->ToNumeric(), object);
2598 }
2599
2600 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2601 }
2602
VisitJump()2603 void BytecodeGraphBuilder::VisitJump() { BuildJump(); }
2604
VisitJumpConstant()2605 void BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); }
2606
VisitJumpIfTrue()2607 void BytecodeGraphBuilder::VisitJumpIfTrue() { BuildJumpIfTrue(); }
2608
VisitJumpIfTrueConstant()2609 void BytecodeGraphBuilder::VisitJumpIfTrueConstant() { BuildJumpIfTrue(); }
2610
VisitJumpIfFalse()2611 void BytecodeGraphBuilder::VisitJumpIfFalse() { BuildJumpIfFalse(); }
2612
VisitJumpIfFalseConstant()2613 void BytecodeGraphBuilder::VisitJumpIfFalseConstant() { BuildJumpIfFalse(); }
2614
VisitJumpIfToBooleanTrue()2615 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() {
2616 BuildJumpIfToBooleanTrue();
2617 }
2618
VisitJumpIfToBooleanTrueConstant()2619 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() {
2620 BuildJumpIfToBooleanTrue();
2621 }
2622
VisitJumpIfToBooleanFalse()2623 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() {
2624 BuildJumpIfToBooleanFalse();
2625 }
2626
VisitJumpIfToBooleanFalseConstant()2627 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() {
2628 BuildJumpIfToBooleanFalse();
2629 }
2630
VisitJumpIfJSReceiver()2631 void BytecodeGraphBuilder::VisitJumpIfJSReceiver() { BuildJumpIfJSReceiver(); }
2632
VisitJumpIfJSReceiverConstant()2633 void BytecodeGraphBuilder::VisitJumpIfJSReceiverConstant() {
2634 BuildJumpIfJSReceiver();
2635 }
2636
VisitJumpIfNull()2637 void BytecodeGraphBuilder::VisitJumpIfNull() {
2638 BuildJumpIfEqual(jsgraph()->NullConstant());
2639 }
2640
VisitJumpIfNullConstant()2641 void BytecodeGraphBuilder::VisitJumpIfNullConstant() {
2642 BuildJumpIfEqual(jsgraph()->NullConstant());
2643 }
2644
VisitJumpIfNotNull()2645 void BytecodeGraphBuilder::VisitJumpIfNotNull() {
2646 BuildJumpIfNotEqual(jsgraph()->NullConstant());
2647 }
2648
VisitJumpIfNotNullConstant()2649 void BytecodeGraphBuilder::VisitJumpIfNotNullConstant() {
2650 BuildJumpIfNotEqual(jsgraph()->NullConstant());
2651 }
2652
VisitJumpIfUndefined()2653 void BytecodeGraphBuilder::VisitJumpIfUndefined() {
2654 BuildJumpIfEqual(jsgraph()->UndefinedConstant());
2655 }
2656
VisitJumpIfUndefinedConstant()2657 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() {
2658 BuildJumpIfEqual(jsgraph()->UndefinedConstant());
2659 }
2660
VisitJumpIfNotUndefined()2661 void BytecodeGraphBuilder::VisitJumpIfNotUndefined() {
2662 BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
2663 }
2664
VisitJumpIfNotUndefinedConstant()2665 void BytecodeGraphBuilder::VisitJumpIfNotUndefinedConstant() {
2666 BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
2667 }
2668
VisitJumpLoop()2669 void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); }
2670
BuildSwitchOnSmi(Node * condition)2671 void BytecodeGraphBuilder::BuildSwitchOnSmi(Node* condition) {
2672 interpreter::JumpTableTargetOffsets offsets =
2673 bytecode_iterator().GetJumpTableTargetOffsets();
2674
2675 NewSwitch(condition, offsets.size() + 1);
2676 for (const auto& entry : offsets) {
2677 SubEnvironment sub_environment(this);
2678 NewIfValue(entry.case_value);
2679 MergeIntoSuccessorEnvironment(entry.target_offset);
2680 }
2681 NewIfDefault();
2682 }
2683
VisitSwitchOnSmiNoFeedback()2684 void BytecodeGraphBuilder::VisitSwitchOnSmiNoFeedback() {
2685 PrepareEagerCheckpoint();
2686
2687 Node* acc = environment()->LookupAccumulator();
2688 Node* acc_smi = NewNode(simplified()->CheckSmi(VectorSlotPair()), acc);
2689 BuildSwitchOnSmi(acc_smi);
2690 }
2691
VisitStackCheck()2692 void BytecodeGraphBuilder::VisitStackCheck() {
2693 PrepareEagerCheckpoint();
2694 Node* node = NewNode(javascript()->StackCheck());
2695 environment()->RecordAfterState(node, Environment::kAttachFrameState);
2696 }
2697
VisitSetPendingMessage()2698 void BytecodeGraphBuilder::VisitSetPendingMessage() {
2699 Node* previous_message = NewNode(javascript()->LoadMessage());
2700 NewNode(javascript()->StoreMessage(), environment()->LookupAccumulator());
2701 environment()->BindAccumulator(previous_message);
2702 }
2703
BuildReturn(const BytecodeLivenessState * liveness)2704 void BytecodeGraphBuilder::BuildReturn(const BytecodeLivenessState* liveness) {
2705 BuildLoopExitsForFunctionExit(liveness);
2706 Node* pop_node = jsgraph()->ZeroConstant();
2707 Node* control =
2708 NewNode(common()->Return(), pop_node, environment()->LookupAccumulator());
2709 MergeControlToLeaveFunction(control);
2710 }
2711
VisitReturn()2712 void BytecodeGraphBuilder::VisitReturn() {
2713 BuildReturn(bytecode_analysis()->GetInLivenessFor(
2714 bytecode_iterator().current_offset()));
2715 }
2716
VisitDebugger()2717 void BytecodeGraphBuilder::VisitDebugger() {
2718 PrepareEagerCheckpoint();
2719 Node* call = NewNode(javascript()->Debugger());
2720 environment()->RecordAfterState(call, Environment::kAttachFrameState);
2721 }
2722
2723 // We cannot create a graph from the debugger copy of the bytecode array.
2724 #define DEBUG_BREAK(Name, ...) \
2725 void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); }
2726 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
2727 #undef DEBUG_BREAK
2728
VisitIncBlockCounter()2729 void BytecodeGraphBuilder::VisitIncBlockCounter() {
2730 Node* closure = GetFunctionClosure();
2731 Node* coverage_array_slot =
2732 jsgraph()->Constant(bytecode_iterator().GetIndexOperand(0));
2733
2734 const Operator* op = javascript()->CallRuntime(Runtime::kIncBlockCounter);
2735
2736 NewNode(op, closure, coverage_array_slot);
2737 }
2738
VisitForInEnumerate()2739 void BytecodeGraphBuilder::VisitForInEnumerate() {
2740 Node* receiver =
2741 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2742 Node* enumerator = NewNode(javascript()->ForInEnumerate(), receiver);
2743 environment()->BindAccumulator(enumerator, Environment::kAttachFrameState);
2744 }
2745
VisitForInPrepare()2746 void BytecodeGraphBuilder::VisitForInPrepare() {
2747 PrepareEagerCheckpoint();
2748 Node* enumerator = environment()->LookupAccumulator();
2749
2750 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
2751 JSTypeHintLowering::LoweringResult lowering =
2752 TryBuildSimplifiedForInPrepare(enumerator, slot);
2753 if (lowering.IsExit()) return;
2754 DCHECK(!lowering.Changed());
2755 Node* node = NewNode(javascript()->ForInPrepare(GetForInMode(1)), enumerator);
2756 environment()->BindRegistersToProjections(
2757 bytecode_iterator().GetRegisterOperand(0), node);
2758 }
2759
VisitForInContinue()2760 void BytecodeGraphBuilder::VisitForInContinue() {
2761 PrepareEagerCheckpoint();
2762 Node* index =
2763 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2764 Node* cache_length =
2765 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2766 Node* exit_cond = NewNode(simplified()->SpeculativeNumberLessThan(
2767 NumberOperationHint::kSignedSmall),
2768 index, cache_length);
2769 environment()->BindAccumulator(exit_cond);
2770 }
2771
VisitForInNext()2772 void BytecodeGraphBuilder::VisitForInNext() {
2773 PrepareEagerCheckpoint();
2774 Node* receiver =
2775 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2776 Node* index =
2777 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2778 int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index();
2779 Node* cache_type = environment()->LookupRegister(
2780 interpreter::Register(catch_reg_pair_index));
2781 Node* cache_array = environment()->LookupRegister(
2782 interpreter::Register(catch_reg_pair_index + 1));
2783
2784 // We need to rename the {index} here, as in case of OSR we loose the
2785 // information that the {index} is always a valid unsigned Smi value.
2786 index = graph()->NewNode(common()->TypeGuard(Type::UnsignedSmall()), index,
2787 environment()->GetEffectDependency(),
2788 environment()->GetControlDependency());
2789 environment()->UpdateEffectDependency(index);
2790
2791 FeedbackSlot slot = bytecode_iterator().GetSlotOperand(3);
2792 JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedForInNext(
2793 receiver, cache_array, cache_type, index, slot);
2794 if (lowering.IsExit()) return;
2795
2796 DCHECK(!lowering.Changed());
2797 Node* node = NewNode(javascript()->ForInNext(GetForInMode(3)), receiver,
2798 cache_array, cache_type, index);
2799 environment()->BindAccumulator(node, Environment::kAttachFrameState);
2800 }
2801
VisitForInStep()2802 void BytecodeGraphBuilder::VisitForInStep() {
2803 PrepareEagerCheckpoint();
2804 Node* index =
2805 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2806 index = NewNode(simplified()->SpeculativeSafeIntegerAdd(
2807 NumberOperationHint::kSignedSmall),
2808 index, jsgraph()->OneConstant());
2809 environment()->BindAccumulator(index, Environment::kAttachFrameState);
2810 }
2811
VisitSuspendGenerator()2812 void BytecodeGraphBuilder::VisitSuspendGenerator() {
2813 Node* generator = environment()->LookupRegister(
2814 bytecode_iterator().GetRegisterOperand(0));
2815 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
2816 // We assume we are storing a range starting from index 0.
2817 CHECK_EQ(0, first_reg.index());
2818 int register_count =
2819 static_cast<int>(bytecode_iterator().GetRegisterCountOperand(2));
2820 int parameter_count_without_receiver =
2821 bytecode_array()->parameter_count() - 1;
2822
2823 Node* suspend_id = jsgraph()->SmiConstant(
2824 bytecode_iterator().GetUnsignedImmediateOperand(3));
2825
2826 // The offsets used by the bytecode iterator are relative to a different base
2827 // than what is used in the interpreter, hence the addition.
2828 Node* offset =
2829 jsgraph()->Constant(bytecode_iterator().current_offset() +
2830 (BytecodeArray::kHeaderSize - kHeapObjectTag));
2831
2832 const BytecodeLivenessState* liveness = bytecode_analysis()->GetInLivenessFor(
2833 bytecode_iterator().current_offset());
2834
2835 // Maybe overallocate the value list since we don't know how many registers
2836 // are live.
2837 // TODO(leszeks): We could get this count from liveness rather than the
2838 // register list.
2839 int value_input_count = 3 + parameter_count_without_receiver + register_count;
2840
2841 Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count);
2842 value_inputs[0] = generator;
2843 value_inputs[1] = suspend_id;
2844 value_inputs[2] = offset;
2845
2846 int count_written = 0;
2847 // Store the parameters.
2848 for (int i = 0; i < parameter_count_without_receiver; i++) {
2849 value_inputs[3 + count_written++] =
2850 environment()->LookupRegister(interpreter::Register::FromParameterIndex(
2851 i, parameter_count_without_receiver));
2852 }
2853
2854 // Store the registers.
2855 for (int i = 0; i < register_count; ++i) {
2856 if (liveness == nullptr || liveness->RegisterIsLive(i)) {
2857 int index_in_parameters_and_registers =
2858 parameter_count_without_receiver + i;
2859 while (count_written < index_in_parameters_and_registers) {
2860 value_inputs[3 + count_written++] = jsgraph()->OptimizedOutConstant();
2861 }
2862 value_inputs[3 + count_written++] =
2863 environment()->LookupRegister(interpreter::Register(i));
2864 DCHECK_EQ(count_written, index_in_parameters_and_registers + 1);
2865 }
2866 }
2867
2868 // Use the actual written count rather than the register count to create the
2869 // node.
2870 MakeNode(javascript()->GeneratorStore(count_written), 3 + count_written,
2871 value_inputs, false);
2872
2873 // TODO(leszeks): This over-approximates the liveness at exit, only the
2874 // accumulator should be live by this point.
2875 BuildReturn(bytecode_analysis()->GetInLivenessFor(
2876 bytecode_iterator().current_offset()));
2877 }
2878
BuildSwitchOnGeneratorState(const ZoneVector<ResumeJumpTarget> & resume_jump_targets,bool allow_fallthrough_on_executing)2879 void BytecodeGraphBuilder::BuildSwitchOnGeneratorState(
2880 const ZoneVector<ResumeJumpTarget>& resume_jump_targets,
2881 bool allow_fallthrough_on_executing) {
2882 Node* generator_state = environment()->LookupGeneratorState();
2883
2884 int extra_cases = allow_fallthrough_on_executing ? 2 : 1;
2885 NewSwitch(generator_state,
2886 static_cast<int>(resume_jump_targets.size() + extra_cases));
2887 for (const ResumeJumpTarget& target : resume_jump_targets) {
2888 SubEnvironment sub_environment(this);
2889 NewIfValue(target.suspend_id());
2890 if (target.is_leaf()) {
2891 // Mark that we are resuming executing.
2892 environment()->BindGeneratorState(
2893 jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting));
2894 }
2895 // Jump to the target offset, whether it's a loop header or the resume.
2896 MergeIntoSuccessorEnvironment(target.target_offset());
2897 }
2898
2899 {
2900 SubEnvironment sub_environment(this);
2901 // We should never hit the default case (assuming generator state cannot be
2902 // corrupted), so abort if we do.
2903 // TODO(leszeks): Maybe only check this in debug mode, and otherwise use
2904 // the default to represent one of the cases above/fallthrough below?
2905 NewIfDefault();
2906 NewNode(simplified()->RuntimeAbort(AbortReason::kInvalidJumpTableIndex));
2907 // TODO(7099): Investigate if we need LoopExit here.
2908 Node* control = NewNode(common()->Throw());
2909 MergeControlToLeaveFunction(control);
2910 }
2911
2912 if (allow_fallthrough_on_executing) {
2913 // If we are executing (rather than resuming), and we allow it, just fall
2914 // through to the actual loop body.
2915 NewIfValue(JSGeneratorObject::kGeneratorExecuting);
2916 } else {
2917 // Otherwise, this environment is dead.
2918 set_environment(nullptr);
2919 }
2920 }
2921
VisitSwitchOnGeneratorState()2922 void BytecodeGraphBuilder::VisitSwitchOnGeneratorState() {
2923 Node* generator =
2924 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2925
2926 Node* generator_is_undefined =
2927 NewNode(simplified()->ReferenceEqual(), generator,
2928 jsgraph()->UndefinedConstant());
2929
2930 NewBranch(generator_is_undefined);
2931 {
2932 SubEnvironment resume_env(this);
2933 NewIfFalse();
2934
2935 Node* generator_state =
2936 NewNode(javascript()->GeneratorRestoreContinuation(), generator);
2937 environment()->BindGeneratorState(generator_state);
2938
2939 Node* generator_context =
2940 NewNode(javascript()->GeneratorRestoreContext(), generator);
2941 environment()->SetContext(generator_context);
2942
2943 BuildSwitchOnGeneratorState(bytecode_analysis()->resume_jump_targets(),
2944 false);
2945 }
2946
2947 // Fallthrough for the first-call case.
2948 NewIfTrue();
2949 }
2950
VisitResumeGenerator()2951 void BytecodeGraphBuilder::VisitResumeGenerator() {
2952 Node* generator =
2953 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2954 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
2955 // We assume we are restoring registers starting fromm index 0.
2956 CHECK_EQ(0, first_reg.index());
2957
2958 const BytecodeLivenessState* liveness =
2959 bytecode_analysis()->GetOutLivenessFor(
2960 bytecode_iterator().current_offset());
2961
2962 int parameter_count_without_receiver =
2963 bytecode_array()->parameter_count() - 1;
2964
2965 // Mapping between registers and array indices must match that used in
2966 // InterpreterAssembler::ExportParametersAndRegisterFile.
2967 for (int i = 0; i < environment()->register_count(); ++i) {
2968 if (liveness == nullptr || liveness->RegisterIsLive(i)) {
2969 Node* value = NewNode(javascript()->GeneratorRestoreRegister(
2970 parameter_count_without_receiver + i),
2971 generator);
2972 environment()->BindRegister(interpreter::Register(i), value);
2973 }
2974 }
2975
2976 // Update the accumulator with the generator's input_or_debug_pos.
2977 Node* input_or_debug_pos =
2978 NewNode(javascript()->GeneratorRestoreInputOrDebugPos(), generator);
2979 environment()->BindAccumulator(input_or_debug_pos);
2980 }
2981
VisitWide()2982 void BytecodeGraphBuilder::VisitWide() {
2983 // Consumed by the BytecodeArrayIterator.
2984 UNREACHABLE();
2985 }
2986
VisitExtraWide()2987 void BytecodeGraphBuilder::VisitExtraWide() {
2988 // Consumed by the BytecodeArrayIterator.
2989 UNREACHABLE();
2990 }
2991
VisitIllegal()2992 void BytecodeGraphBuilder::VisitIllegal() {
2993 // Not emitted in valid bytecode.
2994 UNREACHABLE();
2995 }
2996
SwitchToMergeEnvironment(int current_offset)2997 void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) {
2998 auto it = merge_environments_.find(current_offset);
2999 if (it != merge_environments_.end()) {
3000 mark_as_needing_eager_checkpoint(true);
3001 if (environment() != nullptr) {
3002 it->second->Merge(environment(),
3003 bytecode_analysis()->GetInLivenessFor(current_offset));
3004 }
3005 set_environment(it->second);
3006 }
3007 }
3008
BuildLoopHeaderEnvironment(int current_offset)3009 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) {
3010 if (bytecode_analysis()->IsLoopHeader(current_offset)) {
3011 mark_as_needing_eager_checkpoint(true);
3012 const LoopInfo& loop_info =
3013 bytecode_analysis()->GetLoopInfoFor(current_offset);
3014 const BytecodeLivenessState* liveness =
3015 bytecode_analysis()->GetInLivenessFor(current_offset);
3016
3017 const auto& resume_jump_targets = loop_info.resume_jump_targets();
3018 bool generate_suspend_switch = !resume_jump_targets.empty();
3019
3020 // Add loop header.
3021 environment()->PrepareForLoop(loop_info.assignments(), liveness);
3022
3023 // Store a copy of the environment so we can connect merged back edge inputs
3024 // to the loop header.
3025 merge_environments_[current_offset] = environment()->Copy();
3026
3027 // If this loop contains resumes, create a new switch just after the loop
3028 // for those resumes.
3029 if (generate_suspend_switch) {
3030 BuildSwitchOnGeneratorState(loop_info.resume_jump_targets(), true);
3031
3032 // TODO(leszeks): At this point we know we are executing rather than
3033 // resuming, so we should be able to prune off the phis in the environment
3034 // related to the resume path.
3035
3036 // Set the generator state to a known constant.
3037 environment()->BindGeneratorState(
3038 jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting));
3039 }
3040 }
3041 }
3042
MergeIntoSuccessorEnvironment(int target_offset)3043 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) {
3044 BuildLoopExitsForBranch(target_offset);
3045 Environment*& merge_environment = merge_environments_[target_offset];
3046
3047 if (merge_environment == nullptr) {
3048 // Append merge nodes to the environment. We may merge here with another
3049 // environment. So add a place holder for merge nodes. We may add redundant
3050 // but will be eliminated in a later pass.
3051 // TODO(mstarzinger): Be smarter about this!
3052 NewMerge();
3053 merge_environment = environment();
3054 } else {
3055 // Merge any values which are live coming into the successor.
3056 merge_environment->Merge(
3057 environment(), bytecode_analysis()->GetInLivenessFor(target_offset));
3058 }
3059 set_environment(nullptr);
3060 }
3061
MergeControlToLeaveFunction(Node * exit)3062 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) {
3063 exit_controls_.push_back(exit);
3064 set_environment(nullptr);
3065 }
3066
BuildLoopExitsForBranch(int target_offset)3067 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) {
3068 int origin_offset = bytecode_iterator().current_offset();
3069 // Only build loop exits for forward edges.
3070 if (target_offset > origin_offset) {
3071 BuildLoopExitsUntilLoop(
3072 bytecode_analysis()->GetLoopOffsetFor(target_offset),
3073 bytecode_analysis()->GetInLivenessFor(target_offset));
3074 }
3075 }
3076
BuildLoopExitsUntilLoop(int loop_offset,const BytecodeLivenessState * liveness)3077 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(
3078 int loop_offset, const BytecodeLivenessState* liveness) {
3079 int origin_offset = bytecode_iterator().current_offset();
3080 int current_loop = bytecode_analysis()->GetLoopOffsetFor(origin_offset);
3081 // The limit_offset is the stop offset for building loop exists, used for OSR.
3082 // It prevents the creations of loopexits for loops which do not exist.
3083 loop_offset = std::max(loop_offset, currently_peeled_loop_offset_);
3084
3085 while (loop_offset < current_loop) {
3086 Node* loop_node = merge_environments_[current_loop]->GetControlDependency();
3087 const LoopInfo& loop_info =
3088 bytecode_analysis()->GetLoopInfoFor(current_loop);
3089 environment()->PrepareForLoopExit(loop_node, loop_info.assignments(),
3090 liveness);
3091 current_loop = loop_info.parent_offset();
3092 }
3093 }
3094
BuildLoopExitsForFunctionExit(const BytecodeLivenessState * liveness)3095 void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit(
3096 const BytecodeLivenessState* liveness) {
3097 BuildLoopExitsUntilLoop(-1, liveness);
3098 }
3099
BuildJump()3100 void BytecodeGraphBuilder::BuildJump() {
3101 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
3102 }
3103
BuildJumpIf(Node * condition)3104 void BytecodeGraphBuilder::BuildJumpIf(Node* condition) {
3105 NewBranch(condition, BranchHint::kNone, IsSafetyCheck::kNoSafetyCheck);
3106 {
3107 SubEnvironment sub_environment(this);
3108 NewIfTrue();
3109 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
3110 }
3111 NewIfFalse();
3112 }
3113
BuildJumpIfNot(Node * condition)3114 void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) {
3115 NewBranch(condition, BranchHint::kNone, IsSafetyCheck::kNoSafetyCheck);
3116 {
3117 SubEnvironment sub_environment(this);
3118 NewIfFalse();
3119 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
3120 }
3121 NewIfTrue();
3122 }
3123
BuildJumpIfEqual(Node * comperand)3124 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
3125 Node* accumulator = environment()->LookupAccumulator();
3126 Node* condition =
3127 NewNode(simplified()->ReferenceEqual(), accumulator, comperand);
3128 BuildJumpIf(condition);
3129 }
3130
BuildJumpIfNotEqual(Node * comperand)3131 void BytecodeGraphBuilder::BuildJumpIfNotEqual(Node* comperand) {
3132 Node* accumulator = environment()->LookupAccumulator();
3133 Node* condition =
3134 NewNode(simplified()->ReferenceEqual(), accumulator, comperand);
3135 BuildJumpIfNot(condition);
3136 }
3137
BuildJumpIfFalse()3138 void BytecodeGraphBuilder::BuildJumpIfFalse() {
3139 NewBranch(environment()->LookupAccumulator(), BranchHint::kNone,
3140 IsSafetyCheck::kNoSafetyCheck);
3141 {
3142 SubEnvironment sub_environment(this);
3143 NewIfFalse();
3144 environment()->BindAccumulator(jsgraph()->FalseConstant());
3145 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
3146 }
3147 NewIfTrue();
3148 environment()->BindAccumulator(jsgraph()->TrueConstant());
3149 }
3150
BuildJumpIfTrue()3151 void BytecodeGraphBuilder::BuildJumpIfTrue() {
3152 NewBranch(environment()->LookupAccumulator(), BranchHint::kNone,
3153 IsSafetyCheck::kNoSafetyCheck);
3154 {
3155 SubEnvironment sub_environment(this);
3156 NewIfTrue();
3157 environment()->BindAccumulator(jsgraph()->TrueConstant());
3158 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
3159 }
3160 NewIfFalse();
3161 environment()->BindAccumulator(jsgraph()->FalseConstant());
3162 }
3163
BuildJumpIfToBooleanTrue()3164 void BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() {
3165 Node* accumulator = environment()->LookupAccumulator();
3166 Node* condition = NewNode(simplified()->ToBoolean(), accumulator);
3167 BuildJumpIf(condition);
3168 }
3169
BuildJumpIfToBooleanFalse()3170 void BytecodeGraphBuilder::BuildJumpIfToBooleanFalse() {
3171 Node* accumulator = environment()->LookupAccumulator();
3172 Node* condition = NewNode(simplified()->ToBoolean(), accumulator);
3173 BuildJumpIfNot(condition);
3174 }
3175
BuildJumpIfNotHole()3176 void BytecodeGraphBuilder::BuildJumpIfNotHole() {
3177 Node* accumulator = environment()->LookupAccumulator();
3178 Node* condition = NewNode(simplified()->ReferenceEqual(), accumulator,
3179 jsgraph()->TheHoleConstant());
3180 BuildJumpIfNot(condition);
3181 }
3182
BuildJumpIfJSReceiver()3183 void BytecodeGraphBuilder::BuildJumpIfJSReceiver() {
3184 Node* accumulator = environment()->LookupAccumulator();
3185 Node* condition = NewNode(simplified()->ObjectIsReceiver(), accumulator);
3186 BuildJumpIf(condition);
3187 }
3188
3189 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedUnaryOp(const Operator * op,Node * operand,FeedbackSlot slot)3190 BytecodeGraphBuilder::TryBuildSimplifiedUnaryOp(const Operator* op,
3191 Node* operand,
3192 FeedbackSlot slot) {
3193 Node* effect = environment()->GetEffectDependency();
3194 Node* control = environment()->GetControlDependency();
3195 JSTypeHintLowering::LoweringResult result =
3196 type_hint_lowering().ReduceUnaryOperation(op, operand, effect, control,
3197 slot);
3198 ApplyEarlyReduction(result);
3199 return result;
3200 }
3201
3202 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedBinaryOp(const Operator * op,Node * left,Node * right,FeedbackSlot slot)3203 BytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op, Node* left,
3204 Node* right,
3205 FeedbackSlot slot) {
3206 Node* effect = environment()->GetEffectDependency();
3207 Node* control = environment()->GetControlDependency();
3208 JSTypeHintLowering::LoweringResult result =
3209 type_hint_lowering().ReduceBinaryOperation(op, left, right, effect,
3210 control, slot);
3211 ApplyEarlyReduction(result);
3212 return result;
3213 }
3214
3215 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedForInNext(Node * receiver,Node * cache_array,Node * cache_type,Node * index,FeedbackSlot slot)3216 BytecodeGraphBuilder::TryBuildSimplifiedForInNext(Node* receiver,
3217 Node* cache_array,
3218 Node* cache_type, Node* index,
3219 FeedbackSlot slot) {
3220 Node* effect = environment()->GetEffectDependency();
3221 Node* control = environment()->GetControlDependency();
3222 JSTypeHintLowering::LoweringResult result =
3223 type_hint_lowering().ReduceForInNextOperation(
3224 receiver, cache_array, cache_type, index, effect, control, slot);
3225 ApplyEarlyReduction(result);
3226 return result;
3227 }
3228
3229 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedForInPrepare(Node * enumerator,FeedbackSlot slot)3230 BytecodeGraphBuilder::TryBuildSimplifiedForInPrepare(Node* enumerator,
3231 FeedbackSlot slot) {
3232 Node* effect = environment()->GetEffectDependency();
3233 Node* control = environment()->GetControlDependency();
3234 JSTypeHintLowering::LoweringResult result =
3235 type_hint_lowering().ReduceForInPrepareOperation(enumerator, effect,
3236 control, slot);
3237 ApplyEarlyReduction(result);
3238 return result;
3239 }
3240
3241 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedToNumber(Node * value,FeedbackSlot slot)3242 BytecodeGraphBuilder::TryBuildSimplifiedToNumber(Node* value,
3243 FeedbackSlot slot) {
3244 Node* effect = environment()->GetEffectDependency();
3245 Node* control = environment()->GetControlDependency();
3246 JSTypeHintLowering::LoweringResult result =
3247 type_hint_lowering().ReduceToNumberOperation(value, effect, control,
3248 slot);
3249 ApplyEarlyReduction(result);
3250 return result;
3251 }
3252
TryBuildSimplifiedCall(const Operator * op,Node * const * args,int arg_count,FeedbackSlot slot)3253 JSTypeHintLowering::LoweringResult BytecodeGraphBuilder::TryBuildSimplifiedCall(
3254 const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot) {
3255 Node* effect = environment()->GetEffectDependency();
3256 Node* control = environment()->GetControlDependency();
3257 JSTypeHintLowering::LoweringResult result =
3258 type_hint_lowering().ReduceCallOperation(op, args, arg_count, effect,
3259 control, slot);
3260 ApplyEarlyReduction(result);
3261 return result;
3262 }
3263
3264 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedConstruct(const Operator * op,Node * const * args,int arg_count,FeedbackSlot slot)3265 BytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op,
3266 Node* const* args,
3267 int arg_count,
3268 FeedbackSlot slot) {
3269 Node* effect = environment()->GetEffectDependency();
3270 Node* control = environment()->GetControlDependency();
3271 JSTypeHintLowering::LoweringResult result =
3272 type_hint_lowering().ReduceConstructOperation(op, args, arg_count, effect,
3273 control, slot);
3274 ApplyEarlyReduction(result);
3275 return result;
3276 }
3277
3278 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedLoadNamed(const Operator * op,Node * receiver,FeedbackSlot slot)3279 BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op,
3280 Node* receiver,
3281 FeedbackSlot slot) {
3282 Node* effect = environment()->GetEffectDependency();
3283 Node* control = environment()->GetControlDependency();
3284 JSTypeHintLowering::LoweringResult early_reduction =
3285 type_hint_lowering().ReduceLoadNamedOperation(op, receiver, effect,
3286 control, slot);
3287 ApplyEarlyReduction(early_reduction);
3288 return early_reduction;
3289 }
3290
3291 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedLoadKeyed(const Operator * op,Node * receiver,Node * key,FeedbackSlot slot)3292 BytecodeGraphBuilder::TryBuildSimplifiedLoadKeyed(const Operator* op,
3293 Node* receiver, Node* key,
3294 FeedbackSlot slot) {
3295 Node* effect = environment()->GetEffectDependency();
3296 Node* control = environment()->GetControlDependency();
3297 JSTypeHintLowering::LoweringResult result =
3298 type_hint_lowering().ReduceLoadKeyedOperation(op, receiver, key, effect,
3299 control, slot);
3300 ApplyEarlyReduction(result);
3301 return result;
3302 }
3303
3304 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedStoreNamed(const Operator * op,Node * receiver,Node * value,FeedbackSlot slot)3305 BytecodeGraphBuilder::TryBuildSimplifiedStoreNamed(const Operator* op,
3306 Node* receiver, Node* value,
3307 FeedbackSlot slot) {
3308 Node* effect = environment()->GetEffectDependency();
3309 Node* control = environment()->GetControlDependency();
3310 JSTypeHintLowering::LoweringResult result =
3311 type_hint_lowering().ReduceStoreNamedOperation(op, receiver, value,
3312 effect, control, slot);
3313 ApplyEarlyReduction(result);
3314 return result;
3315 }
3316
3317 JSTypeHintLowering::LoweringResult
TryBuildSimplifiedStoreKeyed(const Operator * op,Node * receiver,Node * key,Node * value,FeedbackSlot slot)3318 BytecodeGraphBuilder::TryBuildSimplifiedStoreKeyed(const Operator* op,
3319 Node* receiver, Node* key,
3320 Node* value,
3321 FeedbackSlot slot) {
3322 Node* effect = environment()->GetEffectDependency();
3323 Node* control = environment()->GetControlDependency();
3324 JSTypeHintLowering::LoweringResult result =
3325 type_hint_lowering().ReduceStoreKeyedOperation(op, receiver, key, value,
3326 effect, control, slot);
3327 ApplyEarlyReduction(result);
3328 return result;
3329 }
3330
ApplyEarlyReduction(JSTypeHintLowering::LoweringResult reduction)3331 void BytecodeGraphBuilder::ApplyEarlyReduction(
3332 JSTypeHintLowering::LoweringResult reduction) {
3333 if (reduction.IsExit()) {
3334 MergeControlToLeaveFunction(reduction.control());
3335 } else if (reduction.IsSideEffectFree()) {
3336 environment()->UpdateEffectDependency(reduction.effect());
3337 environment()->UpdateControlDependency(reduction.control());
3338 } else {
3339 DCHECK(!reduction.Changed());
3340 // At the moment, we assume side-effect free reduction. To support
3341 // side-effects, we would have to invalidate the eager checkpoint,
3342 // so that deoptimization does not repeat the side effect.
3343 }
3344 }
3345
EnsureInputBufferSize(int size)3346 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
3347 if (size > input_buffer_size_) {
3348 size = size + kInputBufferSizeIncrement + input_buffer_size_;
3349 input_buffer_ = local_zone()->NewArray<Node*>(size);
3350 input_buffer_size_ = size;
3351 }
3352 return input_buffer_;
3353 }
3354
ExitThenEnterExceptionHandlers(int current_offset)3355 void BytecodeGraphBuilder::ExitThenEnterExceptionHandlers(int current_offset) {
3356 HandlerTable table(*bytecode_array());
3357
3358 // Potentially exit exception handlers.
3359 while (!exception_handlers_.empty()) {
3360 int current_end = exception_handlers_.top().end_offset_;
3361 if (current_offset < current_end) break; // Still covered by range.
3362 exception_handlers_.pop();
3363 }
3364
3365 // Potentially enter exception handlers.
3366 int num_entries = table.NumberOfRangeEntries();
3367 while (current_exception_handler_ < num_entries) {
3368 int next_start = table.GetRangeStart(current_exception_handler_);
3369 if (current_offset < next_start) break; // Not yet covered by range.
3370 int next_end = table.GetRangeEnd(current_exception_handler_);
3371 int next_handler = table.GetRangeHandler(current_exception_handler_);
3372 int context_register = table.GetRangeData(current_exception_handler_);
3373 exception_handlers_.push(
3374 {next_start, next_end, next_handler, context_register});
3375 current_exception_handler_++;
3376 }
3377 }
3378
MakeNode(const Operator * op,int value_input_count,Node * const * value_inputs,bool incomplete)3379 Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
3380 Node* const* value_inputs,
3381 bool incomplete) {
3382 DCHECK_EQ(op->ValueInputCount(), value_input_count);
3383
3384 bool has_context = OperatorProperties::HasContextInput(op);
3385 bool has_frame_state = OperatorProperties::HasFrameStateInput(op);
3386 bool has_control = op->ControlInputCount() == 1;
3387 bool has_effect = op->EffectInputCount() == 1;
3388
3389 DCHECK_LT(op->ControlInputCount(), 2);
3390 DCHECK_LT(op->EffectInputCount(), 2);
3391
3392 Node* result = nullptr;
3393 if (!has_context && !has_frame_state && !has_control && !has_effect) {
3394 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
3395 } else {
3396 bool inside_handler = !exception_handlers_.empty();
3397 int input_count_with_deps = value_input_count;
3398 if (has_context) ++input_count_with_deps;
3399 if (has_frame_state) ++input_count_with_deps;
3400 if (has_control) ++input_count_with_deps;
3401 if (has_effect) ++input_count_with_deps;
3402 Node** buffer = EnsureInputBufferSize(input_count_with_deps);
3403 memcpy(buffer, value_inputs, kPointerSize * value_input_count);
3404 Node** current_input = buffer + value_input_count;
3405 if (has_context) {
3406 *current_input++ = environment()->Context();
3407 }
3408 if (has_frame_state) {
3409 // The frame state will be inserted later. Here we misuse the {Dead} node
3410 // as a sentinel to be later overwritten with the real frame state by the
3411 // calls to {PrepareFrameState} within individual visitor methods.
3412 *current_input++ = jsgraph()->Dead();
3413 }
3414 if (has_effect) {
3415 *current_input++ = environment()->GetEffectDependency();
3416 }
3417 if (has_control) {
3418 *current_input++ = environment()->GetControlDependency();
3419 }
3420 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
3421 // Update the current control dependency for control-producing nodes.
3422 if (result->op()->ControlOutputCount() > 0) {
3423 environment()->UpdateControlDependency(result);
3424 }
3425 // Update the current effect dependency for effect-producing nodes.
3426 if (result->op()->EffectOutputCount() > 0) {
3427 environment()->UpdateEffectDependency(result);
3428 }
3429 // Add implicit exception continuation for throwing nodes.
3430 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
3431 int handler_offset = exception_handlers_.top().handler_offset_;
3432 int context_index = exception_handlers_.top().context_register_;
3433 interpreter::Register context_register(context_index);
3434 Environment* success_env = environment()->Copy();
3435 const Operator* op = common()->IfException();
3436 Node* effect = environment()->GetEffectDependency();
3437 Node* on_exception = graph()->NewNode(op, effect, result);
3438 Node* context = environment()->LookupRegister(context_register);
3439 environment()->UpdateControlDependency(on_exception);
3440 environment()->UpdateEffectDependency(on_exception);
3441 environment()->BindAccumulator(on_exception);
3442 environment()->SetContext(context);
3443 MergeIntoSuccessorEnvironment(handler_offset);
3444 set_environment(success_env);
3445 }
3446 // Add implicit success continuation for throwing nodes.
3447 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
3448 const Operator* if_success = common()->IfSuccess();
3449 Node* on_success = graph()->NewNode(if_success, result);
3450 environment()->UpdateControlDependency(on_success);
3451 }
3452 // Ensure checkpoints are created after operations with side-effects.
3453 if (has_effect && !result->op()->HasProperty(Operator::kNoWrite)) {
3454 mark_as_needing_eager_checkpoint(true);
3455 }
3456 }
3457
3458 return result;
3459 }
3460
3461
NewPhi(int count,Node * input,Node * control)3462 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) {
3463 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
3464 Node** buffer = EnsureInputBufferSize(count + 1);
3465 MemsetPointer(buffer, input, count);
3466 buffer[count] = control;
3467 return graph()->NewNode(phi_op, count + 1, buffer, true);
3468 }
3469
NewEffectPhi(int count,Node * input,Node * control)3470 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input,
3471 Node* control) {
3472 const Operator* phi_op = common()->EffectPhi(count);
3473 Node** buffer = EnsureInputBufferSize(count + 1);
3474 MemsetPointer(buffer, input, count);
3475 buffer[count] = control;
3476 return graph()->NewNode(phi_op, count + 1, buffer, true);
3477 }
3478
3479
MergeControl(Node * control,Node * other)3480 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
3481 int inputs = control->op()->ControlInputCount() + 1;
3482 if (control->opcode() == IrOpcode::kLoop) {
3483 // Control node for loop exists, add input.
3484 const Operator* op = common()->Loop(inputs);
3485 control->AppendInput(graph_zone(), other);
3486 NodeProperties::ChangeOp(control, op);
3487 } else if (control->opcode() == IrOpcode::kMerge) {
3488 // Control node for merge exists, add input.
3489 const Operator* op = common()->Merge(inputs);
3490 control->AppendInput(graph_zone(), other);
3491 NodeProperties::ChangeOp(control, op);
3492 } else {
3493 // Control node is a singleton, introduce a merge.
3494 const Operator* op = common()->Merge(inputs);
3495 Node* merge_inputs[] = {control, other};
3496 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true);
3497 }
3498 return control;
3499 }
3500
MergeEffect(Node * value,Node * other,Node * control)3501 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
3502 Node* control) {
3503 int inputs = control->op()->ControlInputCount();
3504 if (value->opcode() == IrOpcode::kEffectPhi &&
3505 NodeProperties::GetControlInput(value) == control) {
3506 // Phi already exists, add input.
3507 value->InsertInput(graph_zone(), inputs - 1, other);
3508 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
3509 } else if (value != other) {
3510 // Phi does not exist yet, introduce one.
3511 value = NewEffectPhi(inputs, value, control);
3512 value->ReplaceInput(inputs - 1, other);
3513 }
3514 return value;
3515 }
3516
MergeValue(Node * value,Node * other,Node * control)3517 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
3518 Node* control) {
3519 int inputs = control->op()->ControlInputCount();
3520 if (value->opcode() == IrOpcode::kPhi &&
3521 NodeProperties::GetControlInput(value) == control) {
3522 // Phi already exists, add input.
3523 value->InsertInput(graph_zone(), inputs - 1, other);
3524 NodeProperties::ChangeOp(
3525 value, common()->Phi(MachineRepresentation::kTagged, inputs));
3526 } else if (value != other) {
3527 // Phi does not exist yet, introduce one.
3528 value = NewPhi(inputs, value, control);
3529 value->ReplaceInput(inputs - 1, other);
3530 }
3531 return value;
3532 }
3533
UpdateSourcePosition(SourcePositionTableIterator * it,int offset)3534 void BytecodeGraphBuilder::UpdateSourcePosition(SourcePositionTableIterator* it,
3535 int offset) {
3536 if (it->done()) return;
3537 if (it->code_offset() == offset) {
3538 source_positions_->SetCurrentPosition(SourcePosition(
3539 it->source_position().ScriptOffset(), start_position_.InliningId()));
3540 it->Advance();
3541 } else {
3542 DCHECK_GT(it->code_offset(), offset);
3543 }
3544 }
3545
3546 } // namespace compiler
3547 } // namespace internal
3548 } // namespace v8
3549