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