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