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