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 // Helper for generating frame states for before and after a bytecode.
17 class BytecodeGraphBuilder::FrameStateBeforeAndAfter {
18 public:
FrameStateBeforeAndAfter(BytecodeGraphBuilder * builder,const interpreter::BytecodeArrayIterator & iterator)19 FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder,
20 const interpreter::BytecodeArrayIterator& iterator)
21 : builder_(builder),
22 id_after_(BailoutId::None()),
23 added_to_node_(false),
24 output_poke_offset_(0),
25 output_poke_count_(0) {
26 BailoutId id_before(iterator.current_offset());
27 frame_state_before_ = builder_->environment()->Checkpoint(
28 id_before, OutputFrameStateCombine::Ignore());
29 id_after_ = BailoutId(id_before.ToInt() + iterator.current_bytecode_size());
30 }
31
~FrameStateBeforeAndAfter()32 ~FrameStateBeforeAndAfter() {
33 DCHECK(added_to_node_);
34 DCHECK(builder_->environment()->StateValuesAreUpToDate(output_poke_offset_,
35 output_poke_count_));
36 }
37
38 private:
39 friend class Environment;
40
AddToNode(Node * node,OutputFrameStateCombine combine)41 void AddToNode(Node* node, OutputFrameStateCombine combine) {
42 DCHECK(!added_to_node_);
43 int count = OperatorProperties::GetFrameStateInputCount(node->op());
44 DCHECK_LE(count, 2);
45 if (count >= 1) {
46 // Add the frame state for after the operation.
47 DCHECK_EQ(IrOpcode::kDead,
48 NodeProperties::GetFrameStateInput(node, 0)->opcode());
49 Node* frame_state_after =
50 builder_->environment()->Checkpoint(id_after_, combine);
51 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after);
52 }
53
54 if (count >= 2) {
55 // Add the frame state for before the operation.
56 DCHECK_EQ(IrOpcode::kDead,
57 NodeProperties::GetFrameStateInput(node, 1)->opcode());
58 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
59 }
60
61 if (!combine.IsOutputIgnored()) {
62 output_poke_offset_ = static_cast<int>(combine.GetOffsetToPokeAt());
63 output_poke_count_ = node->op()->ValueOutputCount();
64 }
65 added_to_node_ = true;
66 }
67
68 BytecodeGraphBuilder* builder_;
69 Node* frame_state_before_;
70 BailoutId id_after_;
71
72 bool added_to_node_;
73 int output_poke_offset_;
74 int output_poke_count_;
75 };
76
77
78 // Issues:
79 // - Scopes - intimately tied to AST. Need to eval what is needed.
80 // - Need to resolve closure parameter treatment.
Environment(BytecodeGraphBuilder * builder,int register_count,int parameter_count,Node * control_dependency,Node * context)81 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder,
82 int register_count,
83 int parameter_count,
84 Node* control_dependency,
85 Node* context)
86 : builder_(builder),
87 register_count_(register_count),
88 parameter_count_(parameter_count),
89 context_(context),
90 control_dependency_(control_dependency),
91 effect_dependency_(control_dependency),
92 values_(builder->local_zone()),
93 parameters_state_values_(nullptr),
94 registers_state_values_(nullptr),
95 accumulator_state_values_(nullptr) {
96 // The layout of values_ is:
97 //
98 // [receiver] [parameters] [registers] [accumulator]
99 //
100 // parameter[0] is the receiver (this), parameters 1..N are the
101 // parameters supplied to the method (arg0..argN-1). The accumulator
102 // is stored separately.
103
104 // Parameters including the receiver
105 for (int i = 0; i < parameter_count; i++) {
106 const char* debug_name = (i == 0) ? "%this" : nullptr;
107 const Operator* op = common()->Parameter(i, debug_name);
108 Node* parameter = builder->graph()->NewNode(op, graph()->start());
109 values()->push_back(parameter);
110 }
111
112 // Registers
113 register_base_ = static_cast<int>(values()->size());
114 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
115 values()->insert(values()->end(), register_count, undefined_constant);
116
117 // Accumulator
118 accumulator_base_ = static_cast<int>(values()->size());
119 values()->push_back(undefined_constant);
120 }
121
122
Environment(const BytecodeGraphBuilder::Environment * other)123 BytecodeGraphBuilder::Environment::Environment(
124 const BytecodeGraphBuilder::Environment* other)
125 : builder_(other->builder_),
126 register_count_(other->register_count_),
127 parameter_count_(other->parameter_count_),
128 context_(other->context_),
129 control_dependency_(other->control_dependency_),
130 effect_dependency_(other->effect_dependency_),
131 values_(other->zone()),
132 parameters_state_values_(nullptr),
133 registers_state_values_(nullptr),
134 accumulator_state_values_(nullptr),
135 register_base_(other->register_base_),
136 accumulator_base_(other->accumulator_base_) {
137 values_ = other->values_;
138 }
139
140
RegisterToValuesIndex(interpreter::Register the_register) const141 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
142 interpreter::Register the_register) const {
143 if (the_register.is_parameter()) {
144 return the_register.ToParameterIndex(parameter_count());
145 } else {
146 return the_register.index() + register_base();
147 }
148 }
149
150
LookupAccumulator() const151 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
152 return values()->at(accumulator_base_);
153 }
154
155
LookupRegister(interpreter::Register the_register) const156 Node* BytecodeGraphBuilder::Environment::LookupRegister(
157 interpreter::Register the_register) const {
158 if (the_register.is_function_context()) {
159 return builder()->GetFunctionContext();
160 } else if (the_register.is_function_closure()) {
161 return builder()->GetFunctionClosure();
162 } else if (the_register.is_new_target()) {
163 return builder()->GetNewTarget();
164 } else {
165 int values_index = RegisterToValuesIndex(the_register);
166 return values()->at(values_index);
167 }
168 }
169
170
ExchangeRegisters(interpreter::Register reg0,interpreter::Register reg1)171 void BytecodeGraphBuilder::Environment::ExchangeRegisters(
172 interpreter::Register reg0, interpreter::Register reg1) {
173 int reg0_index = RegisterToValuesIndex(reg0);
174 int reg1_index = RegisterToValuesIndex(reg1);
175 Node* saved_reg0_value = values()->at(reg0_index);
176 values()->at(reg0_index) = values()->at(reg1_index);
177 values()->at(reg1_index) = saved_reg0_value;
178 }
179
180
BindAccumulator(Node * node,FrameStateBeforeAndAfter * states)181 void BytecodeGraphBuilder::Environment::BindAccumulator(
182 Node* node, FrameStateBeforeAndAfter* states) {
183 if (states) {
184 states->AddToNode(node, OutputFrameStateCombine::PokeAt(0));
185 }
186 values()->at(accumulator_base_) = node;
187 }
188
189
BindRegister(interpreter::Register the_register,Node * node,FrameStateBeforeAndAfter * states)190 void BytecodeGraphBuilder::Environment::BindRegister(
191 interpreter::Register the_register, Node* node,
192 FrameStateBeforeAndAfter* states) {
193 int values_index = RegisterToValuesIndex(the_register);
194 if (states) {
195 states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ -
196 values_index));
197 }
198 values()->at(values_index) = node;
199 }
200
201
BindRegistersToProjections(interpreter::Register first_reg,Node * node,FrameStateBeforeAndAfter * states)202 void BytecodeGraphBuilder::Environment::BindRegistersToProjections(
203 interpreter::Register first_reg, Node* node,
204 FrameStateBeforeAndAfter* states) {
205 int values_index = RegisterToValuesIndex(first_reg);
206 if (states) {
207 states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ -
208 values_index));
209 }
210 for (int i = 0; i < node->op()->ValueOutputCount(); i++) {
211 values()->at(values_index + i) =
212 builder()->NewNode(common()->Projection(i), node);
213 }
214 }
215
216
RecordAfterState(Node * node,FrameStateBeforeAndAfter * states)217 void BytecodeGraphBuilder::Environment::RecordAfterState(
218 Node* node, FrameStateBeforeAndAfter* states) {
219 states->AddToNode(node, OutputFrameStateCombine::Ignore());
220 }
221
222
IsMarkedAsUnreachable() const223 bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const {
224 return GetControlDependency()->opcode() == IrOpcode::kDead;
225 }
226
227
MarkAsUnreachable()228 void BytecodeGraphBuilder::Environment::MarkAsUnreachable() {
229 UpdateControlDependency(builder()->jsgraph()->Dead());
230 }
231
232
233 BytecodeGraphBuilder::Environment*
CopyForLoop()234 BytecodeGraphBuilder::Environment::CopyForLoop() {
235 PrepareForLoop();
236 return new (zone()) Environment(this);
237 }
238
239
240 BytecodeGraphBuilder::Environment*
CopyForConditional() const241 BytecodeGraphBuilder::Environment::CopyForConditional() const {
242 return new (zone()) Environment(this);
243 }
244
245
Merge(BytecodeGraphBuilder::Environment * other)246 void BytecodeGraphBuilder::Environment::Merge(
247 BytecodeGraphBuilder::Environment* other) {
248 // Nothing to do if the other environment is dead.
249 if (other->IsMarkedAsUnreachable()) {
250 return;
251 }
252
253 // Create a merge of the control dependencies of both environments and update
254 // the current environment's control dependency accordingly.
255 Node* control = builder()->MergeControl(GetControlDependency(),
256 other->GetControlDependency());
257 UpdateControlDependency(control);
258
259 // Create a merge of the effect dependencies of both environments and update
260 // the current environment's effect dependency accordingly.
261 Node* effect = builder()->MergeEffect(GetEffectDependency(),
262 other->GetEffectDependency(), control);
263 UpdateEffectDependency(effect);
264
265 // Introduce Phi nodes for values that have differing input at merge points,
266 // potentially extending an existing Phi node if possible.
267 context_ = builder()->MergeValue(context_, other->context_, control);
268 for (size_t i = 0; i < values_.size(); i++) {
269 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control);
270 }
271 }
272
273
PrepareForLoop()274 void BytecodeGraphBuilder::Environment::PrepareForLoop() {
275 // Create a control node for the loop header.
276 Node* control = builder()->NewLoop();
277
278 // Create a Phi for external effects.
279 Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control);
280 UpdateEffectDependency(effect);
281
282 // Assume everything in the loop is updated.
283 context_ = builder()->NewPhi(1, context_, control);
284 int size = static_cast<int>(values()->size());
285 for (int i = 0; i < size; i++) {
286 values()->at(i) = builder()->NewPhi(1, values()->at(i), control);
287 }
288
289 // Connect to the loop end.
290 Node* terminate = builder()->graph()->NewNode(
291 builder()->common()->Terminate(), effect, control);
292 builder()->exit_controls_.push_back(terminate);
293 }
294
295
StateValuesRequireUpdate(Node ** state_values,int offset,int count)296 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
297 Node** state_values, int offset, int count) {
298 if (!builder()->info()->is_deoptimization_enabled()) {
299 return false;
300 }
301 if (*state_values == nullptr) {
302 return true;
303 }
304 DCHECK_EQ((*state_values)->InputCount(), count);
305 DCHECK_LE(static_cast<size_t>(offset + count), values()->size());
306 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
307 for (int i = 0; i < count; i++) {
308 if ((*state_values)->InputAt(i) != env_values[i]) {
309 return true;
310 }
311 }
312 return false;
313 }
314
315
UpdateStateValues(Node ** state_values,int offset,int count)316 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
317 int offset,
318 int count) {
319 if (StateValuesRequireUpdate(state_values, offset, count)) {
320 const Operator* op = common()->StateValues(count);
321 (*state_values) = graph()->NewNode(op, count, &values()->at(offset));
322 }
323 }
324
325
Checkpoint(BailoutId bailout_id,OutputFrameStateCombine combine)326 Node* BytecodeGraphBuilder::Environment::Checkpoint(
327 BailoutId bailout_id, OutputFrameStateCombine combine) {
328 if (!builder()->info()->is_deoptimization_enabled()) {
329 return builder()->jsgraph()->EmptyFrameState();
330 }
331
332 // TODO(rmcilroy): Consider using StateValuesCache for some state values.
333 UpdateStateValues(¶meters_state_values_, 0, parameter_count());
334 UpdateStateValues(®isters_state_values_, register_base(),
335 register_count());
336 UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1);
337
338 const Operator* op = common()->FrameState(
339 bailout_id, combine, builder()->frame_state_function_info());
340 Node* result = graph()->NewNode(
341 op, parameters_state_values_, registers_state_values_,
342 accumulator_state_values_, Context(), builder()->GetFunctionClosure(),
343 builder()->graph()->start());
344
345 return result;
346 }
347
348
StateValuesAreUpToDate(Node ** state_values,int offset,int count,int output_poke_start,int output_poke_end)349 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate(
350 Node** state_values, int offset, int count, int output_poke_start,
351 int output_poke_end) {
352 DCHECK_LE(static_cast<size_t>(offset + count), values()->size());
353 for (int i = 0; i < count; i++, offset++) {
354 if (offset < output_poke_start || offset >= output_poke_end) {
355 if ((*state_values)->InputAt(i) != values()->at(offset)) {
356 return false;
357 }
358 }
359 }
360 return true;
361 }
362
363
StateValuesAreUpToDate(int output_poke_offset,int output_poke_count)364 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate(
365 int output_poke_offset, int output_poke_count) {
366 // Poke offset is relative to the top of the stack (i.e., the accumulator).
367 int output_poke_start = accumulator_base() - output_poke_offset;
368 int output_poke_end = output_poke_start + output_poke_count;
369 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(),
370 output_poke_start, output_poke_end) &&
371 StateValuesAreUpToDate(®isters_state_values_, register_base(),
372 register_count(), output_poke_start,
373 output_poke_end) &&
374 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(),
375 1, output_poke_start, output_poke_end);
376 }
377
378
BytecodeGraphBuilder(Zone * local_zone,CompilationInfo * compilation_info,JSGraph * jsgraph)379 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
380 CompilationInfo* compilation_info,
381 JSGraph* jsgraph)
382 : local_zone_(local_zone),
383 info_(compilation_info),
384 jsgraph_(jsgraph),
385 bytecode_array_(handle(info()->shared_info()->bytecode_array())),
386 frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
387 FrameStateType::kInterpretedFunction,
388 bytecode_array()->parameter_count(),
389 bytecode_array()->register_count(), info()->shared_info(),
390 CALL_MAINTAINS_NATIVE_CONTEXT)),
391 merge_environments_(local_zone),
392 loop_header_environments_(local_zone),
393 input_buffer_size_(0),
394 input_buffer_(nullptr),
395 exit_controls_(local_zone) {}
396
397
GetNewTarget()398 Node* BytecodeGraphBuilder::GetNewTarget() {
399 if (!new_target_.is_set()) {
400 int params = bytecode_array()->parameter_count();
401 int index = Linkage::GetJSCallNewTargetParamIndex(params);
402 const Operator* op = common()->Parameter(index, "%new.target");
403 Node* node = NewNode(op, graph()->start());
404 new_target_.set(node);
405 }
406 return new_target_.get();
407 }
408
409
GetFunctionContext()410 Node* BytecodeGraphBuilder::GetFunctionContext() {
411 if (!function_context_.is_set()) {
412 int params = bytecode_array()->parameter_count();
413 int index = Linkage::GetJSCallContextParamIndex(params);
414 const Operator* op = common()->Parameter(index, "%context");
415 Node* node = NewNode(op, graph()->start());
416 function_context_.set(node);
417 }
418 return function_context_.get();
419 }
420
421
GetFunctionClosure()422 Node* BytecodeGraphBuilder::GetFunctionClosure() {
423 if (!function_closure_.is_set()) {
424 int index = Linkage::kJSCallClosureParamIndex;
425 const Operator* op = common()->Parameter(index, "%closure");
426 Node* node = NewNode(op, graph()->start());
427 function_closure_.set(node);
428 }
429 return function_closure_.get();
430 }
431
432
BuildLoadObjectField(Node * object,int offset)433 Node* BytecodeGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
434 return NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()), object,
435 jsgraph()->IntPtrConstant(offset - kHeapObjectTag));
436 }
437
438
BuildLoadImmutableObjectField(Node * object,int offset)439 Node* BytecodeGraphBuilder::BuildLoadImmutableObjectField(Node* object,
440 int offset) {
441 return graph()->NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()),
442 object,
443 jsgraph()->IntPtrConstant(offset - kHeapObjectTag),
444 graph()->start(), graph()->start());
445 }
446
447
BuildLoadNativeContextField(int index)448 Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
449 const Operator* op =
450 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
451 Node* native_context = NewNode(op, environment()->Context());
452 return NewNode(javascript()->LoadContext(0, index, true), native_context);
453 }
454
455
BuildLoadFeedbackVector()456 Node* BytecodeGraphBuilder::BuildLoadFeedbackVector() {
457 if (!feedback_vector_.is_set()) {
458 Node* closure = GetFunctionClosure();
459 Node* shared = BuildLoadImmutableObjectField(
460 closure, JSFunction::kSharedFunctionInfoOffset);
461 Node* vector = BuildLoadImmutableObjectField(
462 shared, SharedFunctionInfo::kFeedbackVectorOffset);
463 feedback_vector_.set(vector);
464 }
465 return feedback_vector_.get();
466 }
467
468
CreateVectorSlotPair(int slot_id)469 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
470 Handle<TypeFeedbackVector> feedback_vector = info()->feedback_vector();
471 FeedbackVectorSlot slot;
472 if (slot_id >= TypeFeedbackVector::kReservedIndexCount) {
473 slot = feedback_vector->ToSlot(slot_id);
474 }
475 return VectorSlotPair(feedback_vector, slot);
476 }
477
478
CreateGraph(bool stack_check)479 bool BytecodeGraphBuilder::CreateGraph(bool stack_check) {
480 // Set up the basic structure of the graph. Outputs for {Start} are
481 // the formal parameters (including the receiver) plus context and
482 // closure.
483
484 // Set up the basic structure of the graph. Outputs for {Start} are the formal
485 // parameters (including the receiver) plus new target, number of arguments,
486 // context and closure.
487 int actual_parameter_count = bytecode_array()->parameter_count() + 4;
488 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
489
490 Environment env(this, bytecode_array()->register_count(),
491 bytecode_array()->parameter_count(), graph()->start(),
492 GetFunctionContext());
493 set_environment(&env);
494
495 CreateGraphBody(stack_check);
496
497 // Finish the basic structure of the graph.
498 DCHECK_NE(0u, exit_controls_.size());
499 int const input_count = static_cast<int>(exit_controls_.size());
500 Node** const inputs = &exit_controls_.front();
501 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
502 graph()->SetEnd(end);
503
504 return true;
505 }
506
507
CreateGraphBody(bool stack_check)508 void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) {
509 // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments
510 // object setup, this function variable if used, tracing hooks.
511
512 if (stack_check) {
513 Node* node = NewNode(javascript()->StackCheck());
514 PrepareEntryFrameState(node);
515 }
516
517 VisitBytecodes();
518 }
519
520
VisitBytecodes()521 void BytecodeGraphBuilder::VisitBytecodes() {
522 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone());
523 analysis.Analyze();
524 set_branch_analysis(&analysis);
525 interpreter::BytecodeArrayIterator iterator(bytecode_array());
526 set_bytecode_iterator(&iterator);
527 while (!iterator.done()) {
528 int current_offset = iterator.current_offset();
529 if (analysis.is_reachable(current_offset)) {
530 MergeEnvironmentsOfForwardBranches(current_offset);
531 BuildLoopHeaderForBackwardBranches(current_offset);
532
533 switch (iterator.current_bytecode()) {
534 #define BYTECODE_CASE(name, ...) \
535 case interpreter::Bytecode::k##name: \
536 Visit##name(iterator); \
537 break;
538 BYTECODE_LIST(BYTECODE_CASE)
539 #undef BYTECODE_CODE
540 }
541 }
542 iterator.Advance();
543 }
544 set_branch_analysis(nullptr);
545 set_bytecode_iterator(nullptr);
546 }
547
548
VisitLdaZero(const interpreter::BytecodeArrayIterator & iterator)549 void BytecodeGraphBuilder::VisitLdaZero(
550 const interpreter::BytecodeArrayIterator& iterator) {
551 Node* node = jsgraph()->ZeroConstant();
552 environment()->BindAccumulator(node);
553 }
554
555
VisitLdaSmi8(const interpreter::BytecodeArrayIterator & iterator)556 void BytecodeGraphBuilder::VisitLdaSmi8(
557 const interpreter::BytecodeArrayIterator& iterator) {
558 Node* node = jsgraph()->Constant(iterator.GetImmediateOperand(0));
559 environment()->BindAccumulator(node);
560 }
561
562
VisitLdaConstantWide(const interpreter::BytecodeArrayIterator & iterator)563 void BytecodeGraphBuilder::VisitLdaConstantWide(
564 const interpreter::BytecodeArrayIterator& iterator) {
565 Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0));
566 environment()->BindAccumulator(node);
567 }
568
569
VisitLdaConstant(const interpreter::BytecodeArrayIterator & iterator)570 void BytecodeGraphBuilder::VisitLdaConstant(
571 const interpreter::BytecodeArrayIterator& iterator) {
572 Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0));
573 environment()->BindAccumulator(node);
574 }
575
576
VisitLdaUndefined(const interpreter::BytecodeArrayIterator & iterator)577 void BytecodeGraphBuilder::VisitLdaUndefined(
578 const interpreter::BytecodeArrayIterator& iterator) {
579 Node* node = jsgraph()->UndefinedConstant();
580 environment()->BindAccumulator(node);
581 }
582
583
VisitLdaNull(const interpreter::BytecodeArrayIterator & iterator)584 void BytecodeGraphBuilder::VisitLdaNull(
585 const interpreter::BytecodeArrayIterator& iterator) {
586 Node* node = jsgraph()->NullConstant();
587 environment()->BindAccumulator(node);
588 }
589
590
VisitLdaTheHole(const interpreter::BytecodeArrayIterator & iterator)591 void BytecodeGraphBuilder::VisitLdaTheHole(
592 const interpreter::BytecodeArrayIterator& iterator) {
593 Node* node = jsgraph()->TheHoleConstant();
594 environment()->BindAccumulator(node);
595 }
596
597
VisitLdaTrue(const interpreter::BytecodeArrayIterator & iterator)598 void BytecodeGraphBuilder::VisitLdaTrue(
599 const interpreter::BytecodeArrayIterator& iterator) {
600 Node* node = jsgraph()->TrueConstant();
601 environment()->BindAccumulator(node);
602 }
603
604
VisitLdaFalse(const interpreter::BytecodeArrayIterator & iterator)605 void BytecodeGraphBuilder::VisitLdaFalse(
606 const interpreter::BytecodeArrayIterator& iterator) {
607 Node* node = jsgraph()->FalseConstant();
608 environment()->BindAccumulator(node);
609 }
610
611
VisitLdar(const interpreter::BytecodeArrayIterator & iterator)612 void BytecodeGraphBuilder::VisitLdar(
613 const interpreter::BytecodeArrayIterator& iterator) {
614 Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0));
615 environment()->BindAccumulator(value);
616 }
617
618
VisitStar(const interpreter::BytecodeArrayIterator & iterator)619 void BytecodeGraphBuilder::VisitStar(
620 const interpreter::BytecodeArrayIterator& iterator) {
621 Node* value = environment()->LookupAccumulator();
622 environment()->BindRegister(iterator.GetRegisterOperand(0), value);
623 }
624
625
VisitMov(const interpreter::BytecodeArrayIterator & iterator)626 void BytecodeGraphBuilder::VisitMov(
627 const interpreter::BytecodeArrayIterator& iterator) {
628 Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0));
629 environment()->BindRegister(iterator.GetRegisterOperand(1), value);
630 }
631
632
VisitExchange(const interpreter::BytecodeArrayIterator & iterator)633 void BytecodeGraphBuilder::VisitExchange(
634 const interpreter::BytecodeArrayIterator& iterator) {
635 environment()->ExchangeRegisters(iterator.GetRegisterOperand(0),
636 iterator.GetRegisterOperand(1));
637 }
638
639
VisitExchangeWide(const interpreter::BytecodeArrayIterator & iterator)640 void BytecodeGraphBuilder::VisitExchangeWide(
641 const interpreter::BytecodeArrayIterator& iterator) {
642 environment()->ExchangeRegisters(iterator.GetRegisterOperand(0),
643 iterator.GetRegisterOperand(1));
644 }
645
646
BuildLoadGlobal(const interpreter::BytecodeArrayIterator & iterator,TypeofMode typeof_mode)647 void BytecodeGraphBuilder::BuildLoadGlobal(
648 const interpreter::BytecodeArrayIterator& iterator,
649 TypeofMode typeof_mode) {
650 FrameStateBeforeAndAfter states(this, iterator);
651 Handle<Name> name =
652 Handle<Name>::cast(iterator.GetConstantForIndexOperand(0));
653 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));
654
655 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
656 Node* node = NewNode(op, BuildLoadFeedbackVector());
657 environment()->BindAccumulator(node, &states);
658 }
659
660
VisitLdaGlobalSloppy(const interpreter::BytecodeArrayIterator & iterator)661 void BytecodeGraphBuilder::VisitLdaGlobalSloppy(
662 const interpreter::BytecodeArrayIterator& iterator) {
663 DCHECK(is_sloppy(language_mode()));
664 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
665 }
666
667
VisitLdaGlobalStrict(const interpreter::BytecodeArrayIterator & iterator)668 void BytecodeGraphBuilder::VisitLdaGlobalStrict(
669 const interpreter::BytecodeArrayIterator& iterator) {
670 DCHECK(is_strict(language_mode()));
671 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
672 }
673
674
VisitLdaGlobalInsideTypeofSloppy(const interpreter::BytecodeArrayIterator & iterator)675 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppy(
676 const interpreter::BytecodeArrayIterator& iterator) {
677 DCHECK(is_sloppy(language_mode()));
678 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
679 }
680
681
VisitLdaGlobalInsideTypeofStrict(const interpreter::BytecodeArrayIterator & iterator)682 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrict(
683 const interpreter::BytecodeArrayIterator& iterator) {
684 DCHECK(is_strict(language_mode()));
685 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
686 }
687
688
VisitLdaGlobalSloppyWide(const interpreter::BytecodeArrayIterator & iterator)689 void BytecodeGraphBuilder::VisitLdaGlobalSloppyWide(
690 const interpreter::BytecodeArrayIterator& iterator) {
691 DCHECK(is_sloppy(language_mode()));
692 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
693 }
694
695
VisitLdaGlobalStrictWide(const interpreter::BytecodeArrayIterator & iterator)696 void BytecodeGraphBuilder::VisitLdaGlobalStrictWide(
697 const interpreter::BytecodeArrayIterator& iterator) {
698 DCHECK(is_strict(language_mode()));
699 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
700 }
701
702
VisitLdaGlobalInsideTypeofSloppyWide(const interpreter::BytecodeArrayIterator & iterator)703 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppyWide(
704 const interpreter::BytecodeArrayIterator& iterator) {
705 DCHECK(is_sloppy(language_mode()));
706 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
707 }
708
709
VisitLdaGlobalInsideTypeofStrictWide(const interpreter::BytecodeArrayIterator & iterator)710 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrictWide(
711 const interpreter::BytecodeArrayIterator& iterator) {
712 DCHECK(is_strict(language_mode()));
713 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
714 }
715
716
BuildStoreGlobal(const interpreter::BytecodeArrayIterator & iterator)717 void BytecodeGraphBuilder::BuildStoreGlobal(
718 const interpreter::BytecodeArrayIterator& iterator) {
719 FrameStateBeforeAndAfter states(this, iterator);
720 Handle<Name> name =
721 Handle<Name>::cast(iterator.GetConstantForIndexOperand(0));
722 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));
723 Node* value = environment()->LookupAccumulator();
724
725 const Operator* op =
726 javascript()->StoreGlobal(language_mode(), name, feedback);
727 Node* node = NewNode(op, value, BuildLoadFeedbackVector());
728 environment()->RecordAfterState(node, &states);
729 }
730
731
VisitStaGlobalSloppy(const interpreter::BytecodeArrayIterator & iterator)732 void BytecodeGraphBuilder::VisitStaGlobalSloppy(
733 const interpreter::BytecodeArrayIterator& iterator) {
734 DCHECK(is_sloppy(language_mode()));
735 BuildStoreGlobal(iterator);
736 }
737
738
VisitStaGlobalStrict(const interpreter::BytecodeArrayIterator & iterator)739 void BytecodeGraphBuilder::VisitStaGlobalStrict(
740 const interpreter::BytecodeArrayIterator& iterator) {
741 DCHECK(is_strict(language_mode()));
742 BuildStoreGlobal(iterator);
743 }
744
VisitStaGlobalSloppyWide(const interpreter::BytecodeArrayIterator & iterator)745 void BytecodeGraphBuilder::VisitStaGlobalSloppyWide(
746 const interpreter::BytecodeArrayIterator& iterator) {
747 DCHECK(is_sloppy(language_mode()));
748 BuildStoreGlobal(iterator);
749 }
750
751
VisitStaGlobalStrictWide(const interpreter::BytecodeArrayIterator & iterator)752 void BytecodeGraphBuilder::VisitStaGlobalStrictWide(
753 const interpreter::BytecodeArrayIterator& iterator) {
754 DCHECK(is_strict(language_mode()));
755 BuildStoreGlobal(iterator);
756 }
757
758
VisitLdaContextSlot(const interpreter::BytecodeArrayIterator & iterator)759 void BytecodeGraphBuilder::VisitLdaContextSlot(
760 const interpreter::BytecodeArrayIterator& iterator) {
761 // TODO(mythria): LoadContextSlots are unrolled by the required depth when
762 // generating bytecode. Hence the value of depth is always 0. Update this
763 // code, when the implementation changes.
764 // TODO(mythria): immutable flag is also set to false. This information is not
765 // available in bytecode array. update this code when the implementation
766 // changes.
767 const Operator* op =
768 javascript()->LoadContext(0, iterator.GetIndexOperand(1), false);
769 Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0));
770 Node* node = NewNode(op, context);
771 environment()->BindAccumulator(node);
772 }
773
774
VisitLdaContextSlotWide(const interpreter::BytecodeArrayIterator & iterator)775 void BytecodeGraphBuilder::VisitLdaContextSlotWide(
776 const interpreter::BytecodeArrayIterator& iterator) {
777 VisitLdaContextSlot(iterator);
778 }
779
780
VisitStaContextSlot(const interpreter::BytecodeArrayIterator & iterator)781 void BytecodeGraphBuilder::VisitStaContextSlot(
782 const interpreter::BytecodeArrayIterator& iterator) {
783 // TODO(mythria): LoadContextSlots are unrolled by the required depth when
784 // generating bytecode. Hence the value of depth is always 0. Update this
785 // code, when the implementation changes.
786 const Operator* op =
787 javascript()->StoreContext(0, iterator.GetIndexOperand(1));
788 Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0));
789 Node* value = environment()->LookupAccumulator();
790 NewNode(op, context, value);
791 }
792
793
VisitStaContextSlotWide(const interpreter::BytecodeArrayIterator & iterator)794 void BytecodeGraphBuilder::VisitStaContextSlotWide(
795 const interpreter::BytecodeArrayIterator& iterator) {
796 VisitStaContextSlot(iterator);
797 }
798
799
BuildLdaLookupSlot(TypeofMode typeof_mode,const interpreter::BytecodeArrayIterator & iterator)800 void BytecodeGraphBuilder::BuildLdaLookupSlot(
801 TypeofMode typeof_mode,
802 const interpreter::BytecodeArrayIterator& iterator) {
803 FrameStateBeforeAndAfter states(this, iterator);
804 Handle<String> name =
805 Handle<String>::cast(iterator.GetConstantForIndexOperand(0));
806 const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
807 Node* value =
808 NewNode(op, BuildLoadFeedbackVector(), environment()->Context());
809 environment()->BindAccumulator(value, &states);
810 }
811
812
VisitLdaLookupSlot(const interpreter::BytecodeArrayIterator & iterator)813 void BytecodeGraphBuilder::VisitLdaLookupSlot(
814 const interpreter::BytecodeArrayIterator& iterator) {
815 BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF, iterator);
816 }
817
818
VisitLdaLookupSlotInsideTypeof(const interpreter::BytecodeArrayIterator & iterator)819 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof(
820 const interpreter::BytecodeArrayIterator& iterator) {
821 BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF, iterator);
822 }
823
824
BuildStaLookupSlot(LanguageMode language_mode,const interpreter::BytecodeArrayIterator & iterator)825 void BytecodeGraphBuilder::BuildStaLookupSlot(
826 LanguageMode language_mode,
827 const interpreter::BytecodeArrayIterator& iterator) {
828 FrameStateBeforeAndAfter states(this, iterator);
829 Node* value = environment()->LookupAccumulator();
830 Node* name = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0));
831 Node* language = jsgraph()->Constant(language_mode);
832 const Operator* op = javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4);
833 Node* store = NewNode(op, value, environment()->Context(), name, language);
834 environment()->BindAccumulator(store, &states);
835 }
836
837
VisitLdaLookupSlotWide(const interpreter::BytecodeArrayIterator & iterator)838 void BytecodeGraphBuilder::VisitLdaLookupSlotWide(
839 const interpreter::BytecodeArrayIterator& iterator) {
840 VisitLdaLookupSlot(iterator);
841 }
842
843
VisitLdaLookupSlotInsideTypeofWide(const interpreter::BytecodeArrayIterator & iterator)844 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeofWide(
845 const interpreter::BytecodeArrayIterator& iterator) {
846 VisitLdaLookupSlotInsideTypeof(iterator);
847 }
848
849
VisitStaLookupSlotSloppy(const interpreter::BytecodeArrayIterator & iterator)850 void BytecodeGraphBuilder::VisitStaLookupSlotSloppy(
851 const interpreter::BytecodeArrayIterator& iterator) {
852 BuildStaLookupSlot(LanguageMode::SLOPPY, iterator);
853 }
854
855
VisitStaLookupSlotStrict(const interpreter::BytecodeArrayIterator & iterator)856 void BytecodeGraphBuilder::VisitStaLookupSlotStrict(
857 const interpreter::BytecodeArrayIterator& iterator) {
858 BuildStaLookupSlot(LanguageMode::STRICT, iterator);
859 }
860
861
VisitStaLookupSlotSloppyWide(const interpreter::BytecodeArrayIterator & iterator)862 void BytecodeGraphBuilder::VisitStaLookupSlotSloppyWide(
863 const interpreter::BytecodeArrayIterator& iterator) {
864 VisitStaLookupSlotSloppy(iterator);
865 }
866
867
VisitStaLookupSlotStrictWide(const interpreter::BytecodeArrayIterator & iterator)868 void BytecodeGraphBuilder::VisitStaLookupSlotStrictWide(
869 const interpreter::BytecodeArrayIterator& iterator) {
870 VisitStaLookupSlotStrict(iterator);
871 }
872
873
BuildNamedLoad(const interpreter::BytecodeArrayIterator & iterator)874 void BytecodeGraphBuilder::BuildNamedLoad(
875 const interpreter::BytecodeArrayIterator& iterator) {
876 FrameStateBeforeAndAfter states(this, iterator);
877 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
878 Handle<Name> name =
879 Handle<Name>::cast(iterator.GetConstantForIndexOperand(1));
880 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2));
881
882 const Operator* op = javascript()->LoadNamed(language_mode(), name, feedback);
883 Node* node = NewNode(op, object, BuildLoadFeedbackVector());
884 environment()->BindAccumulator(node, &states);
885 }
886
887
VisitLoadICSloppy(const interpreter::BytecodeArrayIterator & iterator)888 void BytecodeGraphBuilder::VisitLoadICSloppy(
889 const interpreter::BytecodeArrayIterator& iterator) {
890 DCHECK(is_sloppy(language_mode()));
891 BuildNamedLoad(iterator);
892 }
893
894
VisitLoadICStrict(const interpreter::BytecodeArrayIterator & iterator)895 void BytecodeGraphBuilder::VisitLoadICStrict(
896 const interpreter::BytecodeArrayIterator& iterator) {
897 DCHECK(is_strict(language_mode()));
898 BuildNamedLoad(iterator);
899 }
900
901
VisitLoadICSloppyWide(const interpreter::BytecodeArrayIterator & iterator)902 void BytecodeGraphBuilder::VisitLoadICSloppyWide(
903 const interpreter::BytecodeArrayIterator& iterator) {
904 DCHECK(is_sloppy(language_mode()));
905 BuildNamedLoad(iterator);
906 }
907
908
VisitLoadICStrictWide(const interpreter::BytecodeArrayIterator & iterator)909 void BytecodeGraphBuilder::VisitLoadICStrictWide(
910 const interpreter::BytecodeArrayIterator& iterator) {
911 DCHECK(is_strict(language_mode()));
912 BuildNamedLoad(iterator);
913 }
914
915
BuildKeyedLoad(const interpreter::BytecodeArrayIterator & iterator)916 void BytecodeGraphBuilder::BuildKeyedLoad(
917 const interpreter::BytecodeArrayIterator& iterator) {
918 FrameStateBeforeAndAfter states(this, iterator);
919 Node* key = environment()->LookupAccumulator();
920 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
921 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));
922
923 const Operator* op = javascript()->LoadProperty(language_mode(), feedback);
924 Node* node = NewNode(op, object, key, BuildLoadFeedbackVector());
925 environment()->BindAccumulator(node, &states);
926 }
927
928
VisitKeyedLoadICSloppy(const interpreter::BytecodeArrayIterator & iterator)929 void BytecodeGraphBuilder::VisitKeyedLoadICSloppy(
930 const interpreter::BytecodeArrayIterator& iterator) {
931 DCHECK(is_sloppy(language_mode()));
932 BuildKeyedLoad(iterator);
933 }
934
935
VisitKeyedLoadICStrict(const interpreter::BytecodeArrayIterator & iterator)936 void BytecodeGraphBuilder::VisitKeyedLoadICStrict(
937 const interpreter::BytecodeArrayIterator& iterator) {
938 DCHECK(is_strict(language_mode()));
939 BuildKeyedLoad(iterator);
940 }
941
942
VisitKeyedLoadICSloppyWide(const interpreter::BytecodeArrayIterator & iterator)943 void BytecodeGraphBuilder::VisitKeyedLoadICSloppyWide(
944 const interpreter::BytecodeArrayIterator& iterator) {
945 DCHECK(is_sloppy(language_mode()));
946 BuildKeyedLoad(iterator);
947 }
948
949
VisitKeyedLoadICStrictWide(const interpreter::BytecodeArrayIterator & iterator)950 void BytecodeGraphBuilder::VisitKeyedLoadICStrictWide(
951 const interpreter::BytecodeArrayIterator& iterator) {
952 DCHECK(is_strict(language_mode()));
953 BuildKeyedLoad(iterator);
954 }
955
956
BuildNamedStore(const interpreter::BytecodeArrayIterator & iterator)957 void BytecodeGraphBuilder::BuildNamedStore(
958 const interpreter::BytecodeArrayIterator& iterator) {
959 FrameStateBeforeAndAfter states(this, iterator);
960 Node* value = environment()->LookupAccumulator();
961 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
962 Handle<Name> name =
963 Handle<Name>::cast(iterator.GetConstantForIndexOperand(1));
964 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2));
965
966 const Operator* op =
967 javascript()->StoreNamed(language_mode(), name, feedback);
968 Node* node = NewNode(op, object, value, BuildLoadFeedbackVector());
969 environment()->RecordAfterState(node, &states);
970 }
971
972
VisitStoreICSloppy(const interpreter::BytecodeArrayIterator & iterator)973 void BytecodeGraphBuilder::VisitStoreICSloppy(
974 const interpreter::BytecodeArrayIterator& iterator) {
975 DCHECK(is_sloppy(language_mode()));
976 BuildNamedStore(iterator);
977 }
978
979
VisitStoreICStrict(const interpreter::BytecodeArrayIterator & iterator)980 void BytecodeGraphBuilder::VisitStoreICStrict(
981 const interpreter::BytecodeArrayIterator& iterator) {
982 DCHECK(is_strict(language_mode()));
983 BuildNamedStore(iterator);
984 }
985
986
VisitStoreICSloppyWide(const interpreter::BytecodeArrayIterator & iterator)987 void BytecodeGraphBuilder::VisitStoreICSloppyWide(
988 const interpreter::BytecodeArrayIterator& iterator) {
989 DCHECK(is_sloppy(language_mode()));
990 BuildNamedStore(iterator);
991 }
992
993
VisitStoreICStrictWide(const interpreter::BytecodeArrayIterator & iterator)994 void BytecodeGraphBuilder::VisitStoreICStrictWide(
995 const interpreter::BytecodeArrayIterator& iterator) {
996 DCHECK(is_strict(language_mode()));
997 BuildNamedStore(iterator);
998 }
999
1000
BuildKeyedStore(const interpreter::BytecodeArrayIterator & iterator)1001 void BytecodeGraphBuilder::BuildKeyedStore(
1002 const interpreter::BytecodeArrayIterator& iterator) {
1003 FrameStateBeforeAndAfter states(this, iterator);
1004 Node* value = environment()->LookupAccumulator();
1005 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1006 Node* key = environment()->LookupRegister(iterator.GetRegisterOperand(1));
1007 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2));
1008
1009 const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
1010 Node* node = NewNode(op, object, key, value, BuildLoadFeedbackVector());
1011 environment()->RecordAfterState(node, &states);
1012 }
1013
1014
VisitKeyedStoreICSloppy(const interpreter::BytecodeArrayIterator & iterator)1015 void BytecodeGraphBuilder::VisitKeyedStoreICSloppy(
1016 const interpreter::BytecodeArrayIterator& iterator) {
1017 DCHECK(is_sloppy(language_mode()));
1018 BuildKeyedStore(iterator);
1019 }
1020
1021
VisitKeyedStoreICStrict(const interpreter::BytecodeArrayIterator & iterator)1022 void BytecodeGraphBuilder::VisitKeyedStoreICStrict(
1023 const interpreter::BytecodeArrayIterator& iterator) {
1024 DCHECK(is_strict(language_mode()));
1025 BuildKeyedStore(iterator);
1026 }
1027
1028
VisitKeyedStoreICSloppyWide(const interpreter::BytecodeArrayIterator & iterator)1029 void BytecodeGraphBuilder::VisitKeyedStoreICSloppyWide(
1030 const interpreter::BytecodeArrayIterator& iterator) {
1031 DCHECK(is_sloppy(language_mode()));
1032 BuildKeyedStore(iterator);
1033 }
1034
1035
VisitKeyedStoreICStrictWide(const interpreter::BytecodeArrayIterator & iterator)1036 void BytecodeGraphBuilder::VisitKeyedStoreICStrictWide(
1037 const interpreter::BytecodeArrayIterator& iterator) {
1038 DCHECK(is_strict(language_mode()));
1039 BuildKeyedStore(iterator);
1040 }
1041
1042
VisitPushContext(const interpreter::BytecodeArrayIterator & iterator)1043 void BytecodeGraphBuilder::VisitPushContext(
1044 const interpreter::BytecodeArrayIterator& iterator) {
1045 Node* context = environment()->LookupAccumulator();
1046 environment()->BindRegister(iterator.GetRegisterOperand(0), context);
1047 environment()->SetContext(context);
1048 }
1049
1050
VisitPopContext(const interpreter::BytecodeArrayIterator & iterator)1051 void BytecodeGraphBuilder::VisitPopContext(
1052 const interpreter::BytecodeArrayIterator& iterator) {
1053 Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1054 environment()->SetContext(context);
1055 }
1056
1057
VisitCreateClosure(const interpreter::BytecodeArrayIterator & iterator)1058 void BytecodeGraphBuilder::VisitCreateClosure(
1059 const interpreter::BytecodeArrayIterator& iterator) {
1060 Handle<SharedFunctionInfo> shared_info =
1061 Handle<SharedFunctionInfo>::cast(iterator.GetConstantForIndexOperand(0));
1062 PretenureFlag tenured =
1063 iterator.GetImmediateOperand(1) ? TENURED : NOT_TENURED;
1064 const Operator* op = javascript()->CreateClosure(shared_info, tenured);
1065 Node* closure = NewNode(op);
1066 environment()->BindAccumulator(closure);
1067 }
1068
1069
VisitCreateClosureWide(const interpreter::BytecodeArrayIterator & iterator)1070 void BytecodeGraphBuilder::VisitCreateClosureWide(
1071 const interpreter::BytecodeArrayIterator& iterator) {
1072 VisitCreateClosure(iterator);
1073 }
1074
1075
BuildCreateArguments(CreateArgumentsParameters::Type type,const interpreter::BytecodeArrayIterator & iterator)1076 void BytecodeGraphBuilder::BuildCreateArguments(
1077 CreateArgumentsParameters::Type type,
1078 const interpreter::BytecodeArrayIterator& iterator) {
1079 FrameStateBeforeAndAfter states(this, iterator);
1080 const Operator* op = javascript()->CreateArguments(type, 0);
1081 Node* object = NewNode(op, GetFunctionClosure());
1082 environment()->BindAccumulator(object, &states);
1083 }
1084
1085
VisitCreateMappedArguments(const interpreter::BytecodeArrayIterator & iterator)1086 void BytecodeGraphBuilder::VisitCreateMappedArguments(
1087 const interpreter::BytecodeArrayIterator& iterator) {
1088 BuildCreateArguments(CreateArgumentsParameters::kMappedArguments, iterator);
1089 }
1090
1091
VisitCreateUnmappedArguments(const interpreter::BytecodeArrayIterator & iterator)1092 void BytecodeGraphBuilder::VisitCreateUnmappedArguments(
1093 const interpreter::BytecodeArrayIterator& iterator) {
1094 BuildCreateArguments(CreateArgumentsParameters::kUnmappedArguments, iterator);
1095 }
1096
1097
BuildCreateLiteral(const Operator * op,const interpreter::BytecodeArrayIterator & iterator)1098 void BytecodeGraphBuilder::BuildCreateLiteral(
1099 const Operator* op, const interpreter::BytecodeArrayIterator& iterator) {
1100 FrameStateBeforeAndAfter states(this, iterator);
1101 Node* literal = NewNode(op, GetFunctionClosure());
1102 environment()->BindAccumulator(literal, &states);
1103 }
1104
1105
BuildCreateRegExpLiteral(const interpreter::BytecodeArrayIterator & iterator)1106 void BytecodeGraphBuilder::BuildCreateRegExpLiteral(
1107 const interpreter::BytecodeArrayIterator& iterator) {
1108 Handle<String> constant_pattern =
1109 Handle<String>::cast(iterator.GetConstantForIndexOperand(0));
1110 int literal_index = iterator.GetIndexOperand(1);
1111 int literal_flags = iterator.GetImmediateOperand(2);
1112 const Operator* op = javascript()->CreateLiteralRegExp(
1113 constant_pattern, literal_flags, literal_index);
1114 BuildCreateLiteral(op, iterator);
1115 }
1116
1117
VisitCreateRegExpLiteral(const interpreter::BytecodeArrayIterator & iterator)1118 void BytecodeGraphBuilder::VisitCreateRegExpLiteral(
1119 const interpreter::BytecodeArrayIterator& iterator) {
1120 BuildCreateRegExpLiteral(iterator);
1121 }
1122
1123
VisitCreateRegExpLiteralWide(const interpreter::BytecodeArrayIterator & iterator)1124 void BytecodeGraphBuilder::VisitCreateRegExpLiteralWide(
1125 const interpreter::BytecodeArrayIterator& iterator) {
1126 BuildCreateRegExpLiteral(iterator);
1127 }
1128
1129
BuildCreateArrayLiteral(const interpreter::BytecodeArrayIterator & iterator)1130 void BytecodeGraphBuilder::BuildCreateArrayLiteral(
1131 const interpreter::BytecodeArrayIterator& iterator) {
1132 Handle<FixedArray> constant_elements =
1133 Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0));
1134 int literal_index = iterator.GetIndexOperand(1);
1135 int literal_flags = iterator.GetImmediateOperand(2);
1136 const Operator* op = javascript()->CreateLiteralArray(
1137 constant_elements, literal_flags, literal_index);
1138 BuildCreateLiteral(op, iterator);
1139 }
1140
1141
VisitCreateArrayLiteral(const interpreter::BytecodeArrayIterator & iterator)1142 void BytecodeGraphBuilder::VisitCreateArrayLiteral(
1143 const interpreter::BytecodeArrayIterator& iterator) {
1144 BuildCreateArrayLiteral(iterator);
1145 }
1146
1147
VisitCreateArrayLiteralWide(const interpreter::BytecodeArrayIterator & iterator)1148 void BytecodeGraphBuilder::VisitCreateArrayLiteralWide(
1149 const interpreter::BytecodeArrayIterator& iterator) {
1150 BuildCreateArrayLiteral(iterator);
1151 }
1152
1153
BuildCreateObjectLiteral(const interpreter::BytecodeArrayIterator & iterator)1154 void BytecodeGraphBuilder::BuildCreateObjectLiteral(
1155 const interpreter::BytecodeArrayIterator& iterator) {
1156 Handle<FixedArray> constant_properties =
1157 Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0));
1158 int literal_index = iterator.GetIndexOperand(1);
1159 int literal_flags = iterator.GetImmediateOperand(2);
1160 const Operator* op = javascript()->CreateLiteralObject(
1161 constant_properties, literal_flags, literal_index);
1162 BuildCreateLiteral(op, iterator);
1163 }
1164
1165
VisitCreateObjectLiteral(const interpreter::BytecodeArrayIterator & iterator)1166 void BytecodeGraphBuilder::VisitCreateObjectLiteral(
1167 const interpreter::BytecodeArrayIterator& iterator) {
1168 BuildCreateObjectLiteral(iterator);
1169 }
1170
1171
VisitCreateObjectLiteralWide(const interpreter::BytecodeArrayIterator & iterator)1172 void BytecodeGraphBuilder::VisitCreateObjectLiteralWide(
1173 const interpreter::BytecodeArrayIterator& iterator) {
1174 BuildCreateObjectLiteral(iterator);
1175 }
1176
1177
ProcessCallArguments(const Operator * call_op,Node * callee,interpreter::Register receiver,size_t arity)1178 Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
1179 Node* callee,
1180 interpreter::Register receiver,
1181 size_t arity) {
1182 Node** all = info()->zone()->NewArray<Node*>(static_cast<int>(arity));
1183 all[0] = callee;
1184 all[1] = environment()->LookupRegister(receiver);
1185 int receiver_index = receiver.index();
1186 for (int i = 2; i < static_cast<int>(arity); ++i) {
1187 all[i] = environment()->LookupRegister(
1188 interpreter::Register(receiver_index + i - 1));
1189 }
1190 Node* value = MakeNode(call_op, static_cast<int>(arity), all, false);
1191 return value;
1192 }
1193
1194
BuildCall(const interpreter::BytecodeArrayIterator & iterator)1195 void BytecodeGraphBuilder::BuildCall(
1196 const interpreter::BytecodeArrayIterator& iterator) {
1197 FrameStateBeforeAndAfter states(this, iterator);
1198 // TODO(rmcilroy): Set receiver_hint correctly based on whether the receiver
1199 // register has been loaded with null / undefined explicitly or we are sure it
1200 // is not null / undefined.
1201 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
1202 Node* callee = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1203 interpreter::Register receiver = iterator.GetRegisterOperand(1);
1204 size_t arg_count = iterator.GetCountOperand(2);
1205 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(3));
1206
1207 const Operator* call = javascript()->CallFunction(
1208 arg_count + 2, language_mode(), feedback, receiver_hint);
1209 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2);
1210 environment()->BindAccumulator(value, &states);
1211 }
1212
1213
VisitCall(const interpreter::BytecodeArrayIterator & iterator)1214 void BytecodeGraphBuilder::VisitCall(
1215 const interpreter::BytecodeArrayIterator& iterator) {
1216 BuildCall(iterator);
1217 }
1218
1219
VisitCallWide(const interpreter::BytecodeArrayIterator & iterator)1220 void BytecodeGraphBuilder::VisitCallWide(
1221 const interpreter::BytecodeArrayIterator& iterator) {
1222 BuildCall(iterator);
1223 }
1224
1225
VisitCallJSRuntime(const interpreter::BytecodeArrayIterator & iterator)1226 void BytecodeGraphBuilder::VisitCallJSRuntime(
1227 const interpreter::BytecodeArrayIterator& iterator) {
1228 FrameStateBeforeAndAfter states(this, iterator);
1229 Node* callee = BuildLoadNativeContextField(iterator.GetIndexOperand(0));
1230 interpreter::Register receiver = iterator.GetRegisterOperand(1);
1231 size_t arg_count = iterator.GetCountOperand(2);
1232
1233 // Create node to perform the JS runtime call.
1234 const Operator* call =
1235 javascript()->CallFunction(arg_count + 2, language_mode());
1236 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2);
1237 environment()->BindAccumulator(value, &states);
1238 }
1239
1240
ProcessCallRuntimeArguments(const Operator * call_runtime_op,interpreter::Register first_arg,size_t arity)1241 Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
1242 const Operator* call_runtime_op, interpreter::Register first_arg,
1243 size_t arity) {
1244 Node** all = info()->zone()->NewArray<Node*>(arity);
1245 int first_arg_index = first_arg.index();
1246 for (int i = 0; i < static_cast<int>(arity); ++i) {
1247 all[i] = environment()->LookupRegister(
1248 interpreter::Register(first_arg_index + i));
1249 }
1250 Node* value = MakeNode(call_runtime_op, static_cast<int>(arity), all, false);
1251 return value;
1252 }
1253
1254
VisitCallRuntime(const interpreter::BytecodeArrayIterator & iterator)1255 void BytecodeGraphBuilder::VisitCallRuntime(
1256 const interpreter::BytecodeArrayIterator& iterator) {
1257 FrameStateBeforeAndAfter states(this, iterator);
1258 Runtime::FunctionId functionId =
1259 static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0));
1260 interpreter::Register first_arg = iterator.GetRegisterOperand(1);
1261 size_t arg_count = iterator.GetCountOperand(2);
1262
1263 // Create node to perform the runtime call.
1264 const Operator* call = javascript()->CallRuntime(functionId, arg_count);
1265 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count);
1266 environment()->BindAccumulator(value, &states);
1267 }
1268
1269
VisitCallRuntimeForPair(const interpreter::BytecodeArrayIterator & iterator)1270 void BytecodeGraphBuilder::VisitCallRuntimeForPair(
1271 const interpreter::BytecodeArrayIterator& iterator) {
1272 FrameStateBeforeAndAfter states(this, iterator);
1273 Runtime::FunctionId functionId =
1274 static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0));
1275 interpreter::Register first_arg = iterator.GetRegisterOperand(1);
1276 size_t arg_count = iterator.GetCountOperand(2);
1277 interpreter::Register first_return = iterator.GetRegisterOperand(3);
1278
1279 // Create node to perform the runtime call.
1280 const Operator* call = javascript()->CallRuntime(functionId, arg_count);
1281 Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count);
1282 environment()->BindRegistersToProjections(first_return, return_pair, &states);
1283 }
1284
1285
ProcessCallNewArguments(const Operator * call_new_op,interpreter::Register callee,interpreter::Register first_arg,size_t arity)1286 Node* BytecodeGraphBuilder::ProcessCallNewArguments(
1287 const Operator* call_new_op, interpreter::Register callee,
1288 interpreter::Register first_arg, size_t arity) {
1289 Node** all = info()->zone()->NewArray<Node*>(arity);
1290 all[0] = environment()->LookupRegister(callee);
1291 int first_arg_index = first_arg.index();
1292 for (int i = 1; i < static_cast<int>(arity) - 1; ++i) {
1293 all[i] = environment()->LookupRegister(
1294 interpreter::Register(first_arg_index + i - 1));
1295 }
1296 // Original constructor is the same as the callee.
1297 all[arity - 1] = environment()->LookupRegister(callee);
1298 Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false);
1299 return value;
1300 }
1301
1302
VisitNew(const interpreter::BytecodeArrayIterator & iterator)1303 void BytecodeGraphBuilder::VisitNew(
1304 const interpreter::BytecodeArrayIterator& iterator) {
1305 FrameStateBeforeAndAfter states(this, iterator);
1306 interpreter::Register callee = iterator.GetRegisterOperand(0);
1307 interpreter::Register first_arg = iterator.GetRegisterOperand(1);
1308 size_t arg_count = iterator.GetCountOperand(2);
1309
1310 // TODO(turbofan): Pass the feedback here.
1311 const Operator* call = javascript()->CallConstruct(
1312 static_cast<int>(arg_count) + 2, VectorSlotPair());
1313 Node* value = ProcessCallNewArguments(call, callee, first_arg, arg_count + 2);
1314 environment()->BindAccumulator(value, &states);
1315 }
1316
1317
VisitThrow(const interpreter::BytecodeArrayIterator & iterator)1318 void BytecodeGraphBuilder::VisitThrow(
1319 const interpreter::BytecodeArrayIterator& iterator) {
1320 FrameStateBeforeAndAfter states(this, iterator);
1321 Node* value = environment()->LookupAccumulator();
1322 // TODO(mythria): Change to Runtime::kThrow when we have deoptimization
1323 // information support in the interpreter.
1324 NewNode(javascript()->CallRuntime(Runtime::kReThrow, 1), value);
1325 Node* control = NewNode(common()->Throw(), value);
1326 environment()->RecordAfterState(control, &states);
1327 UpdateControlDependencyToLeaveFunction(control);
1328 }
1329
1330
BuildBinaryOp(const Operator * js_op,const interpreter::BytecodeArrayIterator & iterator)1331 void BytecodeGraphBuilder::BuildBinaryOp(
1332 const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
1333 FrameStateBeforeAndAfter states(this, iterator);
1334 Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1335 Node* right = environment()->LookupAccumulator();
1336 Node* node = NewNode(js_op, left, right);
1337 environment()->BindAccumulator(node, &states);
1338 }
1339
1340
VisitAdd(const interpreter::BytecodeArrayIterator & iterator)1341 void BytecodeGraphBuilder::VisitAdd(
1342 const interpreter::BytecodeArrayIterator& iterator) {
1343 BinaryOperationHints hints = BinaryOperationHints::Any();
1344 BuildBinaryOp(javascript()->Add(language_mode(), hints), iterator);
1345 }
1346
1347
VisitSub(const interpreter::BytecodeArrayIterator & iterator)1348 void BytecodeGraphBuilder::VisitSub(
1349 const interpreter::BytecodeArrayIterator& iterator) {
1350 BinaryOperationHints hints = BinaryOperationHints::Any();
1351 BuildBinaryOp(javascript()->Subtract(language_mode(), hints), iterator);
1352 }
1353
1354
VisitMul(const interpreter::BytecodeArrayIterator & iterator)1355 void BytecodeGraphBuilder::VisitMul(
1356 const interpreter::BytecodeArrayIterator& iterator) {
1357 BinaryOperationHints hints = BinaryOperationHints::Any();
1358 BuildBinaryOp(javascript()->Multiply(language_mode(), hints), iterator);
1359 }
1360
1361
VisitDiv(const interpreter::BytecodeArrayIterator & iterator)1362 void BytecodeGraphBuilder::VisitDiv(
1363 const interpreter::BytecodeArrayIterator& iterator) {
1364 BinaryOperationHints hints = BinaryOperationHints::Any();
1365 BuildBinaryOp(javascript()->Divide(language_mode(), hints), iterator);
1366 }
1367
1368
VisitMod(const interpreter::BytecodeArrayIterator & iterator)1369 void BytecodeGraphBuilder::VisitMod(
1370 const interpreter::BytecodeArrayIterator& iterator) {
1371 BinaryOperationHints hints = BinaryOperationHints::Any();
1372 BuildBinaryOp(javascript()->Modulus(language_mode(), hints), iterator);
1373 }
1374
1375
VisitBitwiseOr(const interpreter::BytecodeArrayIterator & iterator)1376 void BytecodeGraphBuilder::VisitBitwiseOr(
1377 const interpreter::BytecodeArrayIterator& iterator) {
1378 BinaryOperationHints hints = BinaryOperationHints::Any();
1379 BuildBinaryOp(javascript()->BitwiseOr(language_mode(), hints), iterator);
1380 }
1381
1382
VisitBitwiseXor(const interpreter::BytecodeArrayIterator & iterator)1383 void BytecodeGraphBuilder::VisitBitwiseXor(
1384 const interpreter::BytecodeArrayIterator& iterator) {
1385 BinaryOperationHints hints = BinaryOperationHints::Any();
1386 BuildBinaryOp(javascript()->BitwiseXor(language_mode(), hints), iterator);
1387 }
1388
1389
VisitBitwiseAnd(const interpreter::BytecodeArrayIterator & iterator)1390 void BytecodeGraphBuilder::VisitBitwiseAnd(
1391 const interpreter::BytecodeArrayIterator& iterator) {
1392 BinaryOperationHints hints = BinaryOperationHints::Any();
1393 BuildBinaryOp(javascript()->BitwiseAnd(language_mode(), hints), iterator);
1394 }
1395
1396
VisitShiftLeft(const interpreter::BytecodeArrayIterator & iterator)1397 void BytecodeGraphBuilder::VisitShiftLeft(
1398 const interpreter::BytecodeArrayIterator& iterator) {
1399 BinaryOperationHints hints = BinaryOperationHints::Any();
1400 BuildBinaryOp(javascript()->ShiftLeft(language_mode(), hints), iterator);
1401 }
1402
1403
VisitShiftRight(const interpreter::BytecodeArrayIterator & iterator)1404 void BytecodeGraphBuilder::VisitShiftRight(
1405 const interpreter::BytecodeArrayIterator& iterator) {
1406 BinaryOperationHints hints = BinaryOperationHints::Any();
1407 BuildBinaryOp(javascript()->ShiftRight(language_mode(), hints), iterator);
1408 }
1409
1410
VisitShiftRightLogical(const interpreter::BytecodeArrayIterator & iterator)1411 void BytecodeGraphBuilder::VisitShiftRightLogical(
1412 const interpreter::BytecodeArrayIterator& iterator) {
1413 BinaryOperationHints hints = BinaryOperationHints::Any();
1414 BuildBinaryOp(javascript()->ShiftRightLogical(language_mode(), hints),
1415 iterator);
1416 }
1417
1418
VisitInc(const interpreter::BytecodeArrayIterator & iterator)1419 void BytecodeGraphBuilder::VisitInc(
1420 const interpreter::BytecodeArrayIterator& iterator) {
1421 FrameStateBeforeAndAfter states(this, iterator);
1422 const Operator* js_op =
1423 javascript()->Add(language_mode(), BinaryOperationHints::Any());
1424 Node* node = NewNode(js_op, environment()->LookupAccumulator(),
1425 jsgraph()->OneConstant());
1426 environment()->BindAccumulator(node, &states);
1427 }
1428
1429
VisitDec(const interpreter::BytecodeArrayIterator & iterator)1430 void BytecodeGraphBuilder::VisitDec(
1431 const interpreter::BytecodeArrayIterator& iterator) {
1432 FrameStateBeforeAndAfter states(this, iterator);
1433 const Operator* js_op =
1434 javascript()->Subtract(language_mode(), BinaryOperationHints::Any());
1435 Node* node = NewNode(js_op, environment()->LookupAccumulator(),
1436 jsgraph()->OneConstant());
1437 environment()->BindAccumulator(node, &states);
1438 }
1439
1440
VisitLogicalNot(const interpreter::BytecodeArrayIterator & iterator)1441 void BytecodeGraphBuilder::VisitLogicalNot(
1442 const interpreter::BytecodeArrayIterator& iterator) {
1443 Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
1444 environment()->LookupAccumulator());
1445 Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value,
1446 jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
1447 environment()->BindAccumulator(node);
1448 }
1449
1450
VisitTypeOf(const interpreter::BytecodeArrayIterator & iterator)1451 void BytecodeGraphBuilder::VisitTypeOf(
1452 const interpreter::BytecodeArrayIterator& iterator) {
1453 Node* node =
1454 NewNode(javascript()->TypeOf(), environment()->LookupAccumulator());
1455 environment()->BindAccumulator(node);
1456 }
1457
1458
BuildDelete(const interpreter::BytecodeArrayIterator & iterator)1459 void BytecodeGraphBuilder::BuildDelete(
1460 const interpreter::BytecodeArrayIterator& iterator) {
1461 FrameStateBeforeAndAfter states(this, iterator);
1462 Node* key = environment()->LookupAccumulator();
1463 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1464 Node* node =
1465 NewNode(javascript()->DeleteProperty(language_mode()), object, key);
1466 environment()->BindAccumulator(node, &states);
1467 }
1468
1469
VisitDeletePropertyStrict(const interpreter::BytecodeArrayIterator & iterator)1470 void BytecodeGraphBuilder::VisitDeletePropertyStrict(
1471 const interpreter::BytecodeArrayIterator& iterator) {
1472 DCHECK(is_strict(language_mode()));
1473 BuildDelete(iterator);
1474 }
1475
1476
VisitDeletePropertySloppy(const interpreter::BytecodeArrayIterator & iterator)1477 void BytecodeGraphBuilder::VisitDeletePropertySloppy(
1478 const interpreter::BytecodeArrayIterator& iterator) {
1479 DCHECK(is_sloppy(language_mode()));
1480 BuildDelete(iterator);
1481 }
1482
1483
VisitDeleteLookupSlot(const interpreter::BytecodeArrayIterator & iterator)1484 void BytecodeGraphBuilder::VisitDeleteLookupSlot(
1485 const interpreter::BytecodeArrayIterator& iterator) {
1486 FrameStateBeforeAndAfter states(this, iterator);
1487 Node* name = environment()->LookupAccumulator();
1488 const Operator* op = javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2);
1489 Node* result = NewNode(op, environment()->Context(), name);
1490 environment()->BindAccumulator(result, &states);
1491 }
1492
1493
BuildCompareOp(const Operator * js_op,const interpreter::BytecodeArrayIterator & iterator)1494 void BytecodeGraphBuilder::BuildCompareOp(
1495 const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
1496 FrameStateBeforeAndAfter states(this, iterator);
1497 Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1498 Node* right = environment()->LookupAccumulator();
1499 Node* node = NewNode(js_op, left, right);
1500 environment()->BindAccumulator(node, &states);
1501 }
1502
1503
VisitTestEqual(const interpreter::BytecodeArrayIterator & iterator)1504 void BytecodeGraphBuilder::VisitTestEqual(
1505 const interpreter::BytecodeArrayIterator& iterator) {
1506 BuildCompareOp(javascript()->Equal(), iterator);
1507 }
1508
1509
VisitTestNotEqual(const interpreter::BytecodeArrayIterator & iterator)1510 void BytecodeGraphBuilder::VisitTestNotEqual(
1511 const interpreter::BytecodeArrayIterator& iterator) {
1512 BuildCompareOp(javascript()->NotEqual(), iterator);
1513 }
1514
1515
VisitTestEqualStrict(const interpreter::BytecodeArrayIterator & iterator)1516 void BytecodeGraphBuilder::VisitTestEqualStrict(
1517 const interpreter::BytecodeArrayIterator& iterator) {
1518 BuildCompareOp(javascript()->StrictEqual(), iterator);
1519 }
1520
1521
VisitTestNotEqualStrict(const interpreter::BytecodeArrayIterator & iterator)1522 void BytecodeGraphBuilder::VisitTestNotEqualStrict(
1523 const interpreter::BytecodeArrayIterator& iterator) {
1524 BuildCompareOp(javascript()->StrictNotEqual(), iterator);
1525 }
1526
1527
VisitTestLessThan(const interpreter::BytecodeArrayIterator & iterator)1528 void BytecodeGraphBuilder::VisitTestLessThan(
1529 const interpreter::BytecodeArrayIterator& iterator) {
1530 BuildCompareOp(javascript()->LessThan(language_mode()), iterator);
1531 }
1532
1533
VisitTestGreaterThan(const interpreter::BytecodeArrayIterator & iterator)1534 void BytecodeGraphBuilder::VisitTestGreaterThan(
1535 const interpreter::BytecodeArrayIterator& iterator) {
1536 BuildCompareOp(javascript()->GreaterThan(language_mode()), iterator);
1537 }
1538
1539
VisitTestLessThanOrEqual(const interpreter::BytecodeArrayIterator & iterator)1540 void BytecodeGraphBuilder::VisitTestLessThanOrEqual(
1541 const interpreter::BytecodeArrayIterator& iterator) {
1542 BuildCompareOp(javascript()->LessThanOrEqual(language_mode()), iterator);
1543 }
1544
1545
VisitTestGreaterThanOrEqual(const interpreter::BytecodeArrayIterator & iterator)1546 void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual(
1547 const interpreter::BytecodeArrayIterator& iterator) {
1548 BuildCompareOp(javascript()->GreaterThanOrEqual(language_mode()), iterator);
1549 }
1550
1551
VisitTestIn(const interpreter::BytecodeArrayIterator & iterator)1552 void BytecodeGraphBuilder::VisitTestIn(
1553 const interpreter::BytecodeArrayIterator& iterator) {
1554 BuildCompareOp(javascript()->HasProperty(), iterator);
1555 }
1556
1557
VisitTestInstanceOf(const interpreter::BytecodeArrayIterator & iterator)1558 void BytecodeGraphBuilder::VisitTestInstanceOf(
1559 const interpreter::BytecodeArrayIterator& iterator) {
1560 BuildCompareOp(javascript()->InstanceOf(), iterator);
1561 }
1562
1563
BuildCastOperator(const Operator * js_op,const interpreter::BytecodeArrayIterator & iterator)1564 void BytecodeGraphBuilder::BuildCastOperator(
1565 const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
1566 FrameStateBeforeAndAfter states(this, iterator);
1567 Node* node = NewNode(js_op, environment()->LookupAccumulator());
1568 environment()->BindAccumulator(node, &states);
1569 }
1570
1571
VisitToName(const interpreter::BytecodeArrayIterator & iterator)1572 void BytecodeGraphBuilder::VisitToName(
1573 const interpreter::BytecodeArrayIterator& iterator) {
1574 BuildCastOperator(javascript()->ToName(), iterator);
1575 }
1576
1577
VisitToObject(const interpreter::BytecodeArrayIterator & iterator)1578 void BytecodeGraphBuilder::VisitToObject(
1579 const interpreter::BytecodeArrayIterator& iterator) {
1580 BuildCastOperator(javascript()->ToObject(), iterator);
1581 }
1582
1583
VisitToNumber(const interpreter::BytecodeArrayIterator & iterator)1584 void BytecodeGraphBuilder::VisitToNumber(
1585 const interpreter::BytecodeArrayIterator& iterator) {
1586 BuildCastOperator(javascript()->ToNumber(), iterator);
1587 }
1588
1589
VisitJump(const interpreter::BytecodeArrayIterator & iterator)1590 void BytecodeGraphBuilder::VisitJump(
1591 const interpreter::BytecodeArrayIterator& iterator) {
1592 BuildJump();
1593 }
1594
1595
VisitJumpConstant(const interpreter::BytecodeArrayIterator & iterator)1596 void BytecodeGraphBuilder::VisitJumpConstant(
1597 const interpreter::BytecodeArrayIterator& iterator) {
1598 BuildJump();
1599 }
1600
1601
VisitJumpConstantWide(const interpreter::BytecodeArrayIterator & iterator)1602 void BytecodeGraphBuilder::VisitJumpConstantWide(
1603 const interpreter::BytecodeArrayIterator& iterator) {
1604 BuildJump();
1605 }
1606
1607
VisitJumpIfTrue(const interpreter::BytecodeArrayIterator & iterator)1608 void BytecodeGraphBuilder::VisitJumpIfTrue(
1609 const interpreter::BytecodeArrayIterator& iterator) {
1610 BuildJumpIfEqual(jsgraph()->TrueConstant());
1611 }
1612
1613
VisitJumpIfTrueConstant(const interpreter::BytecodeArrayIterator & iterator)1614 void BytecodeGraphBuilder::VisitJumpIfTrueConstant(
1615 const interpreter::BytecodeArrayIterator& iterator) {
1616 BuildJumpIfEqual(jsgraph()->TrueConstant());
1617 }
1618
1619
VisitJumpIfTrueConstantWide(const interpreter::BytecodeArrayIterator & iterator)1620 void BytecodeGraphBuilder::VisitJumpIfTrueConstantWide(
1621 const interpreter::BytecodeArrayIterator& iterator) {
1622 BuildJumpIfEqual(jsgraph()->TrueConstant());
1623 }
1624
1625
VisitJumpIfFalse(const interpreter::BytecodeArrayIterator & iterator)1626 void BytecodeGraphBuilder::VisitJumpIfFalse(
1627 const interpreter::BytecodeArrayIterator& iterator) {
1628 BuildJumpIfEqual(jsgraph()->FalseConstant());
1629 }
1630
1631
VisitJumpIfFalseConstant(const interpreter::BytecodeArrayIterator & iterator)1632 void BytecodeGraphBuilder::VisitJumpIfFalseConstant(
1633 const interpreter::BytecodeArrayIterator& iterator) {
1634 BuildJumpIfEqual(jsgraph()->FalseConstant());
1635 }
1636
1637
VisitJumpIfFalseConstantWide(const interpreter::BytecodeArrayIterator & iterator)1638 void BytecodeGraphBuilder::VisitJumpIfFalseConstantWide(
1639 const interpreter::BytecodeArrayIterator& iterator) {
1640 BuildJumpIfEqual(jsgraph()->FalseConstant());
1641 }
1642
1643
VisitJumpIfToBooleanTrue(const interpreter::BytecodeArrayIterator & iterator)1644 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue(
1645 const interpreter::BytecodeArrayIterator& iterator) {
1646 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant());
1647 }
1648
1649
VisitJumpIfToBooleanTrueConstant(const interpreter::BytecodeArrayIterator & iterator)1650 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant(
1651 const interpreter::BytecodeArrayIterator& iterator) {
1652 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant());
1653 }
1654
1655
VisitJumpIfToBooleanTrueConstantWide(const interpreter::BytecodeArrayIterator & iterator)1656 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstantWide(
1657 const interpreter::BytecodeArrayIterator& iterator) {
1658 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant());
1659 }
1660
1661
VisitJumpIfToBooleanFalse(const interpreter::BytecodeArrayIterator & iterator)1662 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse(
1663 const interpreter::BytecodeArrayIterator& iterator) {
1664 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant());
1665 }
1666
1667
VisitJumpIfToBooleanFalseConstant(const interpreter::BytecodeArrayIterator & iterator)1668 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant(
1669 const interpreter::BytecodeArrayIterator& iterator) {
1670 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant());
1671 }
1672
1673
VisitJumpIfToBooleanFalseConstantWide(const interpreter::BytecodeArrayIterator & iterator)1674 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstantWide(
1675 const interpreter::BytecodeArrayIterator& iterator) {
1676 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant());
1677 }
1678
1679
VisitJumpIfNull(const interpreter::BytecodeArrayIterator & iterator)1680 void BytecodeGraphBuilder::VisitJumpIfNull(
1681 const interpreter::BytecodeArrayIterator& iterator) {
1682 BuildJumpIfEqual(jsgraph()->NullConstant());
1683 }
1684
1685
VisitJumpIfNullConstant(const interpreter::BytecodeArrayIterator & iterator)1686 void BytecodeGraphBuilder::VisitJumpIfNullConstant(
1687 const interpreter::BytecodeArrayIterator& iterator) {
1688 BuildJumpIfEqual(jsgraph()->NullConstant());
1689 }
1690
1691
VisitJumpIfNullConstantWide(const interpreter::BytecodeArrayIterator & iterator)1692 void BytecodeGraphBuilder::VisitJumpIfNullConstantWide(
1693 const interpreter::BytecodeArrayIterator& iterator) {
1694 BuildJumpIfEqual(jsgraph()->NullConstant());
1695 }
1696
1697
VisitJumpIfUndefined(const interpreter::BytecodeArrayIterator & iterator)1698 void BytecodeGraphBuilder::VisitJumpIfUndefined(
1699 const interpreter::BytecodeArrayIterator& iterator) {
1700 BuildJumpIfEqual(jsgraph()->UndefinedConstant());
1701 }
1702
1703
VisitJumpIfUndefinedConstant(const interpreter::BytecodeArrayIterator & iterator)1704 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant(
1705 const interpreter::BytecodeArrayIterator& iterator) {
1706 BuildJumpIfEqual(jsgraph()->UndefinedConstant());
1707 }
1708
1709
VisitJumpIfUndefinedConstantWide(const interpreter::BytecodeArrayIterator & iterator)1710 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstantWide(
1711 const interpreter::BytecodeArrayIterator& iterator) {
1712 BuildJumpIfEqual(jsgraph()->UndefinedConstant());
1713 }
1714
1715
VisitReturn(const interpreter::BytecodeArrayIterator & iterator)1716 void BytecodeGraphBuilder::VisitReturn(
1717 const interpreter::BytecodeArrayIterator& iterator) {
1718 Node* control =
1719 NewNode(common()->Return(), environment()->LookupAccumulator());
1720 UpdateControlDependencyToLeaveFunction(control);
1721 set_environment(nullptr);
1722 }
1723
1724
VisitForInPrepare(const interpreter::BytecodeArrayIterator & iterator)1725 void BytecodeGraphBuilder::VisitForInPrepare(
1726 const interpreter::BytecodeArrayIterator& iterator) {
1727 Node* prepare = nullptr;
1728 {
1729 FrameStateBeforeAndAfter states(this, iterator);
1730 Node* receiver = environment()->LookupAccumulator();
1731 prepare = NewNode(javascript()->ForInPrepare(), receiver);
1732 environment()->RecordAfterState(prepare, &states);
1733 }
1734 // Project cache_type, cache_array, cache_length into register
1735 // operands 1, 2, 3.
1736 for (int i = 0; i < 3; i++) {
1737 environment()->BindRegister(iterator.GetRegisterOperand(i),
1738 NewNode(common()->Projection(i), prepare));
1739 }
1740 }
1741
1742
VisitForInDone(const interpreter::BytecodeArrayIterator & iterator)1743 void BytecodeGraphBuilder::VisitForInDone(
1744 const interpreter::BytecodeArrayIterator& iterator) {
1745 FrameStateBeforeAndAfter states(this, iterator);
1746 Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1747 Node* cache_length =
1748 environment()->LookupRegister(iterator.GetRegisterOperand(1));
1749 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1750 environment()->BindAccumulator(exit_cond, &states);
1751 }
1752
1753
VisitForInNext(const interpreter::BytecodeArrayIterator & iterator)1754 void BytecodeGraphBuilder::VisitForInNext(
1755 const interpreter::BytecodeArrayIterator& iterator) {
1756 FrameStateBeforeAndAfter states(this, iterator);
1757 Node* receiver =
1758 environment()->LookupRegister(iterator.GetRegisterOperand(0));
1759 Node* cache_type =
1760 environment()->LookupRegister(iterator.GetRegisterOperand(1));
1761 Node* cache_array =
1762 environment()->LookupRegister(iterator.GetRegisterOperand(2));
1763 Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(3));
1764 Node* value = NewNode(javascript()->ForInNext(), receiver, cache_array,
1765 cache_type, index);
1766 environment()->BindAccumulator(value, &states);
1767 }
1768
1769
VisitForInStep(const interpreter::BytecodeArrayIterator & iterator)1770 void BytecodeGraphBuilder::VisitForInStep(
1771 const interpreter::BytecodeArrayIterator& iterator) {
1772 FrameStateBeforeAndAfter states(this, iterator);
1773 Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(0));
1774 index = NewNode(javascript()->ForInStep(), index);
1775 environment()->BindAccumulator(index, &states);
1776 }
1777
1778
MergeEnvironmentsOfBackwardBranches(int source_offset,int target_offset)1779 void BytecodeGraphBuilder::MergeEnvironmentsOfBackwardBranches(
1780 int source_offset, int target_offset) {
1781 DCHECK_GE(source_offset, target_offset);
1782 const ZoneVector<int>* branch_sites =
1783 branch_analysis()->BackwardBranchesTargetting(target_offset);
1784 if (branch_sites->back() == source_offset) {
1785 // The set of back branches is complete, merge them.
1786 DCHECK_GE(branch_sites->at(0), target_offset);
1787 Environment* merged = merge_environments_[branch_sites->at(0)];
1788 for (size_t i = 1; i < branch_sites->size(); i++) {
1789 DCHECK_GE(branch_sites->at(i), target_offset);
1790 merged->Merge(merge_environments_[branch_sites->at(i)]);
1791 }
1792 // And now merge with loop header environment created when loop
1793 // header was visited.
1794 loop_header_environments_[target_offset]->Merge(merged);
1795 }
1796 }
1797
1798
MergeEnvironmentsOfForwardBranches(int source_offset)1799 void BytecodeGraphBuilder::MergeEnvironmentsOfForwardBranches(
1800 int source_offset) {
1801 if (branch_analysis()->forward_branches_target(source_offset)) {
1802 // Merge environments of branches that reach this bytecode.
1803 auto branch_sites =
1804 branch_analysis()->ForwardBranchesTargetting(source_offset);
1805 DCHECK_LT(branch_sites->at(0), source_offset);
1806 Environment* merged = merge_environments_[branch_sites->at(0)];
1807 for (size_t i = 1; i < branch_sites->size(); i++) {
1808 DCHECK_LT(branch_sites->at(i), source_offset);
1809 merged->Merge(merge_environments_[branch_sites->at(i)]);
1810 }
1811 if (environment()) {
1812 merged->Merge(environment());
1813 }
1814 set_environment(merged);
1815 }
1816 }
1817
1818
BuildLoopHeaderForBackwardBranches(int source_offset)1819 void BytecodeGraphBuilder::BuildLoopHeaderForBackwardBranches(
1820 int source_offset) {
1821 if (branch_analysis()->backward_branches_target(source_offset)) {
1822 // Add loop header and store a copy so we can connect merged back
1823 // edge inputs to the loop header.
1824 loop_header_environments_[source_offset] = environment()->CopyForLoop();
1825 }
1826 }
1827
1828
BuildJump(int source_offset,int target_offset)1829 void BytecodeGraphBuilder::BuildJump(int source_offset, int target_offset) {
1830 DCHECK_NULL(merge_environments_[source_offset]);
1831 merge_environments_[source_offset] = environment();
1832 if (source_offset >= target_offset) {
1833 MergeEnvironmentsOfBackwardBranches(source_offset, target_offset);
1834 }
1835 set_environment(nullptr);
1836 }
1837
1838
BuildJump()1839 void BytecodeGraphBuilder::BuildJump() {
1840 int source_offset = bytecode_iterator()->current_offset();
1841 int target_offset = bytecode_iterator()->GetJumpTargetOffset();
1842 BuildJump(source_offset, target_offset);
1843 }
1844
1845
BuildConditionalJump(Node * condition)1846 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) {
1847 int source_offset = bytecode_iterator()->current_offset();
1848 NewBranch(condition);
1849 Environment* if_false_environment = environment()->CopyForConditional();
1850 NewIfTrue();
1851 BuildJump(source_offset, bytecode_iterator()->GetJumpTargetOffset());
1852 set_environment(if_false_environment);
1853 NewIfFalse();
1854 }
1855
1856
BuildJumpIfEqual(Node * comperand)1857 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
1858 Node* accumulator = environment()->LookupAccumulator();
1859 Node* condition =
1860 NewNode(javascript()->StrictEqual(), accumulator, comperand);
1861 BuildConditionalJump(condition);
1862 }
1863
1864
BuildJumpIfToBooleanEqual(Node * comperand)1865 void BytecodeGraphBuilder::BuildJumpIfToBooleanEqual(Node* comperand) {
1866 Node* accumulator = environment()->LookupAccumulator();
1867 Node* to_boolean =
1868 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator);
1869 Node* condition = NewNode(javascript()->StrictEqual(), to_boolean, comperand);
1870 BuildConditionalJump(condition);
1871 }
1872
1873
EnsureInputBufferSize(int size)1874 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
1875 if (size > input_buffer_size_) {
1876 size = size + kInputBufferSizeIncrement + input_buffer_size_;
1877 input_buffer_ = local_zone()->NewArray<Node*>(size);
1878 input_buffer_size_ = size;
1879 }
1880 return input_buffer_;
1881 }
1882
1883
PrepareEntryFrameState(Node * node)1884 void BytecodeGraphBuilder::PrepareEntryFrameState(Node* node) {
1885 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
1886 DCHECK_EQ(IrOpcode::kDead,
1887 NodeProperties::GetFrameStateInput(node, 0)->opcode());
1888 NodeProperties::ReplaceFrameStateInput(
1889 node, 0, environment()->Checkpoint(BailoutId(0),
1890 OutputFrameStateCombine::Ignore()));
1891 }
1892
1893
MakeNode(const Operator * op,int value_input_count,Node ** value_inputs,bool incomplete)1894 Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
1895 Node** value_inputs, bool incomplete) {
1896 DCHECK_EQ(op->ValueInputCount(), value_input_count);
1897
1898 bool has_context = OperatorProperties::HasContextInput(op);
1899 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
1900 bool has_control = op->ControlInputCount() == 1;
1901 bool has_effect = op->EffectInputCount() == 1;
1902
1903 DCHECK_LT(op->ControlInputCount(), 2);
1904 DCHECK_LT(op->EffectInputCount(), 2);
1905
1906 Node* result = nullptr;
1907 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
1908 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
1909 } else {
1910 int input_count_with_deps = value_input_count;
1911 if (has_context) ++input_count_with_deps;
1912 input_count_with_deps += frame_state_count;
1913 if (has_control) ++input_count_with_deps;
1914 if (has_effect) ++input_count_with_deps;
1915 Node** buffer = EnsureInputBufferSize(input_count_with_deps);
1916 memcpy(buffer, value_inputs, kPointerSize * value_input_count);
1917 Node** current_input = buffer + value_input_count;
1918 if (has_context) {
1919 *current_input++ = environment()->Context();
1920 }
1921 for (int i = 0; i < frame_state_count; i++) {
1922 // The frame state will be inserted later. Here we misuse
1923 // the {Dead} node as a sentinel to be later overwritten
1924 // with the real frame state.
1925 *current_input++ = jsgraph()->Dead();
1926 }
1927 if (has_effect) {
1928 *current_input++ = environment()->GetEffectDependency();
1929 }
1930 if (has_control) {
1931 *current_input++ = environment()->GetControlDependency();
1932 }
1933 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
1934 if (!environment()->IsMarkedAsUnreachable()) {
1935 // Update the current control dependency for control-producing nodes.
1936 if (NodeProperties::IsControl(result)) {
1937 environment()->UpdateControlDependency(result);
1938 }
1939 // Update the current effect dependency for effect-producing nodes.
1940 if (result->op()->EffectOutputCount() > 0) {
1941 environment()->UpdateEffectDependency(result);
1942 }
1943 // Add implicit success continuation for throwing nodes.
1944 if (!result->op()->HasProperty(Operator::kNoThrow)) {
1945 const Operator* if_success = common()->IfSuccess();
1946 Node* on_success = graph()->NewNode(if_success, result);
1947 environment_->UpdateControlDependency(on_success);
1948 }
1949 }
1950 }
1951
1952 return result;
1953 }
1954
1955
NewPhi(int count,Node * input,Node * control)1956 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) {
1957 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
1958 Node** buffer = EnsureInputBufferSize(count + 1);
1959 MemsetPointer(buffer, input, count);
1960 buffer[count] = control;
1961 return graph()->NewNode(phi_op, count + 1, buffer, true);
1962 }
1963
1964
NewEffectPhi(int count,Node * input,Node * control)1965 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input,
1966 Node* control) {
1967 const Operator* phi_op = common()->EffectPhi(count);
1968 Node** buffer = EnsureInputBufferSize(count + 1);
1969 MemsetPointer(buffer, input, count);
1970 buffer[count] = control;
1971 return graph()->NewNode(phi_op, count + 1, buffer, true);
1972 }
1973
1974
MergeControl(Node * control,Node * other)1975 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
1976 int inputs = control->op()->ControlInputCount() + 1;
1977 if (control->opcode() == IrOpcode::kLoop) {
1978 // Control node for loop exists, add input.
1979 const Operator* op = common()->Loop(inputs);
1980 control->AppendInput(graph_zone(), other);
1981 NodeProperties::ChangeOp(control, op);
1982 } else if (control->opcode() == IrOpcode::kMerge) {
1983 // Control node for merge exists, add input.
1984 const Operator* op = common()->Merge(inputs);
1985 control->AppendInput(graph_zone(), other);
1986 NodeProperties::ChangeOp(control, op);
1987 } else {
1988 // Control node is a singleton, introduce a merge.
1989 const Operator* op = common()->Merge(inputs);
1990 Node* merge_inputs[] = {control, other};
1991 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true);
1992 }
1993 return control;
1994 }
1995
1996
MergeEffect(Node * value,Node * other,Node * control)1997 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
1998 Node* control) {
1999 int inputs = control->op()->ControlInputCount();
2000 if (value->opcode() == IrOpcode::kEffectPhi &&
2001 NodeProperties::GetControlInput(value) == control) {
2002 // Phi already exists, add input.
2003 value->InsertInput(graph_zone(), inputs - 1, other);
2004 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
2005 } else if (value != other) {
2006 // Phi does not exist yet, introduce one.
2007 value = NewEffectPhi(inputs, value, control);
2008 value->ReplaceInput(inputs - 1, other);
2009 }
2010 return value;
2011 }
2012
2013
MergeValue(Node * value,Node * other,Node * control)2014 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
2015 Node* control) {
2016 int inputs = control->op()->ControlInputCount();
2017 if (value->opcode() == IrOpcode::kPhi &&
2018 NodeProperties::GetControlInput(value) == control) {
2019 // Phi already exists, add input.
2020 value->InsertInput(graph_zone(), inputs - 1, other);
2021 NodeProperties::ChangeOp(
2022 value, common()->Phi(MachineRepresentation::kTagged, inputs));
2023 } else if (value != other) {
2024 // Phi does not exist yet, introduce one.
2025 value = NewPhi(inputs, value, control);
2026 value->ReplaceInput(inputs - 1, other);
2027 }
2028 return value;
2029 }
2030
2031
UpdateControlDependencyToLeaveFunction(Node * exit)2032 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
2033 if (environment()->IsMarkedAsUnreachable()) return;
2034 environment()->MarkAsUnreachable();
2035 exit_controls_.push_back(exit);
2036 }
2037
2038 } // namespace compiler
2039 } // namespace internal
2040 } // namespace v8
2041