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