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