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