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/compiler/bytecode-branch-analysis.h"
8 #include "src/compiler/linkage.h"
9 #include "src/compiler/operator-properties.h"
10 #include "src/interpreter/bytecodes.h"
11
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15
16 // The abstract execution environment simulates the content of the interpreter
17 // register file. The environment performs SSA-renaming of all tracked nodes at
18 // split and merge points in the control flow.
19 class BytecodeGraphBuilder::Environment : public ZoneObject {
20 public:
21 Environment(BytecodeGraphBuilder* builder, int register_count,
22 int parameter_count, Node* control_dependency, Node* context);
23
parameter_count() const24 int parameter_count() const { return parameter_count_; }
register_count() const25 int register_count() const { return register_count_; }
26
27 Node* LookupAccumulator() const;
28 Node* LookupRegister(interpreter::Register the_register) const;
29
30 void BindAccumulator(Node* node, FrameStateBeforeAndAfter* states = nullptr);
31 void BindRegister(interpreter::Register the_register, Node* node,
32 FrameStateBeforeAndAfter* states = nullptr);
33 void BindRegistersToProjections(interpreter::Register first_reg, Node* node,
34 FrameStateBeforeAndAfter* states = nullptr);
35 void RecordAfterState(Node* node, FrameStateBeforeAndAfter* states);
36
37 // Effect dependency tracked by this environment.
GetEffectDependency()38 Node* GetEffectDependency() { return effect_dependency_; }
UpdateEffectDependency(Node * dependency)39 void UpdateEffectDependency(Node* dependency) {
40 effect_dependency_ = dependency;
41 }
42
43 // Preserve a checkpoint of the environment for the IR graph. Any
44 // further mutation of the environment will not affect checkpoints.
45 Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine);
46
47 // Returns true if the state values are up to date with the current
48 // environment.
49 bool StateValuesAreUpToDate(int output_poke_offset, int output_poke_count);
50
51 // Control dependency tracked by this environment.
GetControlDependency() const52 Node* GetControlDependency() const { return control_dependency_; }
UpdateControlDependency(Node * dependency)53 void UpdateControlDependency(Node* dependency) {
54 control_dependency_ = dependency;
55 }
56
Context() const57 Node* Context() const { return context_; }
SetContext(Node * new_context)58 void SetContext(Node* new_context) { context_ = new_context; }
59
60 Environment* CopyForConditional() const;
61 Environment* CopyForLoop();
62 void Merge(Environment* other);
63
64 private:
65 explicit Environment(const Environment* copy);
66 void PrepareForLoop();
67 bool StateValuesAreUpToDate(Node** state_values, int offset, int count,
68 int output_poke_start, int output_poke_end);
69 bool StateValuesRequireUpdate(Node** state_values, int offset, int count);
70 void UpdateStateValues(Node** state_values, int offset, int count);
71
72 int RegisterToValuesIndex(interpreter::Register the_register) const;
73
zone() const74 Zone* zone() const { return builder_->local_zone(); }
graph() const75 Graph* graph() const { return builder_->graph(); }
common() const76 CommonOperatorBuilder* common() const { return builder_->common(); }
builder() const77 BytecodeGraphBuilder* builder() const { return builder_; }
values() const78 const NodeVector* values() const { return &values_; }
values()79 NodeVector* values() { return &values_; }
register_base() const80 int register_base() const { return register_base_; }
accumulator_base() const81 int accumulator_base() const { return accumulator_base_; }
82
83 BytecodeGraphBuilder* builder_;
84 int register_count_;
85 int parameter_count_;
86 Node* context_;
87 Node* control_dependency_;
88 Node* effect_dependency_;
89 NodeVector values_;
90 Node* parameters_state_values_;
91 Node* registers_state_values_;
92 Node* accumulator_state_values_;
93 int register_base_;
94 int accumulator_base_;
95 };
96
97 // Helper for generating frame states for before and after a bytecode.
98 class BytecodeGraphBuilder::FrameStateBeforeAndAfter {
99 public:
FrameStateBeforeAndAfter(BytecodeGraphBuilder * builder)100 explicit FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder)
101 : builder_(builder),
102 id_after_(BailoutId::None()),
103 added_to_node_(false),
104 frame_states_unused_(false),
105 output_poke_offset_(0),
106 output_poke_count_(0) {
107 BailoutId id_before(builder->bytecode_iterator().current_offset());
108 frame_state_before_ = builder_->environment()->Checkpoint(
109 id_before, OutputFrameStateCombine::Ignore());
110 id_after_ = BailoutId(id_before.ToInt() +
111 builder->bytecode_iterator().current_bytecode_size());
112 // Create an explicit checkpoint node for before the operation.
113 Node* node = builder_->NewNode(builder_->common()->Checkpoint());
114 DCHECK_EQ(IrOpcode::kDead,
115 NodeProperties::GetFrameStateInput(node, 0)->opcode());
116 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_before_);
117 }
118
~FrameStateBeforeAndAfter()119 ~FrameStateBeforeAndAfter() {
120 DCHECK(added_to_node_);
121 DCHECK(frame_states_unused_ ||
122 builder_->environment()->StateValuesAreUpToDate(output_poke_offset_,
123 output_poke_count_));
124 }
125
126 private:
127 friend class Environment;
128
AddToNode(Node * node,OutputFrameStateCombine combine)129 void AddToNode(Node* node, OutputFrameStateCombine combine) {
130 DCHECK(!added_to_node_);
131 int count = OperatorProperties::GetFrameStateInputCount(node->op());
132 DCHECK_LE(count, 2);
133 if (count >= 1) {
134 // Add the frame state for after the operation.
135 DCHECK_EQ(IrOpcode::kDead,
136 NodeProperties::GetFrameStateInput(node, 0)->opcode());
137 Node* frame_state_after =
138 builder_->environment()->Checkpoint(id_after_, combine);
139 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after);
140 }
141
142 if (count >= 2) {
143 // Add the frame state for before the operation.
144 // TODO(mstarzinger): Get rid of frame state input before!
145 DCHECK_EQ(IrOpcode::kDead,
146 NodeProperties::GetFrameStateInput(node, 1)->opcode());
147 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
148 }
149
150 if (!combine.IsOutputIgnored()) {
151 output_poke_offset_ = static_cast<int>(combine.GetOffsetToPokeAt());
152 output_poke_count_ = node->op()->ValueOutputCount();
153 }
154 frame_states_unused_ = count == 0;
155 added_to_node_ = true;
156 }
157
158 BytecodeGraphBuilder* builder_;
159 Node* frame_state_before_;
160 BailoutId id_after_;
161
162 bool added_to_node_;
163 bool frame_states_unused_;
164 int output_poke_offset_;
165 int output_poke_count_;
166 };
167
168
169 // Issues:
170 // - Scopes - intimately tied to AST. Need to eval what is needed.
171 // - Need to resolve closure parameter treatment.
Environment(BytecodeGraphBuilder * builder,int register_count,int parameter_count,Node * control_dependency,Node * context)172 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder,
173 int register_count,
174 int parameter_count,
175 Node* control_dependency,
176 Node* context)
177 : builder_(builder),
178 register_count_(register_count),
179 parameter_count_(parameter_count),
180 context_(context),
181 control_dependency_(control_dependency),
182 effect_dependency_(control_dependency),
183 values_(builder->local_zone()),
184 parameters_state_values_(nullptr),
185 registers_state_values_(nullptr),
186 accumulator_state_values_(nullptr) {
187 // The layout of values_ is:
188 //
189 // [receiver] [parameters] [registers] [accumulator]
190 //
191 // parameter[0] is the receiver (this), parameters 1..N are the
192 // parameters supplied to the method (arg0..argN-1). The accumulator
193 // is stored separately.
194
195 // Parameters including the receiver
196 for (int i = 0; i < parameter_count; i++) {
197 const char* debug_name = (i == 0) ? "%this" : nullptr;
198 const Operator* op = common()->Parameter(i, debug_name);
199 Node* parameter = builder->graph()->NewNode(op, graph()->start());
200 values()->push_back(parameter);
201 }
202
203 // Registers
204 register_base_ = static_cast<int>(values()->size());
205 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
206 values()->insert(values()->end(), register_count, undefined_constant);
207
208 // Accumulator
209 accumulator_base_ = static_cast<int>(values()->size());
210 values()->push_back(undefined_constant);
211 }
212
213
Environment(const BytecodeGraphBuilder::Environment * other)214 BytecodeGraphBuilder::Environment::Environment(
215 const BytecodeGraphBuilder::Environment* other)
216 : builder_(other->builder_),
217 register_count_(other->register_count_),
218 parameter_count_(other->parameter_count_),
219 context_(other->context_),
220 control_dependency_(other->control_dependency_),
221 effect_dependency_(other->effect_dependency_),
222 values_(other->zone()),
223 parameters_state_values_(nullptr),
224 registers_state_values_(nullptr),
225 accumulator_state_values_(nullptr),
226 register_base_(other->register_base_),
227 accumulator_base_(other->accumulator_base_) {
228 values_ = other->values_;
229 }
230
231
RegisterToValuesIndex(interpreter::Register the_register) const232 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
233 interpreter::Register the_register) const {
234 if (the_register.is_parameter()) {
235 return the_register.ToParameterIndex(parameter_count());
236 } else {
237 return the_register.index() + register_base();
238 }
239 }
240
241
LookupAccumulator() const242 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
243 return values()->at(accumulator_base_);
244 }
245
246
LookupRegister(interpreter::Register the_register) const247 Node* BytecodeGraphBuilder::Environment::LookupRegister(
248 interpreter::Register the_register) const {
249 if (the_register.is_current_context()) {
250 return Context();
251 } else if (the_register.is_function_closure()) {
252 return builder()->GetFunctionClosure();
253 } else if (the_register.is_new_target()) {
254 return builder()->GetNewTarget();
255 } else {
256 int values_index = RegisterToValuesIndex(the_register);
257 return values()->at(values_index);
258 }
259 }
260
261
BindAccumulator(Node * node,FrameStateBeforeAndAfter * states)262 void BytecodeGraphBuilder::Environment::BindAccumulator(
263 Node* node, FrameStateBeforeAndAfter* states) {
264 if (states) {
265 states->AddToNode(node, OutputFrameStateCombine::PokeAt(0));
266 }
267 values()->at(accumulator_base_) = node;
268 }
269
270
BindRegister(interpreter::Register the_register,Node * node,FrameStateBeforeAndAfter * states)271 void BytecodeGraphBuilder::Environment::BindRegister(
272 interpreter::Register the_register, Node* node,
273 FrameStateBeforeAndAfter* states) {
274 int values_index = RegisterToValuesIndex(the_register);
275 if (states) {
276 states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ -
277 values_index));
278 }
279 values()->at(values_index) = node;
280 }
281
282
BindRegistersToProjections(interpreter::Register first_reg,Node * node,FrameStateBeforeAndAfter * states)283 void BytecodeGraphBuilder::Environment::BindRegistersToProjections(
284 interpreter::Register first_reg, Node* node,
285 FrameStateBeforeAndAfter* states) {
286 int values_index = RegisterToValuesIndex(first_reg);
287 if (states) {
288 states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ -
289 values_index));
290 }
291 for (int i = 0; i < node->op()->ValueOutputCount(); i++) {
292 values()->at(values_index + i) =
293 builder()->NewNode(common()->Projection(i), node);
294 }
295 }
296
297
RecordAfterState(Node * node,FrameStateBeforeAndAfter * states)298 void BytecodeGraphBuilder::Environment::RecordAfterState(
299 Node* node, FrameStateBeforeAndAfter* states) {
300 states->AddToNode(node, OutputFrameStateCombine::Ignore());
301 }
302
303
304 BytecodeGraphBuilder::Environment*
CopyForLoop()305 BytecodeGraphBuilder::Environment::CopyForLoop() {
306 PrepareForLoop();
307 return new (zone()) Environment(this);
308 }
309
310
311 BytecodeGraphBuilder::Environment*
CopyForConditional() const312 BytecodeGraphBuilder::Environment::CopyForConditional() const {
313 return new (zone()) Environment(this);
314 }
315
316
Merge(BytecodeGraphBuilder::Environment * other)317 void BytecodeGraphBuilder::Environment::Merge(
318 BytecodeGraphBuilder::Environment* other) {
319 // Create a merge of the control dependencies of both environments and update
320 // the current environment's control dependency accordingly.
321 Node* control = builder()->MergeControl(GetControlDependency(),
322 other->GetControlDependency());
323 UpdateControlDependency(control);
324
325 // Create a merge of the effect dependencies of both environments and update
326 // the current environment's effect dependency accordingly.
327 Node* effect = builder()->MergeEffect(GetEffectDependency(),
328 other->GetEffectDependency(), control);
329 UpdateEffectDependency(effect);
330
331 // Introduce Phi nodes for values that have differing input at merge points,
332 // potentially extending an existing Phi node if possible.
333 context_ = builder()->MergeValue(context_, other->context_, control);
334 for (size_t i = 0; i < values_.size(); i++) {
335 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control);
336 }
337 }
338
339
PrepareForLoop()340 void BytecodeGraphBuilder::Environment::PrepareForLoop() {
341 // Create a control node for the loop header.
342 Node* control = builder()->NewLoop();
343
344 // Create a Phi for external effects.
345 Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control);
346 UpdateEffectDependency(effect);
347
348 // Assume everything in the loop is updated.
349 context_ = builder()->NewPhi(1, context_, control);
350 int size = static_cast<int>(values()->size());
351 for (int i = 0; i < size; i++) {
352 values()->at(i) = builder()->NewPhi(1, values()->at(i), control);
353 }
354
355 // Connect to the loop end.
356 Node* terminate = builder()->graph()->NewNode(
357 builder()->common()->Terminate(), effect, control);
358 builder()->exit_controls_.push_back(terminate);
359 }
360
361
StateValuesRequireUpdate(Node ** state_values,int offset,int count)362 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
363 Node** state_values, int offset, int count) {
364 if (*state_values == nullptr) {
365 return true;
366 }
367 DCHECK_EQ((*state_values)->InputCount(), count);
368 DCHECK_LE(static_cast<size_t>(offset + count), values()->size());
369 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
370 for (int i = 0; i < count; i++) {
371 if ((*state_values)->InputAt(i) != env_values[i]) {
372 return true;
373 }
374 }
375 return false;
376 }
377
378
UpdateStateValues(Node ** state_values,int offset,int count)379 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
380 int offset,
381 int count) {
382 if (StateValuesRequireUpdate(state_values, offset, count)) {
383 const Operator* op = common()->StateValues(count);
384 (*state_values) = graph()->NewNode(op, count, &values()->at(offset));
385 }
386 }
387
388
Checkpoint(BailoutId bailout_id,OutputFrameStateCombine combine)389 Node* BytecodeGraphBuilder::Environment::Checkpoint(
390 BailoutId bailout_id, OutputFrameStateCombine combine) {
391 // TODO(rmcilroy): Consider using StateValuesCache for some state values.
392 UpdateStateValues(¶meters_state_values_, 0, parameter_count());
393 UpdateStateValues(®isters_state_values_, register_base(),
394 register_count());
395 UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1);
396
397 const Operator* op = common()->FrameState(
398 bailout_id, combine, builder()->frame_state_function_info());
399 Node* result = graph()->NewNode(
400 op, parameters_state_values_, registers_state_values_,
401 accumulator_state_values_, Context(), builder()->GetFunctionClosure(),
402 builder()->graph()->start());
403
404 return result;
405 }
406
407
StateValuesAreUpToDate(Node ** state_values,int offset,int count,int output_poke_start,int output_poke_end)408 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate(
409 Node** state_values, int offset, int count, int output_poke_start,
410 int output_poke_end) {
411 DCHECK_LE(static_cast<size_t>(offset + count), values()->size());
412 for (int i = 0; i < count; i++, offset++) {
413 if (offset < output_poke_start || offset >= output_poke_end) {
414 if ((*state_values)->InputAt(i) != values()->at(offset)) {
415 return false;
416 }
417 }
418 }
419 return true;
420 }
421
422
StateValuesAreUpToDate(int output_poke_offset,int output_poke_count)423 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate(
424 int output_poke_offset, int output_poke_count) {
425 // Poke offset is relative to the top of the stack (i.e., the accumulator).
426 int output_poke_start = accumulator_base() - output_poke_offset;
427 int output_poke_end = output_poke_start + output_poke_count;
428 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(),
429 output_poke_start, output_poke_end) &&
430 StateValuesAreUpToDate(®isters_state_values_, register_base(),
431 register_count(), output_poke_start,
432 output_poke_end) &&
433 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(),
434 1, output_poke_start, output_poke_end);
435 }
436
BytecodeGraphBuilder(Zone * local_zone,CompilationInfo * info,JSGraph * jsgraph)437 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
438 CompilationInfo* info,
439 JSGraph* jsgraph)
440 : local_zone_(local_zone),
441 jsgraph_(jsgraph),
442 bytecode_array_(handle(info->shared_info()->bytecode_array())),
443 exception_handler_table_(
444 handle(HandlerTable::cast(bytecode_array()->handler_table()))),
445 feedback_vector_(handle(info->closure()->feedback_vector())),
446 frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
447 FrameStateType::kInterpretedFunction,
448 bytecode_array()->parameter_count(),
449 bytecode_array()->register_count(), info->shared_info())),
450 merge_environments_(local_zone),
451 exception_handlers_(local_zone),
452 current_exception_handler_(0),
453 input_buffer_size_(0),
454 input_buffer_(nullptr),
455 exit_controls_(local_zone) {}
456
GetNewTarget()457 Node* BytecodeGraphBuilder::GetNewTarget() {
458 if (!new_target_.is_set()) {
459 int params = bytecode_array()->parameter_count();
460 int index = Linkage::GetJSCallNewTargetParamIndex(params);
461 const Operator* op = common()->Parameter(index, "%new.target");
462 Node* node = NewNode(op, graph()->start());
463 new_target_.set(node);
464 }
465 return new_target_.get();
466 }
467
468
GetFunctionContext()469 Node* BytecodeGraphBuilder::GetFunctionContext() {
470 if (!function_context_.is_set()) {
471 int params = bytecode_array()->parameter_count();
472 int index = Linkage::GetJSCallContextParamIndex(params);
473 const Operator* op = common()->Parameter(index, "%context");
474 Node* node = NewNode(op, graph()->start());
475 function_context_.set(node);
476 }
477 return function_context_.get();
478 }
479
480
GetFunctionClosure()481 Node* BytecodeGraphBuilder::GetFunctionClosure() {
482 if (!function_closure_.is_set()) {
483 int index = Linkage::kJSCallClosureParamIndex;
484 const Operator* op = common()->Parameter(index, "%closure");
485 Node* node = NewNode(op, graph()->start());
486 function_closure_.set(node);
487 }
488 return function_closure_.get();
489 }
490
491
BuildLoadNativeContextField(int index)492 Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
493 const Operator* op =
494 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
495 Node* native_context = NewNode(op, environment()->Context());
496 return NewNode(javascript()->LoadContext(0, index, true), native_context);
497 }
498
499
CreateVectorSlotPair(int slot_id)500 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
501 FeedbackVectorSlot slot;
502 if (slot_id >= TypeFeedbackVector::kReservedIndexCount) {
503 slot = feedback_vector()->ToSlot(slot_id);
504 }
505 return VectorSlotPair(feedback_vector(), slot);
506 }
507
CreateGraph()508 bool BytecodeGraphBuilder::CreateGraph() {
509 // Set up the basic structure of the graph. Outputs for {Start} are
510 // the formal parameters (including the receiver) plus context and
511 // closure.
512
513 // Set up the basic structure of the graph. Outputs for {Start} are the formal
514 // parameters (including the receiver) plus new target, number of arguments,
515 // context and closure.
516 int actual_parameter_count = bytecode_array()->parameter_count() + 4;
517 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
518
519 Environment env(this, bytecode_array()->register_count(),
520 bytecode_array()->parameter_count(), graph()->start(),
521 GetFunctionContext());
522 set_environment(&env);
523
524 VisitBytecodes();
525
526 // Finish the basic structure of the graph.
527 DCHECK_NE(0u, exit_controls_.size());
528 int const input_count = static_cast<int>(exit_controls_.size());
529 Node** const inputs = &exit_controls_.front();
530 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
531 graph()->SetEnd(end);
532
533 return true;
534 }
535
VisitBytecodes()536 void BytecodeGraphBuilder::VisitBytecodes() {
537 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone());
538 analysis.Analyze();
539 set_branch_analysis(&analysis);
540 interpreter::BytecodeArrayIterator iterator(bytecode_array());
541 set_bytecode_iterator(&iterator);
542 while (!iterator.done()) {
543 int current_offset = iterator.current_offset();
544 EnterAndExitExceptionHandlers(current_offset);
545 SwitchToMergeEnvironment(current_offset);
546 if (environment() != nullptr) {
547 BuildLoopHeaderEnvironment(current_offset);
548
549 switch (iterator.current_bytecode()) {
550 #define BYTECODE_CASE(name, ...) \
551 case interpreter::Bytecode::k##name: \
552 Visit##name(); \
553 break;
554 BYTECODE_LIST(BYTECODE_CASE)
555 #undef BYTECODE_CODE
556 }
557 }
558 iterator.Advance();
559 }
560 set_branch_analysis(nullptr);
561 set_bytecode_iterator(nullptr);
562 DCHECK(exception_handlers_.empty());
563 }
564
VisitLdaZero()565 void BytecodeGraphBuilder::VisitLdaZero() {
566 Node* node = jsgraph()->ZeroConstant();
567 environment()->BindAccumulator(node);
568 }
569
VisitLdaSmi()570 void BytecodeGraphBuilder::VisitLdaSmi() {
571 Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
572 environment()->BindAccumulator(node);
573 }
574
VisitLdaConstant()575 void BytecodeGraphBuilder::VisitLdaConstant() {
576 Node* node =
577 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
578 environment()->BindAccumulator(node);
579 }
580
VisitLdaUndefined()581 void BytecodeGraphBuilder::VisitLdaUndefined() {
582 Node* node = jsgraph()->UndefinedConstant();
583 environment()->BindAccumulator(node);
584 }
585
VisitLdrUndefined()586 void BytecodeGraphBuilder::VisitLdrUndefined() {
587 Node* node = jsgraph()->UndefinedConstant();
588 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node);
589 }
590
VisitLdaNull()591 void BytecodeGraphBuilder::VisitLdaNull() {
592 Node* node = jsgraph()->NullConstant();
593 environment()->BindAccumulator(node);
594 }
595
VisitLdaTheHole()596 void BytecodeGraphBuilder::VisitLdaTheHole() {
597 Node* node = jsgraph()->TheHoleConstant();
598 environment()->BindAccumulator(node);
599 }
600
VisitLdaTrue()601 void BytecodeGraphBuilder::VisitLdaTrue() {
602 Node* node = jsgraph()->TrueConstant();
603 environment()->BindAccumulator(node);
604 }
605
VisitLdaFalse()606 void BytecodeGraphBuilder::VisitLdaFalse() {
607 Node* node = jsgraph()->FalseConstant();
608 environment()->BindAccumulator(node);
609 }
610
VisitLdar()611 void BytecodeGraphBuilder::VisitLdar() {
612 Node* value =
613 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
614 environment()->BindAccumulator(value);
615 }
616
VisitStar()617 void BytecodeGraphBuilder::VisitStar() {
618 Node* value = environment()->LookupAccumulator();
619 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value);
620 }
621
VisitMov()622 void BytecodeGraphBuilder::VisitMov() {
623 Node* value =
624 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
625 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value);
626 }
627
BuildLoadGlobal(TypeofMode typeof_mode)628 Node* BytecodeGraphBuilder::BuildLoadGlobal(TypeofMode typeof_mode) {
629 VectorSlotPair feedback =
630 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(0));
631 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
632 feedback_vector()->GetKind(feedback.slot()));
633 Handle<Name> name(feedback_vector()->GetName(feedback.slot()));
634 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
635 return NewNode(op, GetFunctionClosure());
636 }
637
VisitLdaGlobal()638 void BytecodeGraphBuilder::VisitLdaGlobal() {
639 FrameStateBeforeAndAfter states(this);
640 Node* node = BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF);
641 environment()->BindAccumulator(node, &states);
642 }
643
VisitLdrGlobal()644 void BytecodeGraphBuilder::VisitLdrGlobal() {
645 FrameStateBeforeAndAfter states(this);
646 Node* node = BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF);
647 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), node,
648 &states);
649 }
650
VisitLdaGlobalInsideTypeof()651 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() {
652 FrameStateBeforeAndAfter states(this);
653 Node* node = BuildLoadGlobal(TypeofMode::INSIDE_TYPEOF);
654 environment()->BindAccumulator(node, &states);
655 }
656
BuildStoreGlobal(LanguageMode language_mode)657 void BytecodeGraphBuilder::BuildStoreGlobal(LanguageMode language_mode) {
658 FrameStateBeforeAndAfter states(this);
659 Handle<Name> name =
660 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
661 VectorSlotPair feedback =
662 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
663 Node* value = environment()->LookupAccumulator();
664
665 const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback);
666 Node* node = NewNode(op, value, GetFunctionClosure());
667 environment()->RecordAfterState(node, &states);
668 }
669
VisitStaGlobalSloppy()670 void BytecodeGraphBuilder::VisitStaGlobalSloppy() {
671 BuildStoreGlobal(LanguageMode::SLOPPY);
672 }
673
VisitStaGlobalStrict()674 void BytecodeGraphBuilder::VisitStaGlobalStrict() {
675 BuildStoreGlobal(LanguageMode::STRICT);
676 }
677
BuildLoadContextSlot()678 Node* BytecodeGraphBuilder::BuildLoadContextSlot() {
679 // TODO(mythria): LoadContextSlots are unrolled by the required depth when
680 // generating bytecode. Hence the value of depth is always 0. Update this
681 // code, when the implementation changes.
682 // TODO(mythria): immutable flag is also set to false. This information is not
683 // available in bytecode array. update this code when the implementation
684 // changes.
685 const Operator* op = javascript()->LoadContext(
686 0, bytecode_iterator().GetIndexOperand(1), false);
687 Node* context =
688 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
689 return NewNode(op, context);
690 }
691
VisitLdaContextSlot()692 void BytecodeGraphBuilder::VisitLdaContextSlot() {
693 Node* node = BuildLoadContextSlot();
694 environment()->BindAccumulator(node);
695 }
696
VisitLdrContextSlot()697 void BytecodeGraphBuilder::VisitLdrContextSlot() {
698 Node* node = BuildLoadContextSlot();
699 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(2), node);
700 }
701
VisitStaContextSlot()702 void BytecodeGraphBuilder::VisitStaContextSlot() {
703 // TODO(mythria): LoadContextSlots are unrolled by the required depth when
704 // generating bytecode. Hence the value of depth is always 0. Update this
705 // code, when the implementation changes.
706 const Operator* op =
707 javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(1));
708 Node* context =
709 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
710 Node* value = environment()->LookupAccumulator();
711 NewNode(op, context, value);
712 }
713
BuildLdaLookupSlot(TypeofMode typeof_mode)714 void BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) {
715 FrameStateBeforeAndAfter states(this);
716 Node* name =
717 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
718 const Operator* op =
719 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
720 ? Runtime::kLoadLookupSlot
721 : Runtime::kLoadLookupSlotInsideTypeof);
722 Node* value = NewNode(op, name);
723 environment()->BindAccumulator(value, &states);
724 }
725
VisitLdaLookupSlot()726 void BytecodeGraphBuilder::VisitLdaLookupSlot() {
727 BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF);
728 }
729
VisitLdaLookupSlotInsideTypeof()730 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
731 BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF);
732 }
733
BuildStaLookupSlot(LanguageMode language_mode)734 void BytecodeGraphBuilder::BuildStaLookupSlot(LanguageMode language_mode) {
735 FrameStateBeforeAndAfter states(this);
736 Node* value = environment()->LookupAccumulator();
737 Node* name =
738 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
739 const Operator* op = javascript()->CallRuntime(
740 is_strict(language_mode) ? Runtime::kStoreLookupSlot_Strict
741 : Runtime::kStoreLookupSlot_Sloppy);
742 Node* store = NewNode(op, name, value);
743 environment()->BindAccumulator(store, &states);
744 }
745
VisitStaLookupSlotSloppy()746 void BytecodeGraphBuilder::VisitStaLookupSlotSloppy() {
747 BuildStaLookupSlot(LanguageMode::SLOPPY);
748 }
749
VisitStaLookupSlotStrict()750 void BytecodeGraphBuilder::VisitStaLookupSlotStrict() {
751 BuildStaLookupSlot(LanguageMode::STRICT);
752 }
753
BuildNamedLoad()754 Node* BytecodeGraphBuilder::BuildNamedLoad() {
755 Node* object =
756 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
757 Handle<Name> name =
758 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
759 VectorSlotPair feedback =
760 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
761
762 const Operator* op = javascript()->LoadNamed(name, feedback);
763 return NewNode(op, object, GetFunctionClosure());
764 }
765
VisitLdaNamedProperty()766 void BytecodeGraphBuilder::VisitLdaNamedProperty() {
767 FrameStateBeforeAndAfter states(this);
768 Node* node = BuildNamedLoad();
769 environment()->BindAccumulator(node, &states);
770 }
771
VisitLdrNamedProperty()772 void BytecodeGraphBuilder::VisitLdrNamedProperty() {
773 FrameStateBeforeAndAfter states(this);
774 Node* node = BuildNamedLoad();
775 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(3), node,
776 &states);
777 }
778
BuildKeyedLoad()779 Node* BytecodeGraphBuilder::BuildKeyedLoad() {
780 Node* key = environment()->LookupAccumulator();
781 Node* object =
782 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
783 VectorSlotPair feedback =
784 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
785
786 const Operator* op = javascript()->LoadProperty(feedback);
787 return NewNode(op, object, key, GetFunctionClosure());
788 }
789
VisitLdaKeyedProperty()790 void BytecodeGraphBuilder::VisitLdaKeyedProperty() {
791 FrameStateBeforeAndAfter states(this);
792 Node* node = BuildKeyedLoad();
793 environment()->BindAccumulator(node, &states);
794 }
795
VisitLdrKeyedProperty()796 void BytecodeGraphBuilder::VisitLdrKeyedProperty() {
797 FrameStateBeforeAndAfter states(this);
798 Node* node = BuildKeyedLoad();
799 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(2), node,
800 &states);
801 }
802
BuildNamedStore(LanguageMode language_mode)803 void BytecodeGraphBuilder::BuildNamedStore(LanguageMode language_mode) {
804 FrameStateBeforeAndAfter states(this);
805 Node* value = environment()->LookupAccumulator();
806 Node* object =
807 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
808 Handle<Name> name =
809 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
810 VectorSlotPair feedback =
811 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
812
813 const Operator* op = javascript()->StoreNamed(language_mode, name, feedback);
814 Node* node = NewNode(op, object, value, GetFunctionClosure());
815 environment()->RecordAfterState(node, &states);
816 }
817
VisitStaNamedPropertySloppy()818 void BytecodeGraphBuilder::VisitStaNamedPropertySloppy() {
819 BuildNamedStore(LanguageMode::SLOPPY);
820 }
821
VisitStaNamedPropertyStrict()822 void BytecodeGraphBuilder::VisitStaNamedPropertyStrict() {
823 BuildNamedStore(LanguageMode::STRICT);
824 }
825
BuildKeyedStore(LanguageMode language_mode)826 void BytecodeGraphBuilder::BuildKeyedStore(LanguageMode language_mode) {
827 FrameStateBeforeAndAfter states(this);
828 Node* value = environment()->LookupAccumulator();
829 Node* object =
830 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
831 Node* key =
832 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
833 VectorSlotPair feedback =
834 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
835
836 const Operator* op = javascript()->StoreProperty(language_mode, feedback);
837 Node* node = NewNode(op, object, key, value, GetFunctionClosure());
838 environment()->RecordAfterState(node, &states);
839 }
840
VisitStaKeyedPropertySloppy()841 void BytecodeGraphBuilder::VisitStaKeyedPropertySloppy() {
842 BuildKeyedStore(LanguageMode::SLOPPY);
843 }
844
VisitStaKeyedPropertyStrict()845 void BytecodeGraphBuilder::VisitStaKeyedPropertyStrict() {
846 BuildKeyedStore(LanguageMode::STRICT);
847 }
848
VisitPushContext()849 void BytecodeGraphBuilder::VisitPushContext() {
850 Node* new_context = environment()->LookupAccumulator();
851 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0),
852 environment()->Context());
853 environment()->SetContext(new_context);
854 }
855
VisitPopContext()856 void BytecodeGraphBuilder::VisitPopContext() {
857 Node* context =
858 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
859 environment()->SetContext(context);
860 }
861
VisitCreateClosure()862 void BytecodeGraphBuilder::VisitCreateClosure() {
863 Handle<SharedFunctionInfo> shared_info = Handle<SharedFunctionInfo>::cast(
864 bytecode_iterator().GetConstantForIndexOperand(0));
865 PretenureFlag tenured =
866 bytecode_iterator().GetFlagOperand(1) ? TENURED : NOT_TENURED;
867 const Operator* op = javascript()->CreateClosure(shared_info, tenured);
868 Node* closure = NewNode(op);
869 environment()->BindAccumulator(closure);
870 }
871
BuildCreateArguments(CreateArgumentsType type)872 void BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) {
873 FrameStateBeforeAndAfter states(this);
874 const Operator* op = javascript()->CreateArguments(type);
875 Node* object = NewNode(op, GetFunctionClosure());
876 environment()->BindAccumulator(object, &states);
877 }
878
VisitCreateMappedArguments()879 void BytecodeGraphBuilder::VisitCreateMappedArguments() {
880 BuildCreateArguments(CreateArgumentsType::kMappedArguments);
881 }
882
VisitCreateUnmappedArguments()883 void BytecodeGraphBuilder::VisitCreateUnmappedArguments() {
884 BuildCreateArguments(CreateArgumentsType::kUnmappedArguments);
885 }
886
VisitCreateRestParameter()887 void BytecodeGraphBuilder::VisitCreateRestParameter() {
888 BuildCreateArguments(CreateArgumentsType::kRestParameter);
889 }
890
BuildCreateLiteral(const Operator * op)891 void BytecodeGraphBuilder::BuildCreateLiteral(const Operator* op) {
892 FrameStateBeforeAndAfter states(this);
893 Node* literal = NewNode(op, GetFunctionClosure());
894 environment()->BindAccumulator(literal, &states);
895 }
896
VisitCreateRegExpLiteral()897 void BytecodeGraphBuilder::VisitCreateRegExpLiteral() {
898 Handle<String> constant_pattern =
899 Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
900 int literal_index = bytecode_iterator().GetIndexOperand(1);
901 int literal_flags = bytecode_iterator().GetFlagOperand(2);
902 const Operator* op = javascript()->CreateLiteralRegExp(
903 constant_pattern, literal_flags, literal_index);
904 BuildCreateLiteral(op);
905 }
906
VisitCreateArrayLiteral()907 void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
908 Handle<FixedArray> constant_elements = Handle<FixedArray>::cast(
909 bytecode_iterator().GetConstantForIndexOperand(0));
910 int literal_index = bytecode_iterator().GetIndexOperand(1);
911 int literal_flags = bytecode_iterator().GetFlagOperand(2);
912 int number_of_elements = constant_elements->length();
913 const Operator* op = javascript()->CreateLiteralArray(
914 constant_elements, literal_flags, literal_index, number_of_elements);
915 BuildCreateLiteral(op);
916 }
917
VisitCreateObjectLiteral()918 void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
919 Handle<FixedArray> constant_properties = Handle<FixedArray>::cast(
920 bytecode_iterator().GetConstantForIndexOperand(0));
921 int literal_index = bytecode_iterator().GetIndexOperand(1);
922 int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
923 int literal_flags =
924 interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
925 // TODO(mstarzinger): Thread through number of properties.
926 int number_of_properties = constant_properties->length() / 2;
927 const Operator* op = javascript()->CreateLiteralObject(
928 constant_properties, literal_flags, literal_index, number_of_properties);
929 BuildCreateLiteral(op);
930 }
931
ProcessCallArguments(const Operator * call_op,Node * callee,interpreter::Register receiver,size_t arity)932 Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
933 Node* callee,
934 interpreter::Register receiver,
935 size_t arity) {
936 Node** all = local_zone()->NewArray<Node*>(static_cast<int>(arity));
937 all[0] = callee;
938 all[1] = environment()->LookupRegister(receiver);
939 int receiver_index = receiver.index();
940 for (int i = 2; i < static_cast<int>(arity); ++i) {
941 all[i] = environment()->LookupRegister(
942 interpreter::Register(receiver_index + i - 1));
943 }
944 Node* value = MakeNode(call_op, static_cast<int>(arity), all, false);
945 return value;
946 }
947
BuildCall(TailCallMode tail_call_mode)948 void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode) {
949 FrameStateBeforeAndAfter states(this);
950 // TODO(rmcilroy): Set receiver_hint correctly based on whether the receiver
951 // register has been loaded with null / undefined explicitly or we are sure it
952 // is not null / undefined.
953 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
954 Node* callee =
955 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
956 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
957 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
958 VectorSlotPair feedback =
959 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(3));
960
961 const Operator* call = javascript()->CallFunction(
962 arg_count + 1, feedback, receiver_hint, tail_call_mode);
963 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1);
964 environment()->BindAccumulator(value, &states);
965 }
966
VisitCall()967 void BytecodeGraphBuilder::VisitCall() { BuildCall(TailCallMode::kDisallow); }
968
VisitTailCall()969 void BytecodeGraphBuilder::VisitTailCall() {
970 TailCallMode tail_call_mode =
971 bytecode_array_->GetIsolate()->is_tail_call_elimination_enabled()
972 ? TailCallMode::kAllow
973 : TailCallMode::kDisallow;
974 BuildCall(tail_call_mode);
975 }
976
VisitCallJSRuntime()977 void BytecodeGraphBuilder::VisitCallJSRuntime() {
978 FrameStateBeforeAndAfter states(this);
979 Node* callee =
980 BuildLoadNativeContextField(bytecode_iterator().GetIndexOperand(0));
981 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
982 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
983
984 // Create node to perform the JS runtime call.
985 const Operator* call = javascript()->CallFunction(arg_count + 1);
986 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1);
987 environment()->BindAccumulator(value, &states);
988 }
989
ProcessCallRuntimeArguments(const Operator * call_runtime_op,interpreter::Register first_arg,size_t arity)990 Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
991 const Operator* call_runtime_op, interpreter::Register first_arg,
992 size_t arity) {
993 Node** all = local_zone()->NewArray<Node*>(arity);
994 int first_arg_index = first_arg.index();
995 for (int i = 0; i < static_cast<int>(arity); ++i) {
996 all[i] = environment()->LookupRegister(
997 interpreter::Register(first_arg_index + i));
998 }
999 Node* value = MakeNode(call_runtime_op, static_cast<int>(arity), all, false);
1000 return value;
1001 }
1002
VisitCallRuntime()1003 void BytecodeGraphBuilder::VisitCallRuntime() {
1004 FrameStateBeforeAndAfter states(this);
1005 Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
1006 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
1007 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
1008
1009 // Create node to perform the runtime call.
1010 const Operator* call = javascript()->CallRuntime(functionId, arg_count);
1011 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count);
1012 environment()->BindAccumulator(value, &states);
1013 }
1014
VisitCallRuntimeForPair()1015 void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
1016 FrameStateBeforeAndAfter states(this);
1017 Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
1018 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
1019 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
1020 interpreter::Register first_return =
1021 bytecode_iterator().GetRegisterOperand(3);
1022
1023 // Create node to perform the runtime call.
1024 const Operator* call = javascript()->CallRuntime(functionId, arg_count);
1025 Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count);
1026 environment()->BindRegistersToProjections(first_return, return_pair, &states);
1027 }
1028
VisitInvokeIntrinsic()1029 void BytecodeGraphBuilder::VisitInvokeIntrinsic() {
1030 FrameStateBeforeAndAfter states(this);
1031 Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0);
1032 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
1033 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
1034
1035 // Create node to perform the runtime call. Turbofan will take care of the
1036 // lowering.
1037 const Operator* call = javascript()->CallRuntime(functionId, arg_count);
1038 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count);
1039 environment()->BindAccumulator(value, &states);
1040 }
1041
ProcessCallNewArguments(const Operator * call_new_op,Node * callee,Node * new_target,interpreter::Register first_arg,size_t arity)1042 Node* BytecodeGraphBuilder::ProcessCallNewArguments(
1043 const Operator* call_new_op, Node* callee, Node* new_target,
1044 interpreter::Register first_arg, size_t arity) {
1045 Node** all = local_zone()->NewArray<Node*>(arity);
1046 all[0] = new_target;
1047 int first_arg_index = first_arg.index();
1048 for (int i = 1; i < static_cast<int>(arity) - 1; ++i) {
1049 all[i] = environment()->LookupRegister(
1050 interpreter::Register(first_arg_index + i - 1));
1051 }
1052 all[arity - 1] = callee;
1053 Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false);
1054 return value;
1055 }
1056
VisitNew()1057 void BytecodeGraphBuilder::VisitNew() {
1058 FrameStateBeforeAndAfter states(this);
1059 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
1060 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
1061 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
1062
1063 Node* new_target = environment()->LookupAccumulator();
1064 Node* callee = environment()->LookupRegister(callee_reg);
1065 // TODO(turbofan): Pass the feedback here.
1066 const Operator* call = javascript()->CallConstruct(
1067 static_cast<int>(arg_count) + 2, VectorSlotPair());
1068 Node* value = ProcessCallNewArguments(call, callee, new_target, first_arg,
1069 arg_count + 2);
1070 environment()->BindAccumulator(value, &states);
1071 }
1072
BuildThrow()1073 void BytecodeGraphBuilder::BuildThrow() {
1074 FrameStateBeforeAndAfter states(this);
1075 Node* value = environment()->LookupAccumulator();
1076 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value);
1077 environment()->BindAccumulator(call, &states);
1078 }
1079
VisitThrow()1080 void BytecodeGraphBuilder::VisitThrow() {
1081 BuildThrow();
1082 Node* call = environment()->LookupAccumulator();
1083 Node* control = NewNode(common()->Throw(), call);
1084 MergeControlToLeaveFunction(control);
1085 }
1086
VisitReThrow()1087 void BytecodeGraphBuilder::VisitReThrow() {
1088 Node* value = environment()->LookupAccumulator();
1089 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value);
1090 Node* control = NewNode(common()->Throw(), call);
1091 MergeControlToLeaveFunction(control);
1092 }
1093
BuildBinaryOp(const Operator * js_op)1094 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) {
1095 FrameStateBeforeAndAfter states(this);
1096 Node* left =
1097 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1098 Node* right = environment()->LookupAccumulator();
1099 Node* node = NewNode(js_op, left, right);
1100 environment()->BindAccumulator(node, &states);
1101 }
1102
VisitAdd()1103 void BytecodeGraphBuilder::VisitAdd() {
1104 BinaryOperationHints hints = BinaryOperationHints::Any();
1105 BuildBinaryOp(javascript()->Add(hints));
1106 }
1107
VisitSub()1108 void BytecodeGraphBuilder::VisitSub() {
1109 BinaryOperationHints hints = BinaryOperationHints::Any();
1110 BuildBinaryOp(javascript()->Subtract(hints));
1111 }
1112
VisitMul()1113 void BytecodeGraphBuilder::VisitMul() {
1114 BinaryOperationHints hints = BinaryOperationHints::Any();
1115 BuildBinaryOp(javascript()->Multiply(hints));
1116 }
1117
VisitDiv()1118 void BytecodeGraphBuilder::VisitDiv() {
1119 BinaryOperationHints hints = BinaryOperationHints::Any();
1120 BuildBinaryOp(javascript()->Divide(hints));
1121 }
1122
VisitMod()1123 void BytecodeGraphBuilder::VisitMod() {
1124 BinaryOperationHints hints = BinaryOperationHints::Any();
1125 BuildBinaryOp(javascript()->Modulus(hints));
1126 }
1127
VisitBitwiseOr()1128 void BytecodeGraphBuilder::VisitBitwiseOr() {
1129 BinaryOperationHints hints = BinaryOperationHints::Any();
1130 BuildBinaryOp(javascript()->BitwiseOr(hints));
1131 }
1132
VisitBitwiseXor()1133 void BytecodeGraphBuilder::VisitBitwiseXor() {
1134 BinaryOperationHints hints = BinaryOperationHints::Any();
1135 BuildBinaryOp(javascript()->BitwiseXor(hints));
1136 }
1137
VisitBitwiseAnd()1138 void BytecodeGraphBuilder::VisitBitwiseAnd() {
1139 BinaryOperationHints hints = BinaryOperationHints::Any();
1140 BuildBinaryOp(javascript()->BitwiseAnd(hints));
1141 }
1142
VisitShiftLeft()1143 void BytecodeGraphBuilder::VisitShiftLeft() {
1144 BinaryOperationHints hints = BinaryOperationHints::Any();
1145 BuildBinaryOp(javascript()->ShiftLeft(hints));
1146 }
1147
VisitShiftRight()1148 void BytecodeGraphBuilder::VisitShiftRight() {
1149 BinaryOperationHints hints = BinaryOperationHints::Any();
1150 BuildBinaryOp(javascript()->ShiftRight(hints));
1151 }
1152
VisitShiftRightLogical()1153 void BytecodeGraphBuilder::VisitShiftRightLogical() {
1154 BinaryOperationHints hints = BinaryOperationHints::Any();
1155 BuildBinaryOp(javascript()->ShiftRightLogical(hints));
1156 }
1157
VisitInc()1158 void BytecodeGraphBuilder::VisitInc() {
1159 FrameStateBeforeAndAfter states(this);
1160 // Note: Use subtract -1 here instead of add 1 to ensure we always convert to
1161 // a number, not a string.
1162 const Operator* js_op = javascript()->Subtract(BinaryOperationHints::Any());
1163 Node* node = NewNode(js_op, environment()->LookupAccumulator(),
1164 jsgraph()->Constant(-1.0));
1165 environment()->BindAccumulator(node, &states);
1166 }
1167
VisitDec()1168 void BytecodeGraphBuilder::VisitDec() {
1169 FrameStateBeforeAndAfter states(this);
1170 const Operator* js_op = javascript()->Subtract(BinaryOperationHints::Any());
1171 Node* node = NewNode(js_op, environment()->LookupAccumulator(),
1172 jsgraph()->OneConstant());
1173 environment()->BindAccumulator(node, &states);
1174 }
1175
VisitLogicalNot()1176 void BytecodeGraphBuilder::VisitLogicalNot() {
1177 Node* value = environment()->LookupAccumulator();
1178 Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value,
1179 jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
1180 environment()->BindAccumulator(node);
1181 }
1182
VisitToBooleanLogicalNot()1183 void BytecodeGraphBuilder::VisitToBooleanLogicalNot() {
1184 Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
1185 environment()->LookupAccumulator());
1186 Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value,
1187 jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
1188 environment()->BindAccumulator(node);
1189 }
1190
VisitTypeOf()1191 void BytecodeGraphBuilder::VisitTypeOf() {
1192 Node* node =
1193 NewNode(javascript()->TypeOf(), environment()->LookupAccumulator());
1194 environment()->BindAccumulator(node);
1195 }
1196
BuildDelete(LanguageMode language_mode)1197 void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) {
1198 FrameStateBeforeAndAfter states(this);
1199 Node* key = environment()->LookupAccumulator();
1200 Node* object =
1201 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1202 Node* node =
1203 NewNode(javascript()->DeleteProperty(language_mode), object, key);
1204 environment()->BindAccumulator(node, &states);
1205 }
1206
VisitDeletePropertyStrict()1207 void BytecodeGraphBuilder::VisitDeletePropertyStrict() {
1208 BuildDelete(LanguageMode::STRICT);
1209 }
1210
VisitDeletePropertySloppy()1211 void BytecodeGraphBuilder::VisitDeletePropertySloppy() {
1212 BuildDelete(LanguageMode::SLOPPY);
1213 }
1214
BuildCompareOp(const Operator * js_op)1215 void BytecodeGraphBuilder::BuildCompareOp(const Operator* js_op) {
1216 FrameStateBeforeAndAfter states(this);
1217 Node* left =
1218 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1219 Node* right = environment()->LookupAccumulator();
1220 Node* node = NewNode(js_op, left, right);
1221 environment()->BindAccumulator(node, &states);
1222 }
1223
VisitTestEqual()1224 void BytecodeGraphBuilder::VisitTestEqual() {
1225 CompareOperationHints hints = CompareOperationHints::Any();
1226 BuildCompareOp(javascript()->Equal(hints));
1227 }
1228
VisitTestNotEqual()1229 void BytecodeGraphBuilder::VisitTestNotEqual() {
1230 CompareOperationHints hints = CompareOperationHints::Any();
1231 BuildCompareOp(javascript()->NotEqual(hints));
1232 }
1233
VisitTestEqualStrict()1234 void BytecodeGraphBuilder::VisitTestEqualStrict() {
1235 CompareOperationHints hints = CompareOperationHints::Any();
1236 BuildCompareOp(javascript()->StrictEqual(hints));
1237 }
1238
VisitTestLessThan()1239 void BytecodeGraphBuilder::VisitTestLessThan() {
1240 CompareOperationHints hints = CompareOperationHints::Any();
1241 BuildCompareOp(javascript()->LessThan(hints));
1242 }
1243
VisitTestGreaterThan()1244 void BytecodeGraphBuilder::VisitTestGreaterThan() {
1245 CompareOperationHints hints = CompareOperationHints::Any();
1246 BuildCompareOp(javascript()->GreaterThan(hints));
1247 }
1248
VisitTestLessThanOrEqual()1249 void BytecodeGraphBuilder::VisitTestLessThanOrEqual() {
1250 CompareOperationHints hints = CompareOperationHints::Any();
1251 BuildCompareOp(javascript()->LessThanOrEqual(hints));
1252 }
1253
VisitTestGreaterThanOrEqual()1254 void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() {
1255 CompareOperationHints hints = CompareOperationHints::Any();
1256 BuildCompareOp(javascript()->GreaterThanOrEqual(hints));
1257 }
1258
VisitTestIn()1259 void BytecodeGraphBuilder::VisitTestIn() {
1260 BuildCompareOp(javascript()->HasProperty());
1261 }
1262
VisitTestInstanceOf()1263 void BytecodeGraphBuilder::VisitTestInstanceOf() {
1264 BuildCompareOp(javascript()->InstanceOf());
1265 }
1266
BuildCastOperator(const Operator * js_op)1267 void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) {
1268 FrameStateBeforeAndAfter states(this);
1269 Node* node = NewNode(js_op, environment()->LookupAccumulator());
1270 environment()->BindAccumulator(node, &states);
1271 }
1272
VisitToName()1273 void BytecodeGraphBuilder::VisitToName() {
1274 BuildCastOperator(javascript()->ToName());
1275 }
1276
VisitToObject()1277 void BytecodeGraphBuilder::VisitToObject() {
1278 BuildCastOperator(javascript()->ToObject());
1279 }
1280
VisitToNumber()1281 void BytecodeGraphBuilder::VisitToNumber() {
1282 BuildCastOperator(javascript()->ToNumber());
1283 }
1284
VisitJump()1285 void BytecodeGraphBuilder::VisitJump() { BuildJump(); }
1286
VisitJumpConstant()1287 void BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); }
1288
1289
VisitJumpIfTrue()1290 void BytecodeGraphBuilder::VisitJumpIfTrue() {
1291 BuildJumpIfEqual(jsgraph()->TrueConstant());
1292 }
1293
VisitJumpIfTrueConstant()1294 void BytecodeGraphBuilder::VisitJumpIfTrueConstant() {
1295 BuildJumpIfEqual(jsgraph()->TrueConstant());
1296 }
1297
VisitJumpIfFalse()1298 void BytecodeGraphBuilder::VisitJumpIfFalse() {
1299 BuildJumpIfEqual(jsgraph()->FalseConstant());
1300 }
1301
VisitJumpIfFalseConstant()1302 void BytecodeGraphBuilder::VisitJumpIfFalseConstant() {
1303 BuildJumpIfEqual(jsgraph()->FalseConstant());
1304 }
1305
VisitJumpIfToBooleanTrue()1306 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() {
1307 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant());
1308 }
1309
VisitJumpIfToBooleanTrueConstant()1310 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() {
1311 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant());
1312 }
1313
VisitJumpIfToBooleanFalse()1314 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() {
1315 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant());
1316 }
1317
VisitJumpIfToBooleanFalseConstant()1318 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() {
1319 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant());
1320 }
1321
VisitJumpIfNotHole()1322 void BytecodeGraphBuilder::VisitJumpIfNotHole() { BuildJumpIfNotHole(); }
1323
VisitJumpIfNotHoleConstant()1324 void BytecodeGraphBuilder::VisitJumpIfNotHoleConstant() {
1325 BuildJumpIfNotHole();
1326 }
1327
VisitJumpIfNull()1328 void BytecodeGraphBuilder::VisitJumpIfNull() {
1329 BuildJumpIfEqual(jsgraph()->NullConstant());
1330 }
1331
VisitJumpIfNullConstant()1332 void BytecodeGraphBuilder::VisitJumpIfNullConstant() {
1333 BuildJumpIfEqual(jsgraph()->NullConstant());
1334 }
1335
VisitJumpIfUndefined()1336 void BytecodeGraphBuilder::VisitJumpIfUndefined() {
1337 BuildJumpIfEqual(jsgraph()->UndefinedConstant());
1338 }
1339
VisitJumpIfUndefinedConstant()1340 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() {
1341 BuildJumpIfEqual(jsgraph()->UndefinedConstant());
1342 }
1343
VisitStackCheck()1344 void BytecodeGraphBuilder::VisitStackCheck() {
1345 FrameStateBeforeAndAfter states(this);
1346 Node* node = NewNode(javascript()->StackCheck());
1347 environment()->RecordAfterState(node, &states);
1348 }
1349
VisitReturn()1350 void BytecodeGraphBuilder::VisitReturn() {
1351 Node* control =
1352 NewNode(common()->Return(), environment()->LookupAccumulator());
1353 MergeControlToLeaveFunction(control);
1354 }
1355
VisitDebugger()1356 void BytecodeGraphBuilder::VisitDebugger() {
1357 FrameStateBeforeAndAfter states(this);
1358 Node* call =
1359 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
1360 environment()->BindAccumulator(call, &states);
1361 }
1362
1363 // We cannot create a graph from the debugger copy of the bytecode array.
1364 #define DEBUG_BREAK(Name, ...) \
1365 void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); }
1366 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
1367 #undef DEBUG_BREAK
1368
BuildForInPrepare()1369 void BytecodeGraphBuilder::BuildForInPrepare() {
1370 FrameStateBeforeAndAfter states(this);
1371 Node* receiver = environment()->LookupAccumulator();
1372 Node* prepare = NewNode(javascript()->ForInPrepare(), receiver);
1373 environment()->BindRegistersToProjections(
1374 bytecode_iterator().GetRegisterOperand(0), prepare, &states);
1375 }
1376
VisitForInPrepare()1377 void BytecodeGraphBuilder::VisitForInPrepare() { BuildForInPrepare(); }
1378
VisitForInDone()1379 void BytecodeGraphBuilder::VisitForInDone() {
1380 FrameStateBeforeAndAfter states(this);
1381 Node* index =
1382 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1383 Node* cache_length =
1384 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1385 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1386 environment()->BindAccumulator(exit_cond, &states);
1387 }
1388
BuildForInNext()1389 void BytecodeGraphBuilder::BuildForInNext() {
1390 FrameStateBeforeAndAfter states(this);
1391 Node* receiver =
1392 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1393 Node* index =
1394 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1395 int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index();
1396 Node* cache_type = environment()->LookupRegister(
1397 interpreter::Register(catch_reg_pair_index));
1398 Node* cache_array = environment()->LookupRegister(
1399 interpreter::Register(catch_reg_pair_index + 1));
1400
1401 Node* value = NewNode(javascript()->ForInNext(), receiver, cache_array,
1402 cache_type, index);
1403 environment()->BindAccumulator(value, &states);
1404 }
1405
VisitForInNext()1406 void BytecodeGraphBuilder::VisitForInNext() { BuildForInNext(); }
1407
VisitForInStep()1408 void BytecodeGraphBuilder::VisitForInStep() {
1409 FrameStateBeforeAndAfter states(this);
1410 Node* index =
1411 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1412 index = NewNode(javascript()->ForInStep(), index);
1413 environment()->BindAccumulator(index, &states);
1414 }
1415
VisitSuspendGenerator()1416 void BytecodeGraphBuilder::VisitSuspendGenerator() {
1417 Node* state = environment()->LookupAccumulator();
1418 Node* generator = environment()->LookupRegister(
1419 bytecode_iterator().GetRegisterOperand(0));
1420 // The offsets used by the bytecode iterator are relative to a different base
1421 // than what is used in the interpreter, hence the addition.
1422 Node* offset =
1423 jsgraph()->Constant(bytecode_iterator().current_offset() +
1424 (BytecodeArray::kHeaderSize - kHeapObjectTag));
1425
1426 int register_count = environment()->register_count();
1427 int value_input_count = 3 + register_count;
1428
1429 Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count);
1430 value_inputs[0] = generator;
1431 value_inputs[1] = state;
1432 value_inputs[2] = offset;
1433 for (int i = 0; i < register_count; ++i) {
1434 value_inputs[3 + i] =
1435 environment()->LookupRegister(interpreter::Register(i));
1436 }
1437
1438 MakeNode(javascript()->GeneratorStore(register_count), value_input_count,
1439 value_inputs, false);
1440 }
1441
VisitResumeGenerator()1442 void BytecodeGraphBuilder::VisitResumeGenerator() {
1443 FrameStateBeforeAndAfter states(this);
1444
1445 Node* generator = environment()->LookupRegister(
1446 bytecode_iterator().GetRegisterOperand(0));
1447
1448 // Bijection between registers and array indices must match that used in
1449 // InterpreterAssembler::ExportRegisterFile.
1450 for (int i = 0; i < environment()->register_count(); ++i) {
1451 Node* value = NewNode(javascript()->GeneratorRestoreRegister(i), generator);
1452 environment()->BindRegister(interpreter::Register(i), value);
1453 }
1454
1455 Node* state =
1456 NewNode(javascript()->GeneratorRestoreContinuation(), generator);
1457
1458 environment()->BindAccumulator(state, &states);
1459 }
1460
VisitWide()1461 void BytecodeGraphBuilder::VisitWide() {
1462 // Consumed by the BytecodeArrayIterator.
1463 UNREACHABLE();
1464 }
1465
VisitExtraWide()1466 void BytecodeGraphBuilder::VisitExtraWide() {
1467 // Consumed by the BytecodeArrayIterator.
1468 UNREACHABLE();
1469 }
1470
VisitIllegal()1471 void BytecodeGraphBuilder::VisitIllegal() {
1472 // Not emitted in valid bytecode.
1473 UNREACHABLE();
1474 }
1475
VisitNop()1476 void BytecodeGraphBuilder::VisitNop() {}
1477
SwitchToMergeEnvironment(int current_offset)1478 void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) {
1479 if (merge_environments_[current_offset] != nullptr) {
1480 if (environment() != nullptr) {
1481 merge_environments_[current_offset]->Merge(environment());
1482 }
1483 set_environment(merge_environments_[current_offset]);
1484 }
1485 }
1486
BuildLoopHeaderEnvironment(int current_offset)1487 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) {
1488 if (branch_analysis()->backward_branches_target(current_offset)) {
1489 // Add loop header and store a copy so we can connect merged back
1490 // edge inputs to the loop header.
1491 merge_environments_[current_offset] = environment()->CopyForLoop();
1492 }
1493 }
1494
MergeIntoSuccessorEnvironment(int target_offset)1495 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) {
1496 if (merge_environments_[target_offset] == nullptr) {
1497 // Append merge nodes to the environment. We may merge here with another
1498 // environment. So add a place holder for merge nodes. We may add redundant
1499 // but will be eliminated in a later pass.
1500 // TODO(mstarzinger): Be smarter about this!
1501 NewMerge();
1502 merge_environments_[target_offset] = environment();
1503 } else {
1504 merge_environments_[target_offset]->Merge(environment());
1505 }
1506 set_environment(nullptr);
1507 }
1508
MergeControlToLeaveFunction(Node * exit)1509 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) {
1510 exit_controls_.push_back(exit);
1511 set_environment(nullptr);
1512 }
1513
BuildJump()1514 void BytecodeGraphBuilder::BuildJump() {
1515 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
1516 }
1517
1518
BuildConditionalJump(Node * condition)1519 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) {
1520 NewBranch(condition);
1521 Environment* if_false_environment = environment()->CopyForConditional();
1522 NewIfTrue();
1523 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
1524 set_environment(if_false_environment);
1525 NewIfFalse();
1526 }
1527
1528
BuildJumpIfEqual(Node * comperand)1529 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
1530 Node* accumulator = environment()->LookupAccumulator();
1531 Node* condition =
1532 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
1533 accumulator, comperand);
1534 BuildConditionalJump(condition);
1535 }
1536
1537
BuildJumpIfToBooleanEqual(Node * comperand)1538 void BytecodeGraphBuilder::BuildJumpIfToBooleanEqual(Node* comperand) {
1539 Node* accumulator = environment()->LookupAccumulator();
1540 Node* to_boolean =
1541 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator);
1542 Node* condition =
1543 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
1544 to_boolean, comperand);
1545 BuildConditionalJump(condition);
1546 }
1547
BuildJumpIfNotHole()1548 void BytecodeGraphBuilder::BuildJumpIfNotHole() {
1549 Node* accumulator = environment()->LookupAccumulator();
1550 Node* condition =
1551 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
1552 accumulator, jsgraph()->TheHoleConstant());
1553 Node* node =
1554 NewNode(common()->Select(MachineRepresentation::kTagged), condition,
1555 jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
1556 BuildConditionalJump(node);
1557 }
1558
EnsureInputBufferSize(int size)1559 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
1560 if (size > input_buffer_size_) {
1561 size = size + kInputBufferSizeIncrement + input_buffer_size_;
1562 input_buffer_ = local_zone()->NewArray<Node*>(size);
1563 input_buffer_size_ = size;
1564 }
1565 return input_buffer_;
1566 }
1567
EnterAndExitExceptionHandlers(int current_offset)1568 void BytecodeGraphBuilder::EnterAndExitExceptionHandlers(int current_offset) {
1569 Handle<HandlerTable> table = exception_handler_table();
1570 int num_entries = table->NumberOfRangeEntries();
1571
1572 // Potentially exit exception handlers.
1573 while (!exception_handlers_.empty()) {
1574 int current_end = exception_handlers_.top().end_offset_;
1575 if (current_offset < current_end) break; // Still covered by range.
1576 exception_handlers_.pop();
1577 }
1578
1579 // Potentially enter exception handlers.
1580 while (current_exception_handler_ < num_entries) {
1581 int next_start = table->GetRangeStart(current_exception_handler_);
1582 if (current_offset < next_start) break; // Not yet covered by range.
1583 int next_end = table->GetRangeEnd(current_exception_handler_);
1584 int next_handler = table->GetRangeHandler(current_exception_handler_);
1585 int context_register = table->GetRangeData(current_exception_handler_);
1586 CatchPrediction pred =
1587 table->GetRangePrediction(current_exception_handler_);
1588 exception_handlers_.push(
1589 {next_start, next_end, next_handler, context_register, pred});
1590 current_exception_handler_++;
1591 }
1592 }
1593
MakeNode(const Operator * op,int value_input_count,Node ** value_inputs,bool incomplete)1594 Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
1595 Node** value_inputs, bool incomplete) {
1596 DCHECK_EQ(op->ValueInputCount(), value_input_count);
1597
1598 bool has_context = OperatorProperties::HasContextInput(op);
1599 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
1600 bool has_control = op->ControlInputCount() == 1;
1601 bool has_effect = op->EffectInputCount() == 1;
1602
1603 DCHECK_LT(op->ControlInputCount(), 2);
1604 DCHECK_LT(op->EffectInputCount(), 2);
1605
1606 Node* result = nullptr;
1607 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
1608 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
1609 } else {
1610 bool inside_handler = !exception_handlers_.empty();
1611 int input_count_with_deps = value_input_count;
1612 if (has_context) ++input_count_with_deps;
1613 input_count_with_deps += frame_state_count;
1614 if (has_control) ++input_count_with_deps;
1615 if (has_effect) ++input_count_with_deps;
1616 Node** buffer = EnsureInputBufferSize(input_count_with_deps);
1617 memcpy(buffer, value_inputs, kPointerSize * value_input_count);
1618 Node** current_input = buffer + value_input_count;
1619 if (has_context) {
1620 *current_input++ = environment()->Context();
1621 }
1622 for (int i = 0; i < frame_state_count; i++) {
1623 // The frame state will be inserted later. Here we misuse
1624 // the {Dead} node as a sentinel to be later overwritten
1625 // with the real frame state.
1626 *current_input++ = jsgraph()->Dead();
1627 }
1628 if (has_effect) {
1629 *current_input++ = environment()->GetEffectDependency();
1630 }
1631 if (has_control) {
1632 *current_input++ = environment()->GetControlDependency();
1633 }
1634 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
1635 // Update the current control dependency for control-producing nodes.
1636 if (NodeProperties::IsControl(result)) {
1637 environment()->UpdateControlDependency(result);
1638 }
1639 // Update the current effect dependency for effect-producing nodes.
1640 if (result->op()->EffectOutputCount() > 0) {
1641 environment()->UpdateEffectDependency(result);
1642 }
1643 // Add implicit exception continuation for throwing nodes.
1644 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
1645 int handler_offset = exception_handlers_.top().handler_offset_;
1646 int context_index = exception_handlers_.top().context_register_;
1647 CatchPrediction prediction = exception_handlers_.top().pred_;
1648 interpreter::Register context_register(context_index);
1649 IfExceptionHint hint = prediction == CatchPrediction::CAUGHT
1650 ? IfExceptionHint::kLocallyCaught
1651 : IfExceptionHint::kLocallyUncaught;
1652 Environment* success_env = environment()->CopyForConditional();
1653 const Operator* op = common()->IfException(hint);
1654 Node* effect = environment()->GetEffectDependency();
1655 Node* on_exception = graph()->NewNode(op, effect, result);
1656 Node* context = environment()->LookupRegister(context_register);
1657 environment()->UpdateControlDependency(on_exception);
1658 environment()->UpdateEffectDependency(on_exception);
1659 environment()->BindAccumulator(on_exception);
1660 environment()->SetContext(context);
1661 MergeIntoSuccessorEnvironment(handler_offset);
1662 set_environment(success_env);
1663 }
1664 // Add implicit success continuation for throwing nodes.
1665 if (!result->op()->HasProperty(Operator::kNoThrow)) {
1666 const Operator* if_success = common()->IfSuccess();
1667 Node* on_success = graph()->NewNode(if_success, result);
1668 environment()->UpdateControlDependency(on_success);
1669 }
1670 }
1671
1672 return result;
1673 }
1674
1675
NewPhi(int count,Node * input,Node * control)1676 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) {
1677 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
1678 Node** buffer = EnsureInputBufferSize(count + 1);
1679 MemsetPointer(buffer, input, count);
1680 buffer[count] = control;
1681 return graph()->NewNode(phi_op, count + 1, buffer, true);
1682 }
1683
1684
NewEffectPhi(int count,Node * input,Node * control)1685 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input,
1686 Node* control) {
1687 const Operator* phi_op = common()->EffectPhi(count);
1688 Node** buffer = EnsureInputBufferSize(count + 1);
1689 MemsetPointer(buffer, input, count);
1690 buffer[count] = control;
1691 return graph()->NewNode(phi_op, count + 1, buffer, true);
1692 }
1693
1694
MergeControl(Node * control,Node * other)1695 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
1696 int inputs = control->op()->ControlInputCount() + 1;
1697 if (control->opcode() == IrOpcode::kLoop) {
1698 // Control node for loop exists, add input.
1699 const Operator* op = common()->Loop(inputs);
1700 control->AppendInput(graph_zone(), other);
1701 NodeProperties::ChangeOp(control, op);
1702 } else if (control->opcode() == IrOpcode::kMerge) {
1703 // Control node for merge exists, add input.
1704 const Operator* op = common()->Merge(inputs);
1705 control->AppendInput(graph_zone(), other);
1706 NodeProperties::ChangeOp(control, op);
1707 } else {
1708 // Control node is a singleton, introduce a merge.
1709 const Operator* op = common()->Merge(inputs);
1710 Node* merge_inputs[] = {control, other};
1711 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true);
1712 }
1713 return control;
1714 }
1715
1716
MergeEffect(Node * value,Node * other,Node * control)1717 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
1718 Node* control) {
1719 int inputs = control->op()->ControlInputCount();
1720 if (value->opcode() == IrOpcode::kEffectPhi &&
1721 NodeProperties::GetControlInput(value) == control) {
1722 // Phi already exists, add input.
1723 value->InsertInput(graph_zone(), inputs - 1, other);
1724 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
1725 } else if (value != other) {
1726 // Phi does not exist yet, introduce one.
1727 value = NewEffectPhi(inputs, value, control);
1728 value->ReplaceInput(inputs - 1, other);
1729 }
1730 return value;
1731 }
1732
1733
MergeValue(Node * value,Node * other,Node * control)1734 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
1735 Node* control) {
1736 int inputs = control->op()->ControlInputCount();
1737 if (value->opcode() == IrOpcode::kPhi &&
1738 NodeProperties::GetControlInput(value) == control) {
1739 // Phi already exists, add input.
1740 value->InsertInput(graph_zone(), inputs - 1, other);
1741 NodeProperties::ChangeOp(
1742 value, common()->Phi(MachineRepresentation::kTagged, inputs));
1743 } else if (value != other) {
1744 // Phi does not exist yet, introduce one.
1745 value = NewPhi(inputs, value, control);
1746 value->ReplaceInput(inputs - 1, other);
1747 }
1748 return value;
1749 }
1750
1751 } // namespace compiler
1752 } // namespace internal
1753 } // namespace v8
1754