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