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/operator-properties.h"
13 : #include "src/compiler/simplified-operator.h"
14 : #include "src/interpreter/bytecodes.h"
15 : #include "src/objects-inl.h"
16 : #include "src/objects/literal-objects.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 : namespace compiler {
21 :
22 : // The abstract execution environment simulates the content of the interpreter
23 : // register file. The environment performs SSA-renaming of all tracked nodes at
24 : // split and merge points in the control flow.
25 : class BytecodeGraphBuilder::Environment : public ZoneObject {
26 : public:
27 : Environment(BytecodeGraphBuilder* builder, int register_count,
28 : int parameter_count, Node* control_dependency, Node* context);
29 :
30 : // Specifies whether environment binding methods should attach frame state
31 : // inputs to nodes representing the value being bound. This is done because
32 : // the {OutputFrameStateCombine} is closely related to the binding method.
33 : enum FrameStateAttachmentMode { kAttachFrameState, kDontAttachFrameState };
34 :
35 : int parameter_count() const { return parameter_count_; }
36 : int register_count() const { return register_count_; }
37 :
38 : Node* LookupAccumulator() const;
39 : Node* LookupRegister(interpreter::Register the_register) const;
40 :
41 : void BindAccumulator(Node* node,
42 : FrameStateAttachmentMode mode = kDontAttachFrameState);
43 : void BindRegister(interpreter::Register the_register, Node* node,
44 : FrameStateAttachmentMode mode = kDontAttachFrameState);
45 : void BindRegistersToProjections(
46 : interpreter::Register first_reg, Node* node,
47 : FrameStateAttachmentMode mode = kDontAttachFrameState);
48 : void RecordAfterState(Node* node,
49 : FrameStateAttachmentMode mode = kDontAttachFrameState);
50 :
51 : // Effect dependency tracked by this environment.
52 : Node* GetEffectDependency() { return effect_dependency_; }
53 : void UpdateEffectDependency(Node* dependency) {
54 8998573 : effect_dependency_ = dependency;
55 : }
56 :
57 : // Preserve a checkpoint of the environment for the IR graph. Any
58 : // further mutation of the environment will not affect checkpoints.
59 : Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine,
60 : bool owner_has_exception,
61 : const BytecodeLivenessState* liveness);
62 :
63 : // Control dependency tracked by this environment.
64 : Node* GetControlDependency() const { return control_dependency_; }
65 : void UpdateControlDependency(Node* dependency) {
66 8439813 : control_dependency_ = dependency;
67 : }
68 :
69 : Node* Context() const { return context_; }
70 398959 : void SetContext(Node* new_context) { context_ = new_context; }
71 :
72 : Environment* Copy();
73 : void Merge(Environment* other);
74 :
75 : void PrepareForOsrEntry();
76 : void PrepareForLoop(const BytecodeLoopAssignments& assignments);
77 : void PrepareForLoopExit(Node* loop,
78 : const BytecodeLoopAssignments& assignments);
79 :
80 : private:
81 : explicit Environment(const Environment* copy);
82 :
83 : bool StateValuesRequireUpdate(Node** state_values, Node** values, int count);
84 : void UpdateStateValues(Node** state_values, Node** values, int count);
85 : Node* GetStateValuesFromCache(Node** values, int count,
86 : const BitVector* liveness, int liveness_offset);
87 :
88 : int RegisterToValuesIndex(interpreter::Register the_register) const;
89 :
90 2125996 : Zone* zone() const { return builder_->local_zone(); }
91 9686241 : Graph* graph() const { return builder_->graph(); }
92 9632217 : CommonOperatorBuilder* common() const { return builder_->common(); }
93 : BytecodeGraphBuilder* builder() const { return builder_; }
94 : const NodeVector* values() const { return &values_; }
95 : NodeVector* values() { return &values_; }
96 : int register_base() const { return register_base_; }
97 : int accumulator_base() const { return accumulator_base_; }
98 :
99 : BytecodeGraphBuilder* builder_;
100 : int register_count_;
101 : int parameter_count_;
102 : Node* context_;
103 : Node* control_dependency_;
104 : Node* effect_dependency_;
105 : NodeVector values_;
106 : Node* parameters_state_values_;
107 : int register_base_;
108 : int accumulator_base_;
109 : };
110 :
111 :
112 : // Issues:
113 : // - Scopes - intimately tied to AST. Need to eval what is needed.
114 : // - Need to resolve closure parameter treatment.
115 2035056 : BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder,
116 : int register_count,
117 : int parameter_count,
118 : Node* control_dependency,
119 1491573 : Node* context)
120 : : builder_(builder),
121 : register_count_(register_count),
122 : parameter_count_(parameter_count),
123 : context_(context),
124 : control_dependency_(control_dependency),
125 : effect_dependency_(control_dependency),
126 : values_(builder->local_zone()),
127 859512 : parameters_state_values_(nullptr) {
128 : // The layout of values_ is:
129 : //
130 : // [receiver] [parameters] [registers] [accumulator]
131 : //
132 : // parameter[0] is the receiver (this), parameters 1..N are the
133 : // parameters supplied to the method (arg0..argN-1). The accumulator
134 : // is stored separately.
135 :
136 : // Parameters including the receiver
137 1175543 : for (int i = 0; i < parameter_count; i++) {
138 745786 : const char* debug_name = (i == 0) ? "%this" : nullptr;
139 745786 : const Operator* op = common()->Parameter(i, debug_name);
140 1491574 : Node* parameter = builder->graph()->NewNode(op, graph()->start());
141 745787 : values()->push_back(parameter);
142 : }
143 :
144 : // Registers
145 859514 : register_base_ = static_cast<int>(values()->size());
146 429757 : Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
147 859514 : values()->insert(values()->end(), register_count, undefined_constant);
148 :
149 : // Accumulator
150 859514 : accumulator_base_ = static_cast<int>(values()->size());
151 429757 : values()->push_back(undefined_constant);
152 429757 : }
153 :
154 1062998 : BytecodeGraphBuilder::Environment::Environment(
155 1062998 : const BytecodeGraphBuilder::Environment* other)
156 : : builder_(other->builder_),
157 : register_count_(other->register_count_),
158 : parameter_count_(other->parameter_count_),
159 : context_(other->context_),
160 : control_dependency_(other->control_dependency_),
161 : effect_dependency_(other->effect_dependency_),
162 : values_(other->zone()),
163 : parameters_state_values_(other->parameters_state_values_),
164 : register_base_(other->register_base_),
165 2125996 : accumulator_base_(other->accumulator_base_) {
166 : values_ = other->values_;
167 1062998 : }
168 :
169 :
170 0 : int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
171 10396278 : interpreter::Register the_register) const {
172 10396278 : if (the_register.is_parameter()) {
173 950476 : return the_register.ToParameterIndex(parameter_count());
174 : } else {
175 9445802 : return the_register.index() + register_base();
176 : }
177 : }
178 :
179 6805051 : Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
180 13610102 : return values()->at(accumulator_base_);
181 : }
182 :
183 :
184 6090937 : Node* BytecodeGraphBuilder::Environment::LookupRegister(
185 151372 : interpreter::Register the_register) const {
186 6090937 : if (the_register.is_current_context()) {
187 44245 : return Context();
188 6046693 : } else if (the_register.is_function_closure()) {
189 89459 : return builder()->GetFunctionClosure();
190 5957234 : } else if (the_register.is_new_target()) {
191 17668 : return builder()->GetNewTarget();
192 : } else {
193 : int values_index = RegisterToValuesIndex(the_register);
194 11879132 : return values()->at(values_index);
195 : }
196 : }
197 :
198 8166311 : void BytecodeGraphBuilder::Environment::BindAccumulator(
199 3037679 : Node* node, FrameStateAttachmentMode mode) {
200 8166311 : if (mode == FrameStateAttachmentMode::kAttachFrameState) {
201 3037679 : builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0));
202 : }
203 16332624 : values()->at(accumulator_base_) = node;
204 8166312 : }
205 :
206 4454569 : void BytecodeGraphBuilder::Environment::BindRegister(
207 : interpreter::Register the_register, Node* node,
208 58235 : FrameStateAttachmentMode mode) {
209 : int values_index = RegisterToValuesIndex(the_register);
210 4454568 : if (mode == FrameStateAttachmentMode::kAttachFrameState) {
211 : builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
212 116470 : accumulator_base_ - values_index));
213 : }
214 8909136 : values()->at(values_index) = node;
215 4454568 : }
216 :
217 2141 : void BytecodeGraphBuilder::Environment::BindRegistersToProjections(
218 7919 : interpreter::Register first_reg, Node* node,
219 13697 : FrameStateAttachmentMode mode) {
220 : int values_index = RegisterToValuesIndex(first_reg);
221 2141 : if (mode == FrameStateAttachmentMode::kAttachFrameState) {
222 : builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
223 4282 : accumulator_base_ - values_index));
224 : }
225 21616 : for (int i = 0; i < node->op()->ValueOutputCount(); i++) {
226 5778 : values()->at(values_index + i) =
227 17334 : builder()->NewNode(common()->Projection(i), node);
228 : }
229 2141 : }
230 :
231 660300 : void BytecodeGraphBuilder::Environment::RecordAfterState(
232 660300 : Node* node, FrameStateAttachmentMode mode) {
233 660300 : if (mode == FrameStateAttachmentMode::kAttachFrameState) {
234 660300 : builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore());
235 : }
236 660299 : }
237 :
238 1062998 : BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::Environment::Copy() {
239 1062998 : return new (zone()) Environment(this);
240 : }
241 :
242 :
243 770036 : void BytecodeGraphBuilder::Environment::Merge(
244 17191656 : BytecodeGraphBuilder::Environment* other) {
245 : // Create a merge of the control dependencies of both environments and update
246 : // the current environment's control dependency accordingly.
247 : Node* control = builder()->MergeControl(GetControlDependency(),
248 770036 : other->GetControlDependency());
249 : UpdateControlDependency(control);
250 :
251 : // Create a merge of the effect dependencies of both environments and update
252 : // the current environment's effect dependency accordingly.
253 : Node* effect = builder()->MergeEffect(GetEffectDependency(),
254 770036 : other->GetEffectDependency(), control);
255 : UpdateEffectDependency(effect);
256 :
257 : // Introduce Phi nodes for values that have differing input at merge points,
258 : // potentially extending an existing Phi node if possible.
259 1540070 : context_ = builder()->MergeValue(context_, other->context_, control);
260 31303170 : for (size_t i = 0; i < values_.size(); i++) {
261 60296232 : values_[i] = builder()->MergeValue(values_[i], other->values_[i], control);
262 : }
263 770036 : }
264 :
265 45973 : void BytecodeGraphBuilder::Environment::PrepareForLoop(
266 1753007 : const BytecodeLoopAssignments& assignments) {
267 : // Create a control node for the loop header.
268 45973 : Node* control = builder()->NewLoop();
269 :
270 : // Create a Phi for external effects.
271 45973 : Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control);
272 : UpdateEffectDependency(effect);
273 :
274 : // Create Phis for any values that may be updated by the end of the loop.
275 91946 : context_ = builder()->NewPhi(1, context_, control);
276 290438 : for (int i = 0; i < parameter_count(); i++) {
277 99246 : if (assignments.ContainsParameter(i)) {
278 360146 : values_[i] = builder()->NewPhi(1, values_[i], control);
279 : }
280 : }
281 1303043 : for (int i = 0; i < register_count(); i++) {
282 628535 : if (assignments.ContainsLocal(i)) {
283 276463 : int index = register_base() + i;
284 829389 : values_[index] = builder()->NewPhi(1, values_[index], control);
285 : }
286 : }
287 :
288 45973 : if (assignments.ContainsAccumulator()) {
289 45973 : values_[accumulator_base()] =
290 91946 : builder()->NewPhi(1, values_[accumulator_base()], control);
291 : }
292 :
293 : // Connect to the loop end.
294 : Node* terminate = builder()->graph()->NewNode(
295 183892 : builder()->common()->Terminate(), effect, control);
296 45973 : builder()->exit_controls_.push_back(terminate);
297 45973 : }
298 :
299 287510 : void BytecodeGraphBuilder::Environment::PrepareForOsrEntry() {
300 : DCHECK_EQ(IrOpcode::kLoop, GetControlDependency()->opcode());
301 : DCHECK_EQ(1, GetControlDependency()->InputCount());
302 :
303 5750 : Node* start = graph()->start();
304 :
305 : // Create a control node for the OSR entry point and update the current
306 : // environment's dependencies accordingly.
307 5750 : Node* entry = graph()->NewNode(common()->OsrLoopEntry(), start, start);
308 : UpdateControlDependency(entry);
309 : UpdateEffectDependency(entry);
310 :
311 : // Create OSR values for each environment value.
312 : SetContext(graph()->NewNode(
313 5750 : common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), entry));
314 11500 : int size = static_cast<int>(values()->size());
315 54052 : for (int i = 0; i < size; i++) {
316 : int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly.
317 48302 : if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount;
318 48302 : if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex;
319 144906 : values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry);
320 : }
321 :
322 5750 : BailoutId loop_id(builder_->bytecode_iterator().current_offset());
323 : Node* frame_state =
324 5750 : Checkpoint(loop_id, OutputFrameStateCombine::Ignore(), false, nullptr);
325 : Node* checkpoint =
326 5750 : graph()->NewNode(common()->Checkpoint(), frame_state, entry, entry);
327 : UpdateEffectDependency(checkpoint);
328 :
329 : // Create the OSR guard nodes.
330 5750 : const Operator* guard_op = common()->OsrGuard(OsrGuardType::kUninitialized);
331 : Node* effect = checkpoint;
332 54052 : for (int i = 0; i < size; i++) {
333 48302 : values()->at(i) = effect =
334 96604 : graph()->NewNode(guard_op, values()->at(i), effect, entry);
335 : }
336 : Node* context = effect = graph()->NewNode(guard_op, Context(), effect, entry);
337 : SetContext(context);
338 : UpdateEffectDependency(effect);
339 5750 : }
340 :
341 5337492 : bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
342 : Node** state_values, Node** values, int count) {
343 5337492 : if (*state_values == nullptr) {
344 : return true;
345 : }
346 : Node::Inputs inputs = (*state_values)->inputs();
347 5059129 : if (inputs.count() != count) return true;
348 10211589 : for (int i = 0; i < count; i++) {
349 10232264 : if (inputs[i] != values[i]) {
350 : return true;
351 : }
352 : }
353 : return false;
354 : }
355 :
356 181879 : void BytecodeGraphBuilder::Environment::PrepareForLoopExit(
357 14498354 : Node* loop, const BytecodeLoopAssignments& assignments) {
358 : DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);
359 :
360 : Node* control = GetControlDependency();
361 :
362 : // Create the loop exit node.
363 181879 : Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop);
364 : UpdateControlDependency(loop_exit);
365 :
366 : // Rename the effect.
367 : Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
368 181879 : GetEffectDependency(), loop_exit);
369 : UpdateEffectDependency(effect_rename);
370 :
371 : // TODO(jarin) We should also rename context here. However, unconditional
372 : // renaming confuses global object and native context specialization.
373 : // We should only rename if the context is assigned in the loop.
374 :
375 : // Rename the environment values if they were assigned in the loop.
376 1103546 : for (int i = 0; i < parameter_count(); i++) {
377 369893 : if (assignments.ContainsParameter(i)) {
378 : Node* rename =
379 4462867 : graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit);
380 15911 : values_[i] = rename;
381 : }
382 : }
383 8595716 : for (int i = 0; i < register_count(); i++) {
384 4206919 : if (assignments.ContainsLocal(i)) {
385 : Node* rename = graph()->NewNode(common()->LoopExitValue(),
386 6053196 : values_[register_base() + i], loop_exit);
387 4035466 : values_[register_base() + i] = rename;
388 : }
389 : }
390 :
391 181879 : if (assignments.ContainsAccumulator()) {
392 : Node* rename = graph()->NewNode(common()->LoopExitValue(),
393 545637 : values_[accumulator_base()], loop_exit);
394 363758 : values_[accumulator_base()] = rename;
395 : }
396 181879 : }
397 :
398 5337492 : void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
399 : Node** values,
400 598073 : int count) {
401 5337492 : if (StateValuesRequireUpdate(state_values, values, count)) {
402 299037 : const Operator* op = common()->StateValues(count, SparseInputMask::Dense());
403 299036 : (*state_values) = graph()->NewNode(op, count, values);
404 : }
405 5337494 : }
406 :
407 0 : Node* BytecodeGraphBuilder::Environment::GetStateValuesFromCache(
408 : Node** values, int count, const BitVector* liveness, int liveness_offset) {
409 : return builder_->state_values_cache_.GetNodeForValues(
410 12470156 : values, static_cast<size_t>(count), liveness, liveness_offset);
411 : }
412 :
413 5936786 : Node* BytecodeGraphBuilder::Environment::Checkpoint(
414 : BailoutId bailout_id, OutputFrameStateCombine combine,
415 54729590 : bool owner_has_exception, const BytecodeLivenessState* liveness) {
416 5936786 : if (parameter_count() == register_count()) {
417 : // Re-use the state-value cache if the number of local registers happens
418 : // to match the parameter count.
419 : parameters_state_values_ = GetStateValuesFromCache(
420 599295 : &values()->at(0), parameter_count(), nullptr, 0);
421 : } else {
422 : UpdateStateValues(¶meters_state_values_, &values()->at(0),
423 5337491 : parameter_count());
424 : }
425 :
426 : Node* registers_state_values =
427 5936790 : GetStateValuesFromCache(&values()->at(register_base()), register_count(),
428 5936790 : liveness ? &liveness->bit_vector() : nullptr, 0);
429 :
430 11795286 : bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive();
431 : Node* accumulator_state_values;
432 7240739 : if (parameter_count() == 1 && accumulator_is_live &&
433 3911856 : values()->at(accumulator_base()) == values()->at(0)) {
434 : // Re-use the parameter state values if there happens to only be one
435 : // parameter and the accumulator is live and holds that parameter's value.
436 2716 : accumulator_state_values = parameters_state_values_;
437 : } else {
438 : // Otherwise, use the state values cache to hopefully re-use local register
439 : // state values (if there is only one local register), or at the very least
440 : // re-use previous accumulator state values.
441 : accumulator_state_values = GetStateValuesFromCache(
442 5934071 : &values()->at(accumulator_base()), 1,
443 5934071 : liveness ? &liveness->bit_vector() : nullptr, register_count());
444 : }
445 :
446 : const Operator* op = common()->FrameState(
447 11873568 : bailout_id, combine, builder()->frame_state_function_info());
448 : Node* result = graph()->NewNode(
449 : op, parameters_state_values_, registers_state_values,
450 : accumulator_state_values, Context(), builder()->GetFunctionClosure(),
451 17810346 : builder()->graph()->start());
452 :
453 5936788 : return result;
454 : }
455 :
456 429757 : BytecodeGraphBuilder::BytecodeGraphBuilder(
457 : Zone* local_zone, Handle<SharedFunctionInfo> shared_info,
458 : Handle<FeedbackVector> feedback_vector, BailoutId osr_ast_id,
459 : JSGraph* jsgraph, float invocation_frequency,
460 : SourcePositionTable* source_positions, int inlining_id,
461 429757 : JSTypeHintLowering::Flags flags)
462 : : local_zone_(local_zone),
463 : jsgraph_(jsgraph),
464 : invocation_frequency_(invocation_frequency),
465 : bytecode_array_(handle(shared_info->bytecode_array())),
466 : exception_handler_table_(
467 : handle(HandlerTable::cast(bytecode_array()->handler_table()))),
468 : feedback_vector_(feedback_vector),
469 : type_hint_lowering_(jsgraph, feedback_vector, flags),
470 : frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
471 : FrameStateType::kInterpretedFunction,
472 : bytecode_array()->parameter_count(),
473 429757 : bytecode_array()->register_count(), shared_info)),
474 : bytecode_iterator_(nullptr),
475 : bytecode_analysis_(nullptr),
476 : environment_(nullptr),
477 : osr_ast_id_(osr_ast_id),
478 : merge_environments_(local_zone),
479 : exception_handlers_(local_zone),
480 : current_exception_handler_(0),
481 : input_buffer_size_(0),
482 : input_buffer_(nullptr),
483 : needs_eager_checkpoint_(true),
484 : exit_controls_(local_zone),
485 : state_values_cache_(jsgraph),
486 : source_positions_(source_positions),
487 3008298 : start_position_(shared_info->start_position(), inlining_id) {}
488 :
489 38310 : Node* BytecodeGraphBuilder::GetNewTarget() {
490 17668 : if (!new_target_.is_set()) {
491 : int params = bytecode_array()->parameter_count();
492 : int index = Linkage::GetJSCallNewTargetParamIndex(params);
493 10321 : const Operator* op = common()->Parameter(index, "%new.target");
494 10321 : Node* node = NewNode(op, graph()->start());
495 : new_target_.set(node);
496 : }
497 17668 : return new_target_.get();
498 : }
499 :
500 :
501 1289268 : Node* BytecodeGraphBuilder::GetFunctionContext() {
502 429756 : if (!function_context_.is_set()) {
503 : int params = bytecode_array()->parameter_count();
504 : int index = Linkage::GetJSCallContextParamIndex(params);
505 429756 : const Operator* op = common()->Parameter(index, "%context");
506 429756 : Node* node = NewNode(op, graph()->start());
507 : function_context_.set(node);
508 : }
509 429756 : return function_context_.get();
510 : }
511 :
512 :
513 6994934 : Node* BytecodeGraphBuilder::GetFunctionClosure() {
514 6138275 : if (!function_closure_.is_set()) {
515 : int index = Linkage::kJSCallClosureParamIndex;
516 428330 : const Operator* op = common()->Parameter(index, "%closure");
517 428329 : Node* node = NewNode(op, graph()->start());
518 : function_closure_.set(node);
519 : }
520 6138275 : return function_closure_.get();
521 : }
522 :
523 :
524 27832 : Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
525 : const Operator* op =
526 13916 : javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
527 : Node* native_context = NewNode(op);
528 27832 : Node* result = NewNode(javascript()->LoadContext(0, index, true));
529 13916 : NodeProperties::ReplaceContextInput(result, native_context);
530 13916 : return result;
531 : }
532 :
533 :
534 0 : VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
535 : FeedbackSlot slot;
536 2099265 : if (slot_id >= FeedbackVector::kReservedIndexCount) {
537 : slot = feedback_vector()->ToSlot(slot_id);
538 : }
539 0 : return VectorSlotPair(feedback_vector(), slot);
540 : }
541 :
542 3438052 : bool BytecodeGraphBuilder::CreateGraph(bool stack_check) {
543 429756 : SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
544 :
545 : // Set up the basic structure of the graph. Outputs for {Start} are the formal
546 : // parameters (including the receiver) plus new target, number of arguments,
547 : // context and closure.
548 429756 : int actual_parameter_count = bytecode_array()->parameter_count() + 4;
549 429756 : graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
550 :
551 : Environment env(this, bytecode_array()->register_count(),
552 : bytecode_array()->parameter_count(), graph()->start(),
553 1289269 : GetFunctionContext());
554 : set_environment(&env);
555 :
556 429757 : VisitBytecodes(stack_check);
557 :
558 : // Finish the basic structure of the graph.
559 : DCHECK_NE(0u, exit_controls_.size());
560 859514 : int const input_count = static_cast<int>(exit_controls_.size());
561 : Node** const inputs = &exit_controls_.front();
562 1289271 : Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
563 : graph()->SetEnd(end);
564 :
565 429757 : return true;
566 : }
567 :
568 15001589 : void BytecodeGraphBuilder::PrepareEagerCheckpoint() {
569 3547311 : if (needs_eager_checkpoint()) {
570 : // Create an explicit checkpoint node for before the operation. This only
571 : // needs to happen if we aren't effect-dominated by a {Checkpoint} already.
572 : mark_as_needing_eager_checkpoint(false);
573 2863571 : Node* node = NewNode(common()->Checkpoint());
574 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
575 : DCHECK_EQ(IrOpcode::kDead,
576 : NodeProperties::GetFrameStateInput(node)->opcode());
577 2863569 : BailoutId bailout_id(bytecode_iterator().current_offset());
578 :
579 : const BytecodeLivenessState* liveness_before =
580 : bytecode_analysis()->GetInLivenessFor(
581 2863569 : bytecode_iterator().current_offset());
582 :
583 : Node* frame_state_before = environment()->Checkpoint(
584 2863569 : bailout_id, OutputFrameStateCombine::Ignore(), false, liveness_before);
585 2863567 : NodeProperties::ReplaceFrameStateInput(node, frame_state_before);
586 : #ifdef DEBUG
587 : } else {
588 : // In case we skipped checkpoint creation above, we must be able to find an
589 : // existing checkpoint that effect-dominates the nodes about to be created.
590 : // Starting a search from the current effect-dependency has to succeed.
591 : Node* effect = environment()->GetEffectDependency();
592 : while (effect->opcode() != IrOpcode::kCheckpoint) {
593 : DCHECK(effect->op()->HasProperty(Operator::kNoWrite));
594 : DCHECK_EQ(1, effect->op()->EffectInputCount());
595 : effect = NodeProperties::GetEffectInput(effect);
596 : }
597 : }
598 : #else
599 : }
600 : #endif // DEBUG
601 3547308 : }
602 :
603 3758352 : void BytecodeGraphBuilder::PrepareFrameState(Node* node,
604 12269883 : OutputFrameStateCombine combine) {
605 3758352 : if (OperatorProperties::HasFrameStateInput(node->op())) {
606 : // Add the frame state for after the operation. The node in question has
607 : // already been created and had a {Dead} frame state input up until now.
608 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
609 : DCHECK_EQ(IrOpcode::kDead,
610 : NodeProperties::GetFrameStateInput(node)->opcode());
611 3067471 : BailoutId bailout_id(bytecode_iterator().current_offset());
612 3067471 : bool has_exception = NodeProperties::IsExceptionalCall(node);
613 :
614 : const BytecodeLivenessState* liveness_after =
615 : bytecode_analysis()->GetOutLivenessFor(
616 6134940 : bytecode_iterator().current_offset());
617 :
618 : Node* frame_state_after = environment()->Checkpoint(
619 6134944 : bailout_id, combine, has_exception, liveness_after);
620 3067473 : NodeProperties::ReplaceFrameStateInput(node, frame_state_after);
621 : }
622 3758356 : }
623 :
624 15198411 : void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) {
625 429757 : BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone(),
626 859514 : FLAG_analyze_environment_liveness);
627 429757 : bytecode_analysis.Analyze(osr_ast_id_);
628 : set_bytecode_analysis(&bytecode_analysis);
629 :
630 429757 : interpreter::BytecodeArrayIterator iterator(bytecode_array());
631 : set_bytecode_iterator(&iterator);
632 : SourcePositionTableIterator source_position_iterator(
633 429757 : bytecode_array()->SourcePositionTable());
634 :
635 429756 : if (FLAG_trace_environment_liveness) {
636 0 : OFStream of(stdout);
637 :
638 0 : bytecode_analysis.PrintLivenessTo(of);
639 : }
640 :
641 429756 : BuildOSRNormalEntryPoint();
642 :
643 14768657 : for (; !iterator.done(); iterator.Advance()) {
644 14338875 : int current_offset = iterator.current_offset();
645 14338875 : UpdateCurrentSourcePosition(&source_position_iterator, current_offset);
646 14338885 : EnterAndExitExceptionHandlers(current_offset);
647 14338897 : SwitchToMergeEnvironment(current_offset);
648 14338897 : if (environment() != nullptr) {
649 13766690 : BuildLoopHeaderEnvironment(current_offset);
650 :
651 : // Skip the first stack check if stack_check is false
652 13810870 : if (!stack_check &&
653 44174 : iterator.current_bytecode() == interpreter::Bytecode::kStackCheck) {
654 : stack_check = true;
655 : continue;
656 : }
657 :
658 13729043 : switch (iterator.current_bytecode()) {
659 : #define BYTECODE_CASE(name, ...) \
660 : case interpreter::Bytecode::k##name: \
661 : Visit##name(); \
662 : break;
663 865633 : BYTECODE_LIST(BYTECODE_CASE)
664 : #undef BYTECODE_CODE
665 : }
666 : }
667 : }
668 : set_bytecode_analysis(nullptr);
669 : set_bytecode_iterator(nullptr);
670 429757 : DCHECK(exception_handlers_.empty());
671 429757 : }
672 :
673 487465 : void BytecodeGraphBuilder::VisitLdaZero() {
674 243732 : Node* node = jsgraph()->ZeroConstant();
675 243733 : environment()->BindAccumulator(node);
676 243733 : }
677 :
678 3640509 : void BytecodeGraphBuilder::VisitLdaSmi() {
679 2427006 : Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
680 1213503 : environment()->BindAccumulator(node);
681 1213503 : }
682 :
683 1926072 : void BytecodeGraphBuilder::VisitLdaConstant() {
684 : Node* node =
685 1284048 : jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
686 642024 : environment()->BindAccumulator(node);
687 642024 : }
688 :
689 266470 : void BytecodeGraphBuilder::VisitLdaUndefined() {
690 133235 : Node* node = jsgraph()->UndefinedConstant();
691 133235 : environment()->BindAccumulator(node);
692 133235 : }
693 :
694 20354 : void BytecodeGraphBuilder::VisitLdaNull() {
695 10177 : Node* node = jsgraph()->NullConstant();
696 10177 : environment()->BindAccumulator(node);
697 10177 : }
698 :
699 223994 : void BytecodeGraphBuilder::VisitLdaTheHole() {
700 111997 : Node* node = jsgraph()->TheHoleConstant();
701 111997 : environment()->BindAccumulator(node);
702 111997 : }
703 :
704 77460 : void BytecodeGraphBuilder::VisitLdaTrue() {
705 38730 : Node* node = jsgraph()->TrueConstant();
706 38730 : environment()->BindAccumulator(node);
707 38730 : }
708 :
709 166830 : void BytecodeGraphBuilder::VisitLdaFalse() {
710 83415 : Node* node = jsgraph()->FalseConstant();
711 83415 : environment()->BindAccumulator(node);
712 83415 : }
713 :
714 2031216 : void BytecodeGraphBuilder::VisitLdar() {
715 : Node* value =
716 1354144 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
717 677072 : environment()->BindAccumulator(value);
718 677072 : }
719 :
720 11709351 : void BytecodeGraphBuilder::VisitStar() {
721 3903117 : Node* value = environment()->LookupAccumulator();
722 7806234 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value);
723 3903117 : }
724 :
725 1613580 : void BytecodeGraphBuilder::VisitMov() {
726 : Node* value =
727 806790 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
728 806790 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value);
729 403395 : }
730 :
731 527676 : Node* BytecodeGraphBuilder::BuildLoadGlobal(Handle<Name> name,
732 : uint32_t feedback_slot_index,
733 527676 : TypeofMode typeof_mode) {
734 1055352 : VectorSlotPair feedback = CreateVectorSlotPair(feedback_slot_index);
735 : DCHECK(IsLoadGlobalICKind(feedback_vector()->GetKind(feedback.slot())));
736 527676 : const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
737 527676 : return NewNode(op);
738 : }
739 :
740 1655404 : void BytecodeGraphBuilder::VisitLdaGlobal() {
741 413851 : PrepareEagerCheckpoint();
742 : Handle<Name> name =
743 413851 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
744 413851 : uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
745 : Node* node =
746 413851 : BuildLoadGlobal(name, feedback_slot_index, TypeofMode::NOT_INSIDE_TYPEOF);
747 413851 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
748 413851 : }
749 :
750 1716 : void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() {
751 429 : PrepareEagerCheckpoint();
752 : Handle<Name> name =
753 429 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
754 429 : uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
755 : Node* node =
756 429 : BuildLoadGlobal(name, feedback_slot_index, TypeofMode::INSIDE_TYPEOF);
757 429 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
758 429 : }
759 :
760 221784 : void BytecodeGraphBuilder::BuildStoreGlobal(LanguageMode language_mode) {
761 36964 : PrepareEagerCheckpoint();
762 : Handle<Name> name =
763 36964 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
764 : VectorSlotPair feedback =
765 73928 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
766 36964 : Node* value = environment()->LookupAccumulator();
767 :
768 36964 : const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback);
769 : Node* node = NewNode(op, value);
770 36964 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
771 36964 : }
772 :
773 0 : void BytecodeGraphBuilder::VisitStaGlobalSloppy() {
774 36375 : BuildStoreGlobal(LanguageMode::SLOPPY);
775 0 : }
776 :
777 0 : void BytecodeGraphBuilder::VisitStaGlobalStrict() {
778 589 : BuildStoreGlobal(LanguageMode::STRICT);
779 0 : }
780 :
781 486354 : void BytecodeGraphBuilder::VisitStaDataPropertyInLiteral() {
782 44214 : PrepareEagerCheckpoint();
783 :
784 : Node* object =
785 88428 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
786 : Node* name =
787 88428 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
788 44214 : Node* value = environment()->LookupAccumulator();
789 44214 : int flags = bytecode_iterator().GetFlagOperand(2);
790 : VectorSlotPair feedback =
791 88428 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(3));
792 :
793 44214 : const Operator* op = javascript()->StoreDataPropertyInLiteral(feedback);
794 44214 : Node* node = NewNode(op, object, name, value, jsgraph()->Constant(flags));
795 44214 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
796 44214 : }
797 :
798 532 : void BytecodeGraphBuilder::VisitCollectTypeProfile() {
799 76 : PrepareEagerCheckpoint();
800 :
801 : Node* position =
802 152 : jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
803 76 : Node* value = environment()->LookupAccumulator();
804 76 : Node* vector = jsgraph()->Constant(feedback_vector());
805 :
806 76 : const Operator* op = javascript()->CallRuntime(Runtime::kCollectTypeProfile);
807 :
808 : Node* node = NewNode(op, position, value, vector);
809 76 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
810 76 : }
811 :
812 86550 : void BytecodeGraphBuilder::VisitLdaContextSlot() {
813 : const Operator* op = javascript()->LoadContext(
814 14425 : bytecode_iterator().GetUnsignedImmediateOperand(2),
815 43275 : bytecode_iterator().GetIndexOperand(1), false);
816 : Node* node = NewNode(op);
817 : Node* context =
818 28850 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
819 14425 : NodeProperties::ReplaceContextInput(node, context);
820 14425 : environment()->BindAccumulator(node);
821 14425 : }
822 :
823 96912 : void BytecodeGraphBuilder::VisitLdaImmutableContextSlot() {
824 : const Operator* op = javascript()->LoadContext(
825 16152 : bytecode_iterator().GetUnsignedImmediateOperand(2),
826 48456 : bytecode_iterator().GetIndexOperand(1), true);
827 : Node* node = NewNode(op);
828 : Node* context =
829 32304 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
830 16152 : NodeProperties::ReplaceContextInput(node, context);
831 16152 : environment()->BindAccumulator(node);
832 16152 : }
833 :
834 634650 : void BytecodeGraphBuilder::VisitLdaCurrentContextSlot() {
835 : const Operator* op = javascript()->LoadContext(
836 423100 : 0, bytecode_iterator().GetIndexOperand(0), false);
837 : Node* node = NewNode(op);
838 211550 : environment()->BindAccumulator(node);
839 211550 : }
840 :
841 444219 : void BytecodeGraphBuilder::VisitLdaImmutableCurrentContextSlot() {
842 : const Operator* op = javascript()->LoadContext(
843 296146 : 0, bytecode_iterator().GetIndexOperand(0), true);
844 : Node* node = NewNode(op);
845 148073 : environment()->BindAccumulator(node);
846 148073 : }
847 :
848 25644 : void BytecodeGraphBuilder::VisitStaContextSlot() {
849 : const Operator* op = javascript()->StoreContext(
850 4274 : bytecode_iterator().GetUnsignedImmediateOperand(2),
851 12822 : bytecode_iterator().GetIndexOperand(1));
852 4274 : Node* value = environment()->LookupAccumulator();
853 : Node* node = NewNode(op, value);
854 : Node* context =
855 8548 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
856 4274 : NodeProperties::ReplaceContextInput(node, context);
857 4274 : }
858 :
859 461322 : void BytecodeGraphBuilder::VisitStaCurrentContextSlot() {
860 : const Operator* op =
861 307548 : javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(0));
862 153774 : Node* value = environment()->LookupAccumulator();
863 : NewNode(op, value);
864 153774 : }
865 :
866 13480 : void BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) {
867 2696 : PrepareEagerCheckpoint();
868 : Node* name =
869 5392 : jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
870 : const Operator* op =
871 : javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
872 : ? Runtime::kLoadLookupSlot
873 5392 : : Runtime::kLoadLookupSlotInsideTypeof);
874 : Node* value = NewNode(op, name);
875 2696 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
876 2696 : }
877 :
878 0 : void BytecodeGraphBuilder::VisitLdaLookupSlot() {
879 2678 : BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF);
880 0 : }
881 :
882 0 : void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
883 18 : BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF);
884 0 : }
885 :
886 114275 : BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions(
887 589600 : uint32_t depth) {
888 : // Output environment where the context has an extension
889 : Environment* slow_environment = nullptr;
890 :
891 : // We only need to check up to the last-but-one depth, because the an eval in
892 : // the same scope as the variable itself has no way of shadowing it.
893 232195 : for (uint32_t d = 0; d < depth; d++) {
894 : Node* extension_slot =
895 235840 : NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false));
896 :
897 : Node* check_no_extension =
898 : NewNode(simplified()->ReferenceEqual(), extension_slot,
899 235840 : jsgraph()->TheHoleConstant());
900 :
901 117920 : NewBranch(check_no_extension);
902 117920 : Environment* true_environment = environment()->Copy();
903 :
904 : {
905 117920 : NewIfFalse();
906 : // If there is an extension, merge into the slow path.
907 117920 : if (slow_environment == nullptr) {
908 : slow_environment = environment();
909 114176 : NewMerge();
910 : } else {
911 3744 : slow_environment->Merge(environment());
912 : }
913 : }
914 :
915 : {
916 : set_environment(true_environment);
917 117920 : NewIfTrue();
918 : // Do nothing on if there is no extension, eventually falling through to
919 : // the fast path.
920 : }
921 : }
922 :
923 : // The depth can be zero, in which case no slow-path checks are built, and the
924 : // slow path environment can be null.
925 : DCHECK(depth == 0 || slow_environment != nullptr);
926 :
927 114275 : return slow_environment;
928 : }
929 :
930 8748 : void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) {
931 879 : uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
932 :
933 : // Check if any context in the depth has an extension.
934 879 : Environment* slow_environment = CheckContextExtensions(depth);
935 :
936 : // Fast path, do a context load.
937 : {
938 879 : uint32_t slot_index = bytecode_iterator().GetIndexOperand(1);
939 :
940 1758 : const Operator* op = javascript()->LoadContext(depth, slot_index, false);
941 879 : environment()->BindAccumulator(NewNode(op));
942 : }
943 :
944 : // Only build the slow path if there were any slow-path checks.
945 879 : if (slow_environment != nullptr) {
946 : // Add a merge to the fast environment.
947 872 : NewMerge();
948 : Environment* fast_environment = environment();
949 :
950 : // Slow path, do a runtime load lookup.
951 : set_environment(slow_environment);
952 : {
953 : Node* name = jsgraph()->Constant(
954 1744 : bytecode_iterator().GetConstantForIndexOperand(0));
955 :
956 : const Operator* op =
957 : javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
958 : ? Runtime::kLoadLookupSlot
959 1744 : : Runtime::kLoadLookupSlotInsideTypeof);
960 : Node* value = NewNode(op, name);
961 872 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
962 : }
963 :
964 872 : fast_environment->Merge(environment());
965 : set_environment(fast_environment);
966 : mark_as_needing_eager_checkpoint(true);
967 : }
968 879 : }
969 :
970 0 : void BytecodeGraphBuilder::VisitLdaLookupContextSlot() {
971 873 : BuildLdaLookupContextSlot(TypeofMode::NOT_INSIDE_TYPEOF);
972 0 : }
973 :
974 0 : void BytecodeGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() {
975 6 : BuildLdaLookupContextSlot(TypeofMode::INSIDE_TYPEOF);
976 0 : }
977 :
978 1133408 : void BytecodeGraphBuilder::BuildLdaLookupGlobalSlot(TypeofMode typeof_mode) {
979 113396 : uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
980 :
981 : // Check if any context in the depth has an extension.
982 113396 : Environment* slow_environment = CheckContextExtensions(depth);
983 :
984 : // Fast path, do a global load.
985 : {
986 113396 : PrepareEagerCheckpoint();
987 : Handle<Name> name =
988 113396 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
989 113396 : uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
990 113396 : Node* node = BuildLoadGlobal(name, feedback_slot_index, typeof_mode);
991 113396 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
992 : }
993 :
994 : // Only build the slow path if there were any slow-path checks.
995 113396 : if (slow_environment != nullptr) {
996 : // Add a merge to the fast environment.
997 113304 : NewMerge();
998 : Environment* fast_environment = environment();
999 :
1000 : // Slow path, do a runtime load lookup.
1001 : set_environment(slow_environment);
1002 : {
1003 : Node* name = jsgraph()->Constant(
1004 226608 : bytecode_iterator().GetConstantForIndexOperand(0));
1005 :
1006 : const Operator* op =
1007 : javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
1008 : ? Runtime::kLoadLookupSlot
1009 226608 : : Runtime::kLoadLookupSlotInsideTypeof);
1010 : Node* value = NewNode(op, name);
1011 113304 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1012 : }
1013 :
1014 113304 : fast_environment->Merge(environment());
1015 : set_environment(fast_environment);
1016 : mark_as_needing_eager_checkpoint(true);
1017 : }
1018 113396 : }
1019 :
1020 0 : void BytecodeGraphBuilder::VisitLdaLookupGlobalSlot() {
1021 113321 : BuildLdaLookupGlobalSlot(TypeofMode::NOT_INSIDE_TYPEOF);
1022 0 : }
1023 :
1024 0 : void BytecodeGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() {
1025 75 : BuildLdaLookupGlobalSlot(TypeofMode::INSIDE_TYPEOF);
1026 0 : }
1027 :
1028 66126 : void BytecodeGraphBuilder::BuildStaLookupSlot(LanguageMode language_mode) {
1029 11021 : PrepareEagerCheckpoint();
1030 11021 : Node* value = environment()->LookupAccumulator();
1031 : Node* name =
1032 22042 : jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
1033 : const Operator* op = javascript()->CallRuntime(
1034 : is_strict(language_mode) ? Runtime::kStoreLookupSlot_Strict
1035 22042 : : Runtime::kStoreLookupSlot_Sloppy);
1036 : Node* store = NewNode(op, name, value);
1037 11021 : environment()->BindAccumulator(store, Environment::kAttachFrameState);
1038 11021 : }
1039 :
1040 0 : void BytecodeGraphBuilder::VisitStaLookupSlotSloppy() {
1041 9218 : BuildStaLookupSlot(LanguageMode::SLOPPY);
1042 0 : }
1043 :
1044 0 : void BytecodeGraphBuilder::VisitStaLookupSlotStrict() {
1045 1803 : BuildStaLookupSlot(LanguageMode::STRICT);
1046 0 : }
1047 :
1048 3220371 : void BytecodeGraphBuilder::VisitLdaNamedProperty() {
1049 460053 : PrepareEagerCheckpoint();
1050 : Node* object =
1051 920106 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1052 : Handle<Name> name =
1053 460053 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
1054 : VectorSlotPair feedback =
1055 920106 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1056 460053 : const Operator* op = javascript()->LoadNamed(name, feedback);
1057 :
1058 : Node* node = nullptr;
1059 460053 : if (Node* simplified =
1060 460053 : TryBuildSimplifiedLoadNamed(op, object, feedback.slot())) {
1061 45466 : if (environment() == nullptr) return;
1062 : node = simplified;
1063 : } else {
1064 : node = NewNode(op, object);
1065 : }
1066 :
1067 437320 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1068 : }
1069 :
1070 481264 : void BytecodeGraphBuilder::VisitLdaKeyedProperty() {
1071 68752 : PrepareEagerCheckpoint();
1072 68752 : Node* key = environment()->LookupAccumulator();
1073 : Node* object =
1074 137504 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1075 : VectorSlotPair feedback =
1076 137504 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
1077 68752 : const Operator* op = javascript()->LoadProperty(feedback);
1078 :
1079 : Node* node = nullptr;
1080 68752 : if (Node* simplified =
1081 68752 : TryBuildSimplifiedLoadKeyed(op, object, key, feedback.slot())) {
1082 708 : if (environment() == nullptr) return;
1083 : node = simplified;
1084 : } else {
1085 : node = NewNode(op, object, key);
1086 : }
1087 :
1088 68398 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1089 : }
1090 :
1091 98797 : void BytecodeGraphBuilder::BuildNamedStore(LanguageMode language_mode,
1092 691579 : StoreMode store_mode) {
1093 98797 : PrepareEagerCheckpoint();
1094 98797 : Node* value = environment()->LookupAccumulator();
1095 : Node* object =
1096 197594 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1097 : Handle<Name> name =
1098 98797 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
1099 : VectorSlotPair feedback =
1100 197594 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1101 :
1102 : const Operator* op;
1103 98797 : if (store_mode == StoreMode::kOwn) {
1104 : DCHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
1105 : feedback.vector()->GetKind(feedback.slot()));
1106 34397 : op = javascript()->StoreNamedOwn(name, feedback);
1107 : } else {
1108 : DCHECK(store_mode == StoreMode::kNormal);
1109 : DCHECK_EQ(feedback.vector()->GetLanguageMode(feedback.slot()),
1110 : language_mode);
1111 64400 : op = javascript()->StoreNamed(language_mode, name, feedback);
1112 : }
1113 :
1114 : Node* node = nullptr;
1115 98797 : if (Node* simplified =
1116 98797 : TryBuildSimplifiedStoreNamed(op, object, value, feedback.slot())) {
1117 750 : if (environment() == nullptr) return;
1118 : node = simplified;
1119 : } else {
1120 : node = NewNode(op, object, value);
1121 : }
1122 :
1123 98422 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
1124 : }
1125 :
1126 0 : void BytecodeGraphBuilder::VisitStaNamedPropertySloppy() {
1127 23120 : BuildNamedStore(LanguageMode::SLOPPY, StoreMode::kNormal);
1128 0 : }
1129 :
1130 0 : void BytecodeGraphBuilder::VisitStaNamedPropertyStrict() {
1131 41280 : BuildNamedStore(LanguageMode::STRICT, StoreMode::kNormal);
1132 0 : }
1133 :
1134 0 : void BytecodeGraphBuilder::VisitStaNamedOwnProperty() {
1135 34397 : BuildNamedStore(LanguageMode::STRICT, StoreMode::kOwn);
1136 0 : }
1137 :
1138 366309 : void BytecodeGraphBuilder::BuildKeyedStore(LanguageMode language_mode) {
1139 40701 : PrepareEagerCheckpoint();
1140 40701 : Node* value = environment()->LookupAccumulator();
1141 : Node* object =
1142 81402 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1143 : Node* key =
1144 81402 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1145 : VectorSlotPair feedback =
1146 81402 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1147 : DCHECK_EQ(feedback.vector()->GetLanguageMode(feedback.slot()), language_mode);
1148 40701 : const Operator* op = javascript()->StoreProperty(language_mode, feedback);
1149 :
1150 : Node* node = nullptr;
1151 40701 : if (Node* simplified = TryBuildSimplifiedStoreKeyed(op, object, key, value,
1152 40701 : feedback.slot())) {
1153 142 : if (environment() == nullptr) return;
1154 : node = simplified;
1155 : } else {
1156 : node = NewNode(op, object, key, value);
1157 : }
1158 :
1159 40630 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
1160 : }
1161 :
1162 0 : void BytecodeGraphBuilder::VisitStaKeyedPropertySloppy() {
1163 25125 : BuildKeyedStore(LanguageMode::SLOPPY);
1164 0 : }
1165 :
1166 0 : void BytecodeGraphBuilder::VisitStaKeyedPropertyStrict() {
1167 15576 : BuildKeyedStore(LanguageMode::STRICT);
1168 0 : }
1169 :
1170 2030 : void BytecodeGraphBuilder::VisitLdaModuleVariable() {
1171 406 : int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
1172 406 : uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
1173 : Node* module =
1174 812 : NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true));
1175 406 : Node* value = NewNode(javascript()->LoadModule(cell_index), module);
1176 406 : environment()->BindAccumulator(value);
1177 406 : }
1178 :
1179 2430 : void BytecodeGraphBuilder::VisitStaModuleVariable() {
1180 486 : int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
1181 486 : uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
1182 : Node* module =
1183 972 : NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true));
1184 486 : Node* value = environment()->LookupAccumulator();
1185 486 : NewNode(javascript()->StoreModule(cell_index), module, value);
1186 486 : }
1187 :
1188 226200 : void BytecodeGraphBuilder::VisitPushContext() {
1189 56550 : Node* new_context = environment()->LookupAccumulator();
1190 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0),
1191 169650 : environment()->Context());
1192 : environment()->SetContext(new_context);
1193 56550 : }
1194 :
1195 123951 : void BytecodeGraphBuilder::VisitPopContext() {
1196 : Node* context =
1197 82634 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1198 : environment()->SetContext(context);
1199 41317 : }
1200 :
1201 920110 : void BytecodeGraphBuilder::VisitCreateClosure() {
1202 : Handle<SharedFunctionInfo> shared_info = Handle<SharedFunctionInfo>::cast(
1203 184022 : bytecode_iterator().GetConstantForIndexOperand(0));
1204 184022 : int const slot_id = bytecode_iterator().GetIndexOperand(1);
1205 184022 : VectorSlotPair pair = CreateVectorSlotPair(slot_id);
1206 : PretenureFlag tenured =
1207 : interpreter::CreateClosureFlags::PretenuredBit::decode(
1208 184022 : bytecode_iterator().GetFlagOperand(2))
1209 : ? TENURED
1210 184022 : : NOT_TENURED;
1211 184022 : const Operator* op = javascript()->CreateClosure(shared_info, pair, tenured);
1212 : Node* closure = NewNode(op);
1213 184022 : environment()->BindAccumulator(closure);
1214 184022 : }
1215 :
1216 26872 : void BytecodeGraphBuilder::VisitCreateBlockContext() {
1217 : Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(
1218 6718 : bytecode_iterator().GetConstantForIndexOperand(0));
1219 :
1220 6718 : const Operator* op = javascript()->CreateBlockContext(scope_info);
1221 6718 : Node* context = NewNode(op, environment()->LookupAccumulator());
1222 6718 : environment()->BindAccumulator(context);
1223 6718 : }
1224 :
1225 40446 : void BytecodeGraphBuilder::VisitCreateFunctionContext() {
1226 13482 : uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(0);
1227 : const Operator* op =
1228 26964 : javascript()->CreateFunctionContext(slots, FUNCTION_SCOPE);
1229 13482 : Node* context = NewNode(op, GetFunctionClosure());
1230 13482 : environment()->BindAccumulator(context);
1231 13482 : }
1232 :
1233 13152 : void BytecodeGraphBuilder::VisitCreateEvalContext() {
1234 4384 : uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(0);
1235 8768 : const Operator* op = javascript()->CreateFunctionContext(slots, EVAL_SCOPE);
1236 4384 : Node* context = NewNode(op, GetFunctionClosure());
1237 4384 : environment()->BindAccumulator(context);
1238 4384 : }
1239 :
1240 188174 : void BytecodeGraphBuilder::VisitCreateCatchContext() {
1241 26882 : interpreter::Register reg = bytecode_iterator().GetRegisterOperand(0);
1242 26882 : Node* exception = environment()->LookupRegister(reg);
1243 : Handle<String> name =
1244 26882 : Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
1245 : Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(
1246 26882 : bytecode_iterator().GetConstantForIndexOperand(2));
1247 26882 : Node* closure = environment()->LookupAccumulator();
1248 :
1249 26882 : const Operator* op = javascript()->CreateCatchContext(name, scope_info);
1250 : Node* context = NewNode(op, exception, closure);
1251 26882 : environment()->BindAccumulator(context);
1252 26882 : }
1253 :
1254 5064 : void BytecodeGraphBuilder::VisitCreateWithContext() {
1255 : Node* object =
1256 1688 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1257 : Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(
1258 844 : bytecode_iterator().GetConstantForIndexOperand(1));
1259 :
1260 844 : const Operator* op = javascript()->CreateWithContext(scope_info);
1261 844 : Node* context = NewNode(op, object, environment()->LookupAccumulator());
1262 844 : environment()->BindAccumulator(context);
1263 844 : }
1264 :
1265 18854 : void BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) {
1266 9427 : const Operator* op = javascript()->CreateArguments(type);
1267 9427 : Node* object = NewNode(op, GetFunctionClosure());
1268 9427 : environment()->BindAccumulator(object, Environment::kAttachFrameState);
1269 9427 : }
1270 :
1271 0 : void BytecodeGraphBuilder::VisitCreateMappedArguments() {
1272 5370 : BuildCreateArguments(CreateArgumentsType::kMappedArguments);
1273 0 : }
1274 :
1275 0 : void BytecodeGraphBuilder::VisitCreateUnmappedArguments() {
1276 3432 : BuildCreateArguments(CreateArgumentsType::kUnmappedArguments);
1277 0 : }
1278 :
1279 0 : void BytecodeGraphBuilder::VisitCreateRestParameter() {
1280 625 : BuildCreateArguments(CreateArgumentsType::kRestParameter);
1281 0 : }
1282 :
1283 50745 : void BytecodeGraphBuilder::VisitCreateRegExpLiteral() {
1284 : Handle<String> constant_pattern =
1285 10149 : Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
1286 10149 : int literal_index = bytecode_iterator().GetIndexOperand(1);
1287 10149 : int literal_flags = bytecode_iterator().GetFlagOperand(2);
1288 : Node* literal = NewNode(javascript()->CreateLiteralRegExp(
1289 : constant_pattern, literal_flags, literal_index),
1290 20298 : GetFunctionClosure());
1291 10149 : environment()->BindAccumulator(literal, Environment::kAttachFrameState);
1292 10149 : }
1293 :
1294 128425 : void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
1295 : Handle<ConstantElementsPair> constant_elements =
1296 : Handle<ConstantElementsPair>::cast(
1297 25685 : bytecode_iterator().GetConstantForIndexOperand(0));
1298 25685 : int literal_index = bytecode_iterator().GetIndexOperand(1);
1299 25685 : int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
1300 : int literal_flags =
1301 : interpreter::CreateArrayLiteralFlags::FlagsBits::decode(bytecode_flags);
1302 : // Disable allocation site mementos. Only unoptimized code will collect
1303 : // feedback about allocation site. Once the code is optimized we expect the
1304 : // data to converge. So, we disable allocation site mementos in optimized
1305 : // code. We can revisit this when we have data to the contrary.
1306 25685 : literal_flags |= ArrayLiteral::kDisableMementos;
1307 : // TODO(mstarzinger): Thread through number of elements. The below number is
1308 : // only an estimate and does not match {ArrayLiteral::values::length}.
1309 : int number_of_elements = constant_elements->constant_values()->length();
1310 : Node* literal = NewNode(
1311 : javascript()->CreateLiteralArray(constant_elements, literal_flags,
1312 : literal_index, number_of_elements),
1313 51370 : GetFunctionClosure());
1314 25685 : environment()->BindAccumulator(literal, Environment::kAttachFrameState);
1315 25685 : }
1316 :
1317 293436 : void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
1318 : Handle<BoilerplateDescription> constant_properties =
1319 : Handle<BoilerplateDescription>::cast(
1320 48906 : bytecode_iterator().GetConstantForIndexOperand(0));
1321 48906 : int literal_index = bytecode_iterator().GetIndexOperand(1);
1322 48906 : int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
1323 : int literal_flags =
1324 : interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
1325 : // TODO(mstarzinger): Thread through number of properties. The below number is
1326 : // only an estimate and does not match {ObjectLiteral::properties_count}.
1327 48906 : int number_of_properties = constant_properties->size();
1328 : Node* literal = NewNode(
1329 : javascript()->CreateLiteralObject(constant_properties, literal_flags,
1330 : literal_index, number_of_properties),
1331 97812 : GetFunctionClosure());
1332 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(3),
1333 97812 : literal, Environment::kAttachFrameState);
1334 48906 : }
1335 :
1336 67315 : Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegister(
1337 : Node* callee, Node* receiver, interpreter::Register first_arg,
1338 805784 : int arg_count) {
1339 : // The arity of the Call node -- includes the callee, receiver and function
1340 : // arguments.
1341 67315 : int arity = 2 + arg_count;
1342 :
1343 67315 : Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
1344 :
1345 67315 : all[0] = callee;
1346 67315 : all[1] = receiver;
1347 :
1348 : // The function arguments are in consecutive registers.
1349 : int arg_base = first_arg.index();
1350 805784 : for (int i = 0; i < arg_count; ++i) {
1351 738469 : all[2 + i] =
1352 1476938 : environment()->LookupRegister(interpreter::Register(arg_base + i));
1353 : }
1354 :
1355 67315 : return all;
1356 : }
1357 :
1358 0 : Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
1359 : Node* const* args,
1360 : int arg_count) {
1361 618211 : return MakeNode(call_op, arg_count, args, false);
1362 : }
1363 :
1364 14158 : Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
1365 : Node* callee,
1366 : interpreter::Register receiver,
1367 14158 : size_t reg_count) {
1368 14158 : Node* receiver_node = environment()->LookupRegister(receiver);
1369 : // The receiver is followed by the arguments in the consecutive registers.
1370 : DCHECK_GE(reg_count, 1);
1371 14158 : interpreter::Register first_arg = interpreter::Register(receiver.index() + 1);
1372 14158 : int arg_count = static_cast<int>(reg_count) - 1;
1373 :
1374 : Node* const* call_args =
1375 14158 : GetCallArgumentsFromRegister(callee, receiver_node, first_arg, arg_count);
1376 28316 : return ProcessCallArguments(call_op, call_args, 2 + arg_count);
1377 : }
1378 :
1379 604053 : void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode,
1380 : ConvertReceiverMode receiver_mode,
1381 : Node* const* args, size_t arg_count,
1382 1208106 : int slot_id) {
1383 : DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode(
1384 : bytecode_iterator().current_bytecode()),
1385 : receiver_mode);
1386 604053 : PrepareEagerCheckpoint();
1387 :
1388 : // Slot index of 0 is used indicate no feedback slot is available. Assert
1389 : // the assumption that slot index 0 is never a valid feedback slot.
1390 : STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0);
1391 604053 : VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1392 :
1393 604053 : float const frequency = ComputeCallFrequency(slot_id);
1394 : const Operator* call = javascript()->Call(arg_count, frequency, feedback,
1395 604053 : receiver_mode, tail_call_mode);
1396 604053 : Node* value = ProcessCallArguments(call, args, static_cast<int>(arg_count));
1397 604053 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1398 604053 : }
1399 :
1400 53157 : void BytecodeGraphBuilder::BuildCallVarArgs(TailCallMode tail_call_mode,
1401 318942 : ConvertReceiverMode receiver_mode) {
1402 : DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode(
1403 : bytecode_iterator().current_bytecode()),
1404 : receiver_mode);
1405 : Node* callee =
1406 106314 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1407 53157 : interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
1408 53157 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1409 53157 : int const slot_id = bytecode_iterator().GetIndexOperand(3);
1410 :
1411 : Node* receiver_node;
1412 : interpreter::Register first_arg;
1413 : int arg_count;
1414 :
1415 53157 : if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
1416 : // The receiver is implicit (and undefined), the arguments are in
1417 : // consecutive registers.
1418 40025 : receiver_node = jsgraph()->UndefinedConstant();
1419 40025 : first_arg = first_reg;
1420 40025 : arg_count = static_cast<int>(reg_count);
1421 : } else {
1422 : // The receiver is the first register, followed by the arguments in the
1423 : // consecutive registers.
1424 : DCHECK_GE(reg_count, 1);
1425 13132 : receiver_node = environment()->LookupRegister(first_reg);
1426 13132 : first_arg = interpreter::Register(first_reg.index() + 1);
1427 13132 : arg_count = static_cast<int>(reg_count) - 1;
1428 : }
1429 :
1430 : Node* const* call_args =
1431 53157 : GetCallArgumentsFromRegister(callee, receiver_node, first_arg, arg_count);
1432 : BuildCall(tail_call_mode, receiver_mode, call_args,
1433 53157 : static_cast<size_t>(2 + arg_count), slot_id);
1434 53157 : }
1435 :
1436 0 : void BytecodeGraphBuilder::VisitCallAnyReceiver() {
1437 800 : BuildCallVarArgs(TailCallMode::kDisallow, ConvertReceiverMode::kAny);
1438 0 : }
1439 :
1440 0 : void BytecodeGraphBuilder::VisitCallProperty() {
1441 : BuildCallVarArgs(TailCallMode::kDisallow,
1442 11398 : ConvertReceiverMode::kNotNullOrUndefined);
1443 0 : }
1444 :
1445 236270 : void BytecodeGraphBuilder::VisitCallProperty0() {
1446 : Node* callee =
1447 94508 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1448 : Node* receiver =
1449 94508 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1450 47254 : int const slot_id = bytecode_iterator().GetIndexOperand(2);
1451 : BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNotNullOrUndefined,
1452 94508 : {callee, receiver}, slot_id);
1453 47254 : }
1454 :
1455 909279 : void BytecodeGraphBuilder::VisitCallProperty1() {
1456 : Node* callee =
1457 259794 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1458 : Node* receiver =
1459 259794 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1460 : Node* arg0 =
1461 259794 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
1462 129897 : int const slot_id = bytecode_iterator().GetIndexOperand(3);
1463 : BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNotNullOrUndefined,
1464 259794 : {callee, receiver, arg0}, slot_id);
1465 129897 : }
1466 :
1467 188964 : void BytecodeGraphBuilder::VisitCallProperty2() {
1468 : Node* callee =
1469 41992 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1470 : Node* receiver =
1471 41992 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1472 : Node* arg0 =
1473 41992 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
1474 : Node* arg1 =
1475 41992 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(3));
1476 20996 : int const slot_id = bytecode_iterator().GetIndexOperand(4);
1477 : BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNotNullOrUndefined,
1478 41992 : {callee, receiver, arg0, arg1}, slot_id);
1479 20996 : }
1480 :
1481 0 : void BytecodeGraphBuilder::VisitCallUndefinedReceiver() {
1482 : BuildCallVarArgs(TailCallMode::kDisallow,
1483 40025 : ConvertReceiverMode::kNullOrUndefined);
1484 0 : }
1485 :
1486 143300 : void BytecodeGraphBuilder::VisitCallUndefinedReceiver0() {
1487 : Node* callee =
1488 71650 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1489 35825 : Node* receiver = jsgraph()->UndefinedConstant();
1490 35825 : int const slot_id = bytecode_iterator().GetIndexOperand(1);
1491 : BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNullOrUndefined,
1492 71650 : {callee, receiver}, slot_id);
1493 35825 : }
1494 :
1495 1171614 : void BytecodeGraphBuilder::VisitCallUndefinedReceiver1() {
1496 : Node* callee =
1497 390538 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1498 195269 : Node* receiver = jsgraph()->UndefinedConstant();
1499 : Node* arg0 =
1500 390538 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1501 195269 : int const slot_id = bytecode_iterator().GetIndexOperand(2);
1502 : BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNullOrUndefined,
1503 390538 : {callee, receiver, arg0}, slot_id);
1504 195269 : }
1505 :
1506 973240 : void BytecodeGraphBuilder::VisitCallUndefinedReceiver2() {
1507 : Node* callee =
1508 243310 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1509 121655 : Node* receiver = jsgraph()->UndefinedConstant();
1510 : Node* arg0 =
1511 243310 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1512 : Node* arg1 =
1513 243310 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
1514 121655 : int const slot_id = bytecode_iterator().GetIndexOperand(3);
1515 : BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNullOrUndefined,
1516 243310 : {callee, receiver, arg0, arg1}, slot_id);
1517 121655 : }
1518 :
1519 1694 : void BytecodeGraphBuilder::VisitCallWithSpread() {
1520 242 : PrepareEagerCheckpoint();
1521 : Node* callee =
1522 484 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1523 242 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1524 242 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1525 : const Operator* call =
1526 484 : javascript()->CallWithSpread(static_cast<int>(reg_count + 1));
1527 :
1528 242 : Node* value = ProcessCallArguments(call, callee, receiver, reg_count);
1529 242 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1530 242 : }
1531 :
1532 934 : void BytecodeGraphBuilder::VisitTailCall() {
1533 : TailCallMode tail_call_mode =
1534 934 : bytecode_array_->GetIsolate()->is_tail_call_elimination_enabled()
1535 : ? TailCallMode::kAllow
1536 934 : : TailCallMode::kDisallow;
1537 934 : BuildCallVarArgs(tail_call_mode, ConvertReceiverMode::kAny);
1538 934 : }
1539 :
1540 83496 : void BytecodeGraphBuilder::VisitCallJSRuntime() {
1541 13916 : PrepareEagerCheckpoint();
1542 : Node* callee =
1543 13916 : BuildLoadNativeContextField(bytecode_iterator().GetIndexOperand(0));
1544 13916 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1545 13916 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1546 :
1547 : // Create node to perform the JS runtime call.
1548 27832 : const Operator* call = javascript()->Call(reg_count + 1);
1549 13916 : Node* value = ProcessCallArguments(call, callee, receiver, reg_count);
1550 13916 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1551 13916 : }
1552 :
1553 260646 : Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
1554 : const Operator* call_runtime_op, interpreter::Register receiver,
1555 776566 : size_t reg_count) {
1556 260646 : int arg_count = static_cast<int>(reg_count);
1557 : // arity is args.
1558 : int arity = arg_count;
1559 260646 : Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
1560 : int first_arg_index = receiver.index();
1561 776566 : for (int i = 0; i < static_cast<int>(reg_count); ++i) {
1562 515920 : all[i] = environment()->LookupRegister(
1563 1031840 : interpreter::Register(first_arg_index + i));
1564 : }
1565 260646 : Node* value = MakeNode(call_runtime_op, arity, all, false);
1566 260646 : return value;
1567 : }
1568 :
1569 1228560 : void BytecodeGraphBuilder::VisitCallRuntime() {
1570 204760 : PrepareEagerCheckpoint();
1571 204760 : Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
1572 204760 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1573 204760 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1574 :
1575 : // Create node to perform the runtime call.
1576 204760 : const Operator* call = javascript()->CallRuntime(functionId, reg_count);
1577 204760 : Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count);
1578 204760 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1579 204760 : }
1580 :
1581 4515 : void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
1582 645 : PrepareEagerCheckpoint();
1583 645 : Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
1584 645 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1585 645 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1586 : interpreter::Register first_return =
1587 645 : bytecode_iterator().GetRegisterOperand(3);
1588 :
1589 : // Create node to perform the runtime call.
1590 645 : const Operator* call = javascript()->CallRuntime(functionId, reg_count);
1591 645 : Node* return_pair = ProcessCallRuntimeArguments(call, receiver, reg_count);
1592 : environment()->BindRegistersToProjections(first_return, return_pair,
1593 645 : Environment::kAttachFrameState);
1594 645 : }
1595 :
1596 239 : Node* BytecodeGraphBuilder::ProcessConstructWithSpreadArguments(
1597 : const Operator* op, Node* callee, Node* new_target,
1598 494 : interpreter::Register receiver, size_t reg_count) {
1599 239 : int arg_count = static_cast<int>(reg_count);
1600 : // arity is args + callee and new target.
1601 239 : int arity = arg_count + 2;
1602 239 : Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
1603 239 : all[0] = callee;
1604 : int first_arg_index = receiver.index();
1605 494 : for (int i = 0; i < arg_count; ++i) {
1606 255 : all[1 + i] = environment()->LookupRegister(
1607 510 : interpreter::Register(first_arg_index + i));
1608 : }
1609 239 : all[arity - 1] = new_target;
1610 239 : Node* value = MakeNode(op, arity, all, false);
1611 239 : return value;
1612 : }
1613 :
1614 1673 : void BytecodeGraphBuilder::VisitConstructWithSpread() {
1615 239 : PrepareEagerCheckpoint();
1616 239 : interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
1617 239 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1618 239 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1619 :
1620 239 : Node* new_target = environment()->LookupAccumulator();
1621 239 : Node* callee = environment()->LookupRegister(callee_reg);
1622 :
1623 : const Operator* op =
1624 478 : javascript()->ConstructWithSpread(static_cast<uint32_t>(reg_count + 2));
1625 : Node* value = ProcessConstructWithSpreadArguments(op, callee, new_target,
1626 239 : receiver, reg_count);
1627 239 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1628 239 : }
1629 :
1630 331446 : void BytecodeGraphBuilder::VisitInvokeIntrinsic() {
1631 55241 : PrepareEagerCheckpoint();
1632 55241 : Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0);
1633 55241 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1634 55241 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1635 :
1636 : // Create node to perform the runtime call. Turbofan will take care of the
1637 : // lowering.
1638 55241 : const Operator* call = javascript()->CallRuntime(functionId, reg_count);
1639 55241 : Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count);
1640 55241 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1641 55241 : }
1642 :
1643 34033 : Node* BytecodeGraphBuilder::ProcessConstructArguments(
1644 : const Operator* call_new_op, Node* callee, Node* new_target,
1645 338714 : interpreter::Register receiver, size_t reg_count) {
1646 34033 : int arg_count = static_cast<int>(reg_count);
1647 : // arity is args + callee and new target.
1648 34033 : int arity = arg_count + 2;
1649 34033 : Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
1650 34033 : all[0] = callee;
1651 : int first_arg_index = receiver.index();
1652 338714 : for (int i = 0; i < arg_count; ++i) {
1653 304681 : all[1 + i] = environment()->LookupRegister(
1654 609362 : interpreter::Register(first_arg_index + i));
1655 : }
1656 34033 : all[arity - 1] = new_target;
1657 34033 : Node* value = MakeNode(call_new_op, arity, all, false);
1658 34033 : return value;
1659 : }
1660 :
1661 272264 : void BytecodeGraphBuilder::VisitConstruct() {
1662 34033 : PrepareEagerCheckpoint();
1663 34033 : interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
1664 34033 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1665 34033 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1666 : // Slot index of 0 is used indicate no feedback slot is available. Assert
1667 : // the assumption that slot index 0 is never a valid feedback slot.
1668 : STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0);
1669 34033 : int const slot_id = bytecode_iterator().GetIndexOperand(3);
1670 34033 : VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1671 :
1672 34033 : Node* new_target = environment()->LookupAccumulator();
1673 34033 : Node* callee = environment()->LookupRegister(callee_reg);
1674 :
1675 34033 : float const frequency = ComputeCallFrequency(slot_id);
1676 : const Operator* call = javascript()->Construct(
1677 68066 : static_cast<uint32_t>(reg_count + 2), frequency, feedback);
1678 : Node* value =
1679 34033 : ProcessConstructArguments(call, callee, new_target, receiver, reg_count);
1680 34033 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1681 34033 : }
1682 :
1683 109500 : void BytecodeGraphBuilder::VisitThrow() {
1684 : BuildLoopExitsForFunctionExit();
1685 21900 : Node* value = environment()->LookupAccumulator();
1686 21900 : Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value);
1687 21900 : environment()->BindAccumulator(call, Environment::kAttachFrameState);
1688 21900 : Node* control = NewNode(common()->Throw());
1689 : MergeControlToLeaveFunction(control);
1690 21900 : }
1691 :
1692 46252 : void BytecodeGraphBuilder::VisitReThrow() {
1693 : BuildLoopExitsForFunctionExit();
1694 11563 : Node* value = environment()->LookupAccumulator();
1695 11563 : NewNode(javascript()->CallRuntime(Runtime::kReThrow), value);
1696 11563 : Node* control = NewNode(common()->Throw());
1697 : MergeControlToLeaveFunction(control);
1698 11563 : }
1699 :
1700 1581402 : void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) {
1701 263567 : PrepareEagerCheckpoint();
1702 : Node* left =
1703 527134 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1704 263567 : Node* right = environment()->LookupAccumulator();
1705 :
1706 : Node* node = nullptr;
1707 : FeedbackSlot slot = feedback_vector()->ToSlot(
1708 527134 : bytecode_iterator().GetIndexOperand(kBinaryOperationHintIndex));
1709 263567 : if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) {
1710 : node = simplified;
1711 : } else {
1712 : node = NewNode(op, left, right);
1713 : }
1714 :
1715 263567 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1716 263567 : }
1717 :
1718 : // Helper function to create binary operation hint from the recorded type
1719 : // feedback.
1720 265919 : BinaryOperationHint BytecodeGraphBuilder::GetBinaryOperationHint(
1721 265919 : int operand_index) {
1722 : FeedbackSlot slot = feedback_vector()->ToSlot(
1723 265919 : bytecode_iterator().GetIndexOperand(operand_index));
1724 : DCHECK_EQ(FeedbackSlotKind::kBinaryOp, feedback_vector()->GetKind(slot));
1725 : BinaryOpICNexus nexus(feedback_vector(), slot);
1726 265919 : return nexus.GetBinaryOperationFeedback();
1727 : }
1728 :
1729 : // Helper function to create compare operation hint from the recorded type
1730 : // feedback.
1731 710912 : CompareOperationHint BytecodeGraphBuilder::GetCompareOperationHint() {
1732 355456 : int slot_index = bytecode_iterator().GetIndexOperand(1);
1733 355456 : if (slot_index == 0) {
1734 : return CompareOperationHint::kAny;
1735 : }
1736 : FeedbackSlot slot =
1737 355456 : feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(1));
1738 : DCHECK_EQ(FeedbackSlotKind::kCompareOp, feedback_vector()->GetKind(slot));
1739 : CompareICNexus nexus(feedback_vector(), slot);
1740 355456 : return nexus.GetCompareOperationFeedback();
1741 : }
1742 :
1743 638086 : float BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const {
1744 : CallICNexus nexus(feedback_vector(), feedback_vector()->ToSlot(slot_id));
1745 638086 : return nexus.ComputeCallFrequency() * invocation_frequency_;
1746 : }
1747 :
1748 394188 : void BytecodeGraphBuilder::VisitAdd() {
1749 : BuildBinaryOp(
1750 394188 : javascript()->Add(GetBinaryOperationHint(kBinaryOperationHintIndex)));
1751 197094 : }
1752 :
1753 7425 : void BytecodeGraphBuilder::VisitSub() {
1754 7425 : BuildBinaryOp(javascript()->Subtract());
1755 7425 : }
1756 :
1757 7391 : void BytecodeGraphBuilder::VisitMul() {
1758 7391 : BuildBinaryOp(javascript()->Multiply());
1759 7391 : }
1760 :
1761 65314 : void BytecodeGraphBuilder::VisitDiv() { BuildBinaryOp(javascript()->Divide()); }
1762 :
1763 1820 : void BytecodeGraphBuilder::VisitMod() {
1764 1820 : BuildBinaryOp(javascript()->Modulus());
1765 1820 : }
1766 :
1767 3033 : void BytecodeGraphBuilder::VisitBitwiseOr() {
1768 3033 : BuildBinaryOp(javascript()->BitwiseOr());
1769 3033 : }
1770 :
1771 5196 : void BytecodeGraphBuilder::VisitBitwiseXor() {
1772 5196 : BuildBinaryOp(javascript()->BitwiseXor());
1773 5196 : }
1774 :
1775 3542 : void BytecodeGraphBuilder::VisitBitwiseAnd() {
1776 3542 : BuildBinaryOp(javascript()->BitwiseAnd());
1777 3542 : }
1778 :
1779 2032 : void BytecodeGraphBuilder::VisitShiftLeft() {
1780 2032 : BuildBinaryOp(javascript()->ShiftLeft());
1781 2032 : }
1782 :
1783 1564 : void BytecodeGraphBuilder::VisitShiftRight() {
1784 1564 : BuildBinaryOp(javascript()->ShiftRight());
1785 1564 : }
1786 :
1787 1813 : void BytecodeGraphBuilder::VisitShiftRightLogical() {
1788 1813 : BuildBinaryOp(javascript()->ShiftRightLogical());
1789 1813 : }
1790 :
1791 1062786 : void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) {
1792 177131 : PrepareEagerCheckpoint();
1793 177131 : Node* left = environment()->LookupAccumulator();
1794 354262 : Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
1795 :
1796 : Node* node = nullptr;
1797 : FeedbackSlot slot = feedback_vector()->ToSlot(
1798 354262 : bytecode_iterator().GetIndexOperand(kBinaryOperationSmiHintIndex));
1799 177131 : if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) {
1800 : node = simplified;
1801 : } else {
1802 : node = NewNode(op, left, right);
1803 : }
1804 :
1805 177131 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1806 177131 : }
1807 :
1808 137650 : void BytecodeGraphBuilder::VisitAddSmi() {
1809 : BuildBinaryOpWithImmediate(
1810 137650 : javascript()->Add(GetBinaryOperationHint(kBinaryOperationSmiHintIndex)));
1811 68825 : }
1812 :
1813 8014 : void BytecodeGraphBuilder::VisitSubSmi() {
1814 8014 : BuildBinaryOpWithImmediate(javascript()->Subtract());
1815 8014 : }
1816 :
1817 42824 : void BytecodeGraphBuilder::VisitMulSmi() {
1818 42824 : BuildBinaryOpWithImmediate(javascript()->Multiply());
1819 42824 : }
1820 :
1821 7242 : void BytecodeGraphBuilder::VisitDivSmi() {
1822 7242 : BuildBinaryOpWithImmediate(javascript()->Divide());
1823 7242 : }
1824 :
1825 4132 : void BytecodeGraphBuilder::VisitModSmi() {
1826 4132 : BuildBinaryOpWithImmediate(javascript()->Modulus());
1827 4132 : }
1828 :
1829 24463 : void BytecodeGraphBuilder::VisitBitwiseOrSmi() {
1830 24463 : BuildBinaryOpWithImmediate(javascript()->BitwiseOr());
1831 24463 : }
1832 :
1833 1467 : void BytecodeGraphBuilder::VisitBitwiseXorSmi() {
1834 1467 : BuildBinaryOpWithImmediate(javascript()->BitwiseXor());
1835 1467 : }
1836 :
1837 5497 : void BytecodeGraphBuilder::VisitBitwiseAndSmi() {
1838 5497 : BuildBinaryOpWithImmediate(javascript()->BitwiseAnd());
1839 5497 : }
1840 :
1841 4142 : void BytecodeGraphBuilder::VisitShiftLeftSmi() {
1842 4142 : BuildBinaryOpWithImmediate(javascript()->ShiftLeft());
1843 4142 : }
1844 :
1845 5511 : void BytecodeGraphBuilder::VisitShiftRightSmi() {
1846 5511 : BuildBinaryOpWithImmediate(javascript()->ShiftRight());
1847 5511 : }
1848 :
1849 5014 : void BytecodeGraphBuilder::VisitShiftRightLogicalSmi() {
1850 5014 : BuildBinaryOpWithImmediate(javascript()->ShiftRightLogical());
1851 5014 : }
1852 :
1853 224094 : void BytecodeGraphBuilder::VisitInc() {
1854 37349 : PrepareEagerCheckpoint();
1855 : // Note: Use subtract -1 here instead of add 1 to ensure we always convert to
1856 : // a number, not a string.
1857 37349 : Node* left = environment()->LookupAccumulator();
1858 37349 : Node* right = jsgraph()->Constant(-1);
1859 37349 : const Operator* op = javascript()->Subtract();
1860 :
1861 : Node* node = nullptr;
1862 : FeedbackSlot slot = feedback_vector()->ToSlot(
1863 74698 : bytecode_iterator().GetIndexOperand(kCountOperationHintIndex));
1864 37349 : if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) {
1865 : node = simplified;
1866 : } else {
1867 : node = NewNode(op, left, right);
1868 : }
1869 :
1870 37349 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1871 37349 : }
1872 :
1873 31320 : void BytecodeGraphBuilder::VisitDec() {
1874 5220 : PrepareEagerCheckpoint();
1875 5220 : Node* left = environment()->LookupAccumulator();
1876 5220 : Node* right = jsgraph()->OneConstant();
1877 5220 : const Operator* op = javascript()->Subtract();
1878 :
1879 : Node* node = nullptr;
1880 : FeedbackSlot slot = feedback_vector()->ToSlot(
1881 10440 : bytecode_iterator().GetIndexOperand(kCountOperationHintIndex));
1882 5220 : if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) {
1883 : node = simplified;
1884 : } else {
1885 : node = NewNode(op, left, right);
1886 : }
1887 :
1888 5220 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1889 5220 : }
1890 :
1891 14154 : void BytecodeGraphBuilder::VisitLogicalNot() {
1892 4718 : Node* value = environment()->LookupAccumulator();
1893 4718 : Node* node = NewNode(simplified()->BooleanNot(), value);
1894 4718 : environment()->BindAccumulator(node);
1895 4718 : }
1896 :
1897 34676 : void BytecodeGraphBuilder::VisitToBooleanLogicalNot() {
1898 : Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
1899 26007 : environment()->LookupAccumulator());
1900 8669 : Node* node = NewNode(simplified()->BooleanNot(), value);
1901 8669 : environment()->BindAccumulator(node);
1902 8669 : }
1903 :
1904 94047 : void BytecodeGraphBuilder::VisitTypeOf() {
1905 : Node* node =
1906 62698 : NewNode(javascript()->TypeOf(), environment()->LookupAccumulator());
1907 31349 : environment()->BindAccumulator(node);
1908 31349 : }
1909 :
1910 11893 : void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) {
1911 1699 : PrepareEagerCheckpoint();
1912 1699 : Node* key = environment()->LookupAccumulator();
1913 : Node* object =
1914 3398 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1915 3398 : Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode));
1916 1699 : Node* node = NewNode(javascript()->DeleteProperty(), object, key, mode);
1917 1699 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1918 1699 : }
1919 :
1920 0 : void BytecodeGraphBuilder::VisitDeletePropertyStrict() {
1921 890 : BuildDelete(LanguageMode::STRICT);
1922 0 : }
1923 :
1924 0 : void BytecodeGraphBuilder::VisitDeletePropertySloppy() {
1925 809 : BuildDelete(LanguageMode::SLOPPY);
1926 0 : }
1927 :
1928 1824 : void BytecodeGraphBuilder::VisitGetSuperConstructor() {
1929 : Node* node = NewNode(javascript()->GetSuperConstructor(),
1930 912 : environment()->LookupAccumulator());
1931 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node,
1932 912 : Environment::kAttachFrameState);
1933 456 : }
1934 :
1935 2132736 : void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) {
1936 355456 : PrepareEagerCheckpoint();
1937 : Node* left =
1938 710912 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1939 355456 : Node* right = environment()->LookupAccumulator();
1940 :
1941 355456 : int slot_index = bytecode_iterator().GetIndexOperand(1);
1942 : DCHECK(slot_index != 0);
1943 355456 : FeedbackSlot slot = feedback_vector()->ToSlot(slot_index);
1944 : Node* node = nullptr;
1945 355456 : if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) {
1946 : node = simplified;
1947 : } else {
1948 : node = NewNode(op, left, right);
1949 : }
1950 355456 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1951 355456 : }
1952 :
1953 44230 : void BytecodeGraphBuilder::VisitTestEqual() {
1954 44230 : BuildCompareOp(javascript()->Equal(GetCompareOperationHint()));
1955 22115 : }
1956 :
1957 509376 : void BytecodeGraphBuilder::VisitTestEqualStrict() {
1958 509376 : BuildCompareOp(javascript()->StrictEqual(GetCompareOperationHint()));
1959 254688 : }
1960 :
1961 64904 : void BytecodeGraphBuilder::VisitTestLessThan() {
1962 64904 : BuildCompareOp(javascript()->LessThan(GetCompareOperationHint()));
1963 32452 : }
1964 :
1965 78176 : void BytecodeGraphBuilder::VisitTestGreaterThan() {
1966 78176 : BuildCompareOp(javascript()->GreaterThan(GetCompareOperationHint()));
1967 39088 : }
1968 :
1969 5348 : void BytecodeGraphBuilder::VisitTestLessThanOrEqual() {
1970 5348 : BuildCompareOp(javascript()->LessThanOrEqual(GetCompareOperationHint()));
1971 2674 : }
1972 :
1973 8878 : void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() {
1974 8878 : BuildCompareOp(javascript()->GreaterThanOrEqual(GetCompareOperationHint()));
1975 4439 : }
1976 :
1977 263670 : void BytecodeGraphBuilder::VisitTestEqualStrictNoFeedback() {
1978 : // TODO(5310): Currently this is used with both Smi operands and with
1979 : // string operands. We pass string operands for static property check in
1980 : // VisitClassLiteralProperties. This should be changed, so we only use this
1981 : // for Smi operations and lower it to SpeculativeNumberEqual[kSignedSmall]
1982 43945 : PrepareEagerCheckpoint();
1983 : Node* left =
1984 87890 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1985 43945 : Node* right = environment()->LookupAccumulator();
1986 :
1987 : Node* node = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
1988 43945 : left, right);
1989 43945 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1990 43945 : }
1991 :
1992 27175 : void BytecodeGraphBuilder::BuildTestingOp(const Operator* op) {
1993 5435 : PrepareEagerCheckpoint();
1994 : Node* left =
1995 10870 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1996 5435 : Node* right = environment()->LookupAccumulator();
1997 : Node* node = NewNode(op, left, right);
1998 5435 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1999 5435 : }
2000 :
2001 3361 : void BytecodeGraphBuilder::VisitTestIn() {
2002 3361 : BuildTestingOp(javascript()->HasProperty());
2003 3361 : }
2004 :
2005 2074 : void BytecodeGraphBuilder::VisitTestInstanceOf() {
2006 2074 : BuildTestingOp(javascript()->InstanceOf());
2007 2074 : }
2008 :
2009 23946 : void BytecodeGraphBuilder::VisitTestUndetectable() {
2010 7982 : Node* object = environment()->LookupAccumulator();
2011 7982 : Node* node = NewNode(jsgraph()->simplified()->ObjectIsUndetectable(), object);
2012 7982 : environment()->BindAccumulator(node);
2013 7982 : }
2014 :
2015 588 : void BytecodeGraphBuilder::VisitTestNull() {
2016 147 : Node* object = environment()->LookupAccumulator();
2017 : Node* result = NewNode(simplified()->ReferenceEqual(), object,
2018 294 : jsgraph()->NullConstant());
2019 147 : environment()->BindAccumulator(result);
2020 147 : }
2021 :
2022 5912 : void BytecodeGraphBuilder::VisitTestUndefined() {
2023 1478 : Node* object = environment()->LookupAccumulator();
2024 : Node* result = NewNode(simplified()->ReferenceEqual(), object,
2025 2956 : jsgraph()->UndefinedConstant());
2026 1478 : environment()->BindAccumulator(result);
2027 1478 : }
2028 :
2029 366829 : void BytecodeGraphBuilder::VisitTestTypeOf() {
2030 59584 : Node* object = environment()->LookupAccumulator();
2031 : auto literal_flag = interpreter::TestTypeOfFlags::Decode(
2032 59584 : bytecode_iterator().GetFlagOperand(0));
2033 : Node* result;
2034 59584 : switch (literal_flag) {
2035 : case interpreter::TestTypeOfFlags::LiteralFlag::kNumber:
2036 16173 : result = NewNode(simplified()->ObjectIsNumber(), object);
2037 16173 : break;
2038 : case interpreter::TestTypeOfFlags::LiteralFlag::kString:
2039 4795 : result = NewNode(simplified()->ObjectIsString(), object);
2040 4795 : break;
2041 : case interpreter::TestTypeOfFlags::LiteralFlag::kSymbol:
2042 661 : result = NewNode(simplified()->ObjectIsSymbol(), object);
2043 661 : break;
2044 : case interpreter::TestTypeOfFlags::LiteralFlag::kBoolean:
2045 : result = NewNode(common()->Select(MachineRepresentation::kTagged),
2046 : NewNode(simplified()->ReferenceEqual(), object,
2047 : jsgraph()->TrueConstant()),
2048 : jsgraph()->TrueConstant(),
2049 : NewNode(simplified()->ReferenceEqual(), object,
2050 2778 : jsgraph()->FalseConstant()));
2051 463 : break;
2052 : case interpreter::TestTypeOfFlags::LiteralFlag::kUndefined:
2053 : result = graph()->NewNode(
2054 : common()->Select(MachineRepresentation::kTagged),
2055 : graph()->NewNode(simplified()->ReferenceEqual(), object,
2056 : jsgraph()->NullConstant()),
2057 : jsgraph()->FalseConstant(),
2058 8170 : graph()->NewNode(simplified()->ObjectIsUndetectable(), object));
2059 1634 : break;
2060 : case interpreter::TestTypeOfFlags::LiteralFlag::kFunction:
2061 : result =
2062 22711 : graph()->NewNode(simplified()->ObjectIsDetectableCallable(), object);
2063 22711 : break;
2064 : case interpreter::TestTypeOfFlags::LiteralFlag::kObject:
2065 : result = graph()->NewNode(
2066 : common()->Select(MachineRepresentation::kTagged),
2067 : graph()->NewNode(simplified()->ObjectIsNonCallable(), object),
2068 : jsgraph()->TrueConstant(),
2069 : graph()->NewNode(simplified()->ReferenceEqual(), object,
2070 65735 : jsgraph()->NullConstant()));
2071 13147 : break;
2072 : case interpreter::TestTypeOfFlags::LiteralFlag::kOther:
2073 0 : UNREACHABLE(); // Should never be emitted.
2074 : result = nullptr;
2075 : break;
2076 : }
2077 59584 : environment()->BindAccumulator(result);
2078 59584 : }
2079 :
2080 11640 : void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) {
2081 3880 : Node* value = NewNode(js_op, environment()->LookupAccumulator());
2082 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value,
2083 7760 : Environment::kAttachFrameState);
2084 3880 : }
2085 :
2086 1540 : void BytecodeGraphBuilder::VisitToName() {
2087 1540 : BuildCastOperator(javascript()->ToName());
2088 1540 : }
2089 :
2090 2340 : void BytecodeGraphBuilder::VisitToObject() {
2091 2340 : BuildCastOperator(javascript()->ToObject());
2092 2340 : }
2093 :
2094 27724 : void BytecodeGraphBuilder::VisitToNumber() {
2095 4993 : PrepareEagerCheckpoint();
2096 4993 : Node* object = environment()->LookupAccumulator();
2097 :
2098 : Node* node = nullptr;
2099 : FeedbackSlot slot =
2100 9986 : feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(1));
2101 4993 : if (Node* simplified = TryBuildSimplifiedToNumber(object, slot)) {
2102 : node = simplified;
2103 : } else {
2104 2759 : node = NewNode(javascript()->ToNumber(), object);
2105 : }
2106 :
2107 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node,
2108 9986 : Environment::kAttachFrameState);
2109 4993 : }
2110 :
2111 130024 : void BytecodeGraphBuilder::VisitJump() { BuildJump(); }
2112 :
2113 10437 : void BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); }
2114 :
2115 194516 : void BytecodeGraphBuilder::VisitJumpIfTrue() { BuildJumpIfTrue(); }
2116 :
2117 7109 : void BytecodeGraphBuilder::VisitJumpIfTrueConstant() { BuildJumpIfTrue(); }
2118 :
2119 246420 : void BytecodeGraphBuilder::VisitJumpIfFalse() { BuildJumpIfFalse(); }
2120 :
2121 3289 : void BytecodeGraphBuilder::VisitJumpIfFalseConstant() { BuildJumpIfFalse(); }
2122 :
2123 0 : void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() {
2124 38002 : BuildJumpIfToBooleanTrue();
2125 0 : }
2126 :
2127 0 : void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() {
2128 1915 : BuildJumpIfToBooleanTrue();
2129 0 : }
2130 :
2131 0 : void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() {
2132 66248 : BuildJumpIfToBooleanFalse();
2133 0 : }
2134 :
2135 0 : void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() {
2136 214 : BuildJumpIfToBooleanFalse();
2137 0 : }
2138 :
2139 17327 : void BytecodeGraphBuilder::VisitJumpIfNotHole() { BuildJumpIfNotHole(); }
2140 :
2141 0 : void BytecodeGraphBuilder::VisitJumpIfNotHoleConstant() {
2142 0 : BuildJumpIfNotHole();
2143 0 : }
2144 :
2145 6292 : void BytecodeGraphBuilder::VisitJumpIfJSReceiver() { BuildJumpIfJSReceiver(); }
2146 :
2147 0 : void BytecodeGraphBuilder::VisitJumpIfJSReceiverConstant() {
2148 0 : BuildJumpIfJSReceiver();
2149 0 : }
2150 :
2151 2694 : void BytecodeGraphBuilder::VisitJumpIfNull() {
2152 2694 : BuildJumpIfEqual(jsgraph()->NullConstant());
2153 2694 : }
2154 :
2155 72 : void BytecodeGraphBuilder::VisitJumpIfNullConstant() {
2156 72 : BuildJumpIfEqual(jsgraph()->NullConstant());
2157 72 : }
2158 :
2159 2434 : void BytecodeGraphBuilder::VisitJumpIfNotNull() {
2160 2434 : BuildJumpIfNotEqual(jsgraph()->NullConstant());
2161 2434 : }
2162 :
2163 0 : void BytecodeGraphBuilder::VisitJumpIfNotNullConstant() {
2164 0 : BuildJumpIfNotEqual(jsgraph()->NullConstant());
2165 0 : }
2166 :
2167 11128 : void BytecodeGraphBuilder::VisitJumpIfUndefined() {
2168 11128 : BuildJumpIfEqual(jsgraph()->UndefinedConstant());
2169 11128 : }
2170 :
2171 171 : void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() {
2172 171 : BuildJumpIfEqual(jsgraph()->UndefinedConstant());
2173 171 : }
2174 :
2175 5924 : void BytecodeGraphBuilder::VisitJumpIfNotUndefined() {
2176 5924 : BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
2177 5924 : }
2178 :
2179 8 : void BytecodeGraphBuilder::VisitJumpIfNotUndefinedConstant() {
2180 8 : BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
2181 8 : }
2182 :
2183 44488 : void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); }
2184 :
2185 1316895 : void BytecodeGraphBuilder::VisitStackCheck() {
2186 438965 : PrepareEagerCheckpoint();
2187 438965 : Node* node = NewNode(javascript()->StackCheck());
2188 438965 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
2189 438964 : }
2190 :
2191 163040 : void BytecodeGraphBuilder::VisitSetPendingMessage() {
2192 40760 : Node* previous_message = NewNode(javascript()->LoadMessage());
2193 81520 : NewNode(javascript()->StoreMessage(), environment()->LookupAccumulator());
2194 40760 : environment()->BindAccumulator(previous_message);
2195 40760 : }
2196 :
2197 2478996 : void BytecodeGraphBuilder::VisitReturn() {
2198 : BuildLoopExitsForFunctionExit();
2199 619749 : Node* pop_node = jsgraph()->ZeroConstant();
2200 : Node* control =
2201 1239498 : NewNode(common()->Return(), pop_node, environment()->LookupAccumulator());
2202 : MergeControlToLeaveFunction(control);
2203 619748 : }
2204 :
2205 3087 : void BytecodeGraphBuilder::VisitDebugger() {
2206 1029 : PrepareEagerCheckpoint();
2207 1029 : Node* call = NewNode(javascript()->Debugger());
2208 1029 : environment()->RecordAfterState(call, Environment::kAttachFrameState);
2209 1029 : }
2210 :
2211 : // We cannot create a graph from the debugger copy of the bytecode array.
2212 : #define DEBUG_BREAK(Name, ...) \
2213 : void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); }
2214 0 : DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
2215 : #undef DEBUG_BREAK
2216 :
2217 8976 : void BytecodeGraphBuilder::VisitForInPrepare() {
2218 1496 : PrepareEagerCheckpoint();
2219 : Node* receiver =
2220 2992 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2221 1496 : Node* prepare = NewNode(javascript()->ForInPrepare(), receiver);
2222 : environment()->BindRegistersToProjections(
2223 : bytecode_iterator().GetRegisterOperand(1), prepare,
2224 2992 : Environment::kAttachFrameState);
2225 1496 : }
2226 :
2227 10472 : void BytecodeGraphBuilder::VisitForInContinue() {
2228 1496 : PrepareEagerCheckpoint();
2229 : Node* index =
2230 2992 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2231 : Node* cache_length =
2232 2992 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2233 : Node* exit_cond =
2234 : NewNode(javascript()->LessThan(CompareOperationHint::kSignedSmall), index,
2235 1496 : cache_length);
2236 1496 : environment()->BindAccumulator(exit_cond, Environment::kAttachFrameState);
2237 1496 : }
2238 :
2239 14960 : void BytecodeGraphBuilder::VisitForInNext() {
2240 1496 : PrepareEagerCheckpoint();
2241 : Node* receiver =
2242 2992 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2243 : Node* index =
2244 2992 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2245 2992 : int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index();
2246 : Node* cache_type = environment()->LookupRegister(
2247 1496 : interpreter::Register(catch_reg_pair_index));
2248 : Node* cache_array = environment()->LookupRegister(
2249 2992 : interpreter::Register(catch_reg_pair_index + 1));
2250 :
2251 : Node* value = NewNode(javascript()->ForInNext(), receiver, cache_array,
2252 1496 : cache_type, index);
2253 1496 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
2254 1496 : }
2255 :
2256 8976 : void BytecodeGraphBuilder::VisitForInStep() {
2257 1496 : PrepareEagerCheckpoint();
2258 : Node* index =
2259 2992 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2260 : index = NewNode(
2261 : simplified()->SpeculativeNumberAdd(NumberOperationHint::kSignedSmall),
2262 2992 : index, jsgraph()->OneConstant());
2263 1496 : environment()->BindAccumulator(index, Environment::kAttachFrameState);
2264 1496 : }
2265 :
2266 155839 : void BytecodeGraphBuilder::VisitSuspendGenerator() {
2267 6825 : Node* state = environment()->LookupAccumulator();
2268 : Node* generator = environment()->LookupRegister(
2269 13650 : bytecode_iterator().GetRegisterOperand(0));
2270 : SuspendFlags flags = interpreter::SuspendGeneratorBytecodeFlags::Decode(
2271 6825 : bytecode_iterator().GetFlagOperand(1));
2272 : // The offsets used by the bytecode iterator are relative to a different base
2273 : // than what is used in the interpreter, hence the addition.
2274 : Node* offset =
2275 6825 : jsgraph()->Constant(bytecode_iterator().current_offset() +
2276 13650 : (BytecodeArray::kHeaderSize - kHeapObjectTag));
2277 :
2278 6825 : int register_count = environment()->register_count();
2279 6825 : int value_input_count = 3 + register_count;
2280 :
2281 6825 : Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count);
2282 6825 : value_inputs[0] = generator;
2283 6825 : value_inputs[1] = state;
2284 6825 : value_inputs[2] = offset;
2285 101239 : for (int i = 0; i < register_count; ++i) {
2286 94414 : value_inputs[3 + i] =
2287 94414 : environment()->LookupRegister(interpreter::Register(i));
2288 : }
2289 :
2290 : MakeNode(javascript()->GeneratorStore(register_count, flags),
2291 6825 : value_input_count, value_inputs, false);
2292 6825 : }
2293 :
2294 114585 : void BytecodeGraphBuilder::VisitResumeGenerator() {
2295 2460 : PrepareEagerCheckpoint();
2296 :
2297 : Node* generator = environment()->LookupRegister(
2298 4920 : bytecode_iterator().GetRegisterOperand(0));
2299 :
2300 : // Bijection between registers and array indices must match that used in
2301 : // InterpreterAssembler::ExportRegisterFile.
2302 71470 : for (int i = 0; i < environment()->register_count(); ++i) {
2303 33275 : Node* value = NewNode(javascript()->GeneratorRestoreRegister(i), generator);
2304 33275 : environment()->BindRegister(interpreter::Register(i), value);
2305 : }
2306 :
2307 : Node* state =
2308 2460 : NewNode(javascript()->GeneratorRestoreContinuation(), generator);
2309 :
2310 2460 : environment()->BindAccumulator(state, Environment::kAttachFrameState);
2311 2460 : }
2312 :
2313 0 : void BytecodeGraphBuilder::VisitWide() {
2314 : // Consumed by the BytecodeArrayIterator.
2315 0 : UNREACHABLE();
2316 : }
2317 :
2318 0 : void BytecodeGraphBuilder::VisitExtraWide() {
2319 : // Consumed by the BytecodeArrayIterator.
2320 0 : UNREACHABLE();
2321 : }
2322 :
2323 0 : void BytecodeGraphBuilder::VisitIllegal() {
2324 : // Not emitted in valid bytecode.
2325 0 : UNREACHABLE();
2326 : }
2327 :
2328 0 : void BytecodeGraphBuilder::VisitNop() {}
2329 :
2330 14989269 : void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) {
2331 : auto it = merge_environments_.find(current_offset);
2332 14338900 : if (it != merge_environments_.end()) {
2333 : mark_as_needing_eager_checkpoint(true);
2334 650371 : if (environment() != nullptr) {
2335 218434 : it->second->Merge(environment());
2336 : }
2337 650371 : set_environment(it->second);
2338 : }
2339 14338900 : }
2340 :
2341 27671307 : void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) {
2342 27533388 : if (bytecode_analysis()->IsLoopHeader(current_offset)) {
2343 : mark_as_needing_eager_checkpoint(true);
2344 : const LoopInfo& loop_info =
2345 91946 : bytecode_analysis()->GetLoopInfoFor(current_offset);
2346 :
2347 : // Add loop header.
2348 91946 : environment()->PrepareForLoop(loop_info.assignments());
2349 :
2350 45973 : BuildOSRLoopEntryPoint(current_offset);
2351 :
2352 : // Store a copy of the environment so we can connect merged back edge inputs
2353 : // to the loop header.
2354 91946 : merge_environments_[current_offset] = environment()->Copy();
2355 : }
2356 13766698 : }
2357 :
2358 2156606 : void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) {
2359 1078303 : BuildLoopExitsForBranch(target_offset);
2360 1078303 : Environment*& merge_environment = merge_environments_[target_offset];
2361 1078302 : if (merge_environment == nullptr) {
2362 : // Append merge nodes to the environment. We may merge here with another
2363 : // environment. So add a place holder for merge nodes. We may add redundant
2364 : // but will be eliminated in a later pass.
2365 : // TODO(mstarzinger): Be smarter about this!
2366 650370 : NewMerge();
2367 650371 : merge_environment = environment();
2368 : } else {
2369 427932 : merge_environment->Merge(environment());
2370 : }
2371 : set_environment(nullptr);
2372 1078303 : }
2373 :
2374 0 : void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) {
2375 676744 : exit_controls_.push_back(exit);
2376 : set_environment(nullptr);
2377 0 : }
2378 :
2379 57473 : void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) {
2380 : DCHECK(bytecode_analysis()->IsLoopHeader(current_offset));
2381 :
2382 45973 : if (bytecode_analysis()->IsOSREntryPoint(current_offset)) {
2383 : // For OSR add a special {OsrLoopEntry} node into the current loop header.
2384 : // It will be turned into a usable entry by the OSR deconstruction.
2385 5750 : Environment* osr_env = environment()->Copy();
2386 5750 : osr_env->PrepareForOsrEntry();
2387 5750 : environment()->Merge(osr_env);
2388 : }
2389 45973 : }
2390 :
2391 435506 : void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() {
2392 429756 : if (bytecode_analysis()->HasOSREntryPoint()) {
2393 : // For OSR add an {OsrNormalEntry} as the the top-level environment start.
2394 : // It will be replaced with {Dead} by the OSR deconstruction.
2395 5750 : NewNode(common()->OsrNormalEntry());
2396 : }
2397 429756 : }
2398 :
2399 2112118 : void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) {
2400 1078303 : int origin_offset = bytecode_iterator().current_offset();
2401 : // Only build loop exits for forward edges.
2402 1078303 : if (target_offset > origin_offset) {
2403 : BuildLoopExitsUntilLoop(
2404 1033815 : bytecode_analysis()->GetLoopOffsetFor(target_offset));
2405 : }
2406 1078303 : }
2407 :
2408 3737810 : void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) {
2409 1687026 : int origin_offset = bytecode_iterator().current_offset();
2410 1687026 : int current_loop = bytecode_analysis()->GetLoopOffsetFor(origin_offset);
2411 3555931 : while (loop_offset < current_loop) {
2412 181879 : Node* loop_node = merge_environments_[current_loop]->GetControlDependency();
2413 181879 : const LoopInfo& loop_info =
2414 363758 : bytecode_analysis()->GetLoopInfoFor(current_loop);
2415 363758 : environment()->PrepareForLoopExit(loop_node, loop_info.assignments());
2416 181879 : current_loop = loop_info.parent_offset();
2417 : }
2418 1687026 : }
2419 :
2420 0 : void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit() {
2421 653212 : BuildLoopExitsUntilLoop(-1);
2422 0 : }
2423 :
2424 184949 : void BytecodeGraphBuilder::BuildJump() {
2425 184949 : MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
2426 184949 : }
2427 :
2428 180822 : void BytecodeGraphBuilder::BuildJumpIf(Node* condition) {
2429 60274 : NewBranch(condition);
2430 60274 : Environment* if_false_environment = environment()->Copy();
2431 60274 : NewIfTrue();
2432 60274 : MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
2433 : set_environment(if_false_environment);
2434 60274 : NewIfFalse();
2435 60274 : }
2436 :
2437 276465 : void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) {
2438 92155 : NewBranch(condition);
2439 92155 : Environment* if_true_environment = environment()->Copy();
2440 92155 : NewIfFalse();
2441 92155 : MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
2442 : set_environment(if_true_environment);
2443 92155 : NewIfTrue();
2444 92155 : }
2445 :
2446 28130 : void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
2447 14065 : Node* accumulator = environment()->LookupAccumulator();
2448 : Node* condition =
2449 14065 : NewNode(simplified()->ReferenceEqual(), accumulator, comperand);
2450 14065 : BuildJumpIf(condition);
2451 14065 : }
2452 :
2453 16732 : void BytecodeGraphBuilder::BuildJumpIfNotEqual(Node* comperand) {
2454 8366 : Node* accumulator = environment()->LookupAccumulator();
2455 : Node* condition =
2456 8366 : NewNode(simplified()->ReferenceEqual(), accumulator, comperand);
2457 8366 : BuildJumpIfNot(condition);
2458 8366 : }
2459 :
2460 1498254 : void BytecodeGraphBuilder::BuildJumpIfFalse() {
2461 249709 : NewBranch(environment()->LookupAccumulator());
2462 249709 : Environment* if_true_environment = environment()->Copy();
2463 499418 : environment()->BindAccumulator(jsgraph()->FalseConstant());
2464 249709 : NewIfFalse();
2465 249709 : MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
2466 249709 : if_true_environment->BindAccumulator(jsgraph()->TrueConstant());
2467 : set_environment(if_true_environment);
2468 249709 : NewIfTrue();
2469 249709 : }
2470 :
2471 1209750 : void BytecodeGraphBuilder::BuildJumpIfTrue() {
2472 201625 : NewBranch(environment()->LookupAccumulator());
2473 201625 : Environment* if_false_environment = environment()->Copy();
2474 403250 : environment()->BindAccumulator(jsgraph()->TrueConstant());
2475 201625 : NewIfTrue();
2476 201625 : MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
2477 201625 : if_false_environment->BindAccumulator(jsgraph()->FalseConstant());
2478 : set_environment(if_false_environment);
2479 201625 : NewIfFalse();
2480 201625 : }
2481 :
2482 79834 : void BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() {
2483 39917 : Node* accumulator = environment()->LookupAccumulator();
2484 : Node* condition =
2485 79834 : NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator);
2486 39917 : BuildJumpIf(condition);
2487 39917 : }
2488 :
2489 132924 : void BytecodeGraphBuilder::BuildJumpIfToBooleanFalse() {
2490 66462 : Node* accumulator = environment()->LookupAccumulator();
2491 : Node* condition =
2492 132924 : NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator);
2493 66462 : BuildJumpIfNot(condition);
2494 66462 : }
2495 :
2496 51981 : void BytecodeGraphBuilder::BuildJumpIfNotHole() {
2497 17327 : Node* accumulator = environment()->LookupAccumulator();
2498 : Node* condition = NewNode(simplified()->ReferenceEqual(), accumulator,
2499 34654 : jsgraph()->TheHoleConstant());
2500 17327 : BuildJumpIfNot(condition);
2501 17327 : }
2502 :
2503 12584 : void BytecodeGraphBuilder::BuildJumpIfJSReceiver() {
2504 6292 : Node* accumulator = environment()->LookupAccumulator();
2505 6292 : Node* condition = NewNode(simplified()->ObjectIsReceiver(), accumulator);
2506 6292 : BuildJumpIf(condition);
2507 6292 : }
2508 :
2509 838723 : Node* BytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op,
2510 : Node* left, Node* right,
2511 838723 : FeedbackSlot slot) {
2512 838723 : Node* effect = environment()->GetEffectDependency();
2513 838723 : Node* control = environment()->GetControlDependency();
2514 838723 : Reduction early_reduction = type_hint_lowering().ReduceBinaryOperation(
2515 838723 : op, left, right, effect, control, slot);
2516 838723 : if (early_reduction.Changed()) {
2517 309494 : ApplyEarlyReduction(early_reduction);
2518 309494 : return early_reduction.replacement();
2519 : }
2520 : return nullptr;
2521 : }
2522 :
2523 4993 : Node* BytecodeGraphBuilder::TryBuildSimplifiedToNumber(Node* value,
2524 4993 : FeedbackSlot slot) {
2525 4993 : Node* effect = environment()->GetEffectDependency();
2526 4993 : Node* control = environment()->GetControlDependency();
2527 4993 : Reduction early_reduction = type_hint_lowering().ReduceToNumberOperation(
2528 4993 : value, effect, control, slot);
2529 4993 : if (early_reduction.Changed()) {
2530 2234 : ApplyEarlyReduction(early_reduction);
2531 2234 : return early_reduction.replacement();
2532 : }
2533 : return nullptr;
2534 : }
2535 :
2536 460053 : Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op,
2537 : Node* receiver,
2538 914924 : FeedbackSlot slot) {
2539 : // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
2540 : // pruned from the graph by a soft-deopt. It can happen that a LoadIC that
2541 : // control-dominates the OSR entry is still in "uninitialized" state.
2542 460053 : if (bytecode_analysis()->HasOSREntryPoint()) return nullptr;
2543 454871 : Node* effect = environment()->GetEffectDependency();
2544 454871 : Node* control = environment()->GetControlDependency();
2545 454871 : Reduction early_reduction = type_hint_lowering().ReduceLoadNamedOperation(
2546 454871 : op, receiver, effect, control, slot);
2547 454871 : if (early_reduction.Changed()) {
2548 22733 : ApplyEarlyReduction(early_reduction);
2549 22733 : return early_reduction.replacement();
2550 : }
2551 : return nullptr;
2552 : }
2553 :
2554 68752 : Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadKeyed(const Operator* op,
2555 : Node* receiver,
2556 : Node* key,
2557 136554 : FeedbackSlot slot) {
2558 : // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
2559 : // pruned from the graph by a soft-deopt. It can happen that a LoadIC that
2560 : // control-dominates the OSR entry is still in "uninitialized" state.
2561 68752 : if (bytecode_analysis()->HasOSREntryPoint()) return nullptr;
2562 67802 : Node* effect = environment()->GetEffectDependency();
2563 67802 : Node* control = environment()->GetControlDependency();
2564 67802 : Reduction early_reduction = type_hint_lowering().ReduceLoadKeyedOperation(
2565 67802 : op, receiver, key, effect, control, slot);
2566 67802 : if (early_reduction.Changed()) {
2567 354 : ApplyEarlyReduction(early_reduction);
2568 354 : return early_reduction.replacement();
2569 : }
2570 : return nullptr;
2571 : }
2572 :
2573 98797 : Node* BytecodeGraphBuilder::TryBuildSimplifiedStoreNamed(const Operator* op,
2574 : Node* receiver,
2575 : Node* value,
2576 196855 : FeedbackSlot slot) {
2577 : // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
2578 : // pruned from the graph by a soft-deopt. It can happen that a LoadIC that
2579 : // control-dominates the OSR entry is still in "uninitialized" state.
2580 98797 : if (bytecode_analysis()->HasOSREntryPoint()) return nullptr;
2581 98058 : Node* effect = environment()->GetEffectDependency();
2582 98058 : Node* control = environment()->GetControlDependency();
2583 98058 : Reduction early_reduction = type_hint_lowering().ReduceStoreNamedOperation(
2584 98058 : op, receiver, value, effect, control, slot);
2585 98058 : if (early_reduction.Changed()) {
2586 375 : ApplyEarlyReduction(early_reduction);
2587 375 : return early_reduction.replacement();
2588 : }
2589 : return nullptr;
2590 : }
2591 :
2592 40701 : Node* BytecodeGraphBuilder::TryBuildSimplifiedStoreKeyed(const Operator* op,
2593 : Node* receiver,
2594 : Node* key, Node* value,
2595 80065 : FeedbackSlot slot) {
2596 : // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
2597 : // pruned from the graph by a soft-deopt. It can happen that a LoadIC that
2598 : // control-dominates the OSR entry is still in "uninitialized" state.
2599 40701 : if (bytecode_analysis()->HasOSREntryPoint()) return nullptr;
2600 39364 : Node* effect = environment()->GetEffectDependency();
2601 39364 : Node* control = environment()->GetControlDependency();
2602 39364 : Reduction early_reduction = type_hint_lowering().ReduceStoreKeyedOperation(
2603 39364 : op, receiver, key, value, effect, control, slot);
2604 39364 : if (early_reduction.Changed()) {
2605 71 : ApplyEarlyReduction(early_reduction);
2606 71 : return early_reduction.replacement();
2607 : }
2608 : return nullptr;
2609 : }
2610 :
2611 646989 : void BytecodeGraphBuilder::ApplyEarlyReduction(Reduction reduction) {
2612 670522 : Node* node = reduction.replacement();
2613 : DCHECK(node->op()->HasProperty(Operator::kNoWrite));
2614 670522 : if (node->op()->EffectOutputCount() > 0) {
2615 : environment()->UpdateEffectDependency(node);
2616 : }
2617 335261 : if (IrOpcode::IsGraphTerminator(node->opcode())) {
2618 : MergeControlToLeaveFunction(node);
2619 : }
2620 335261 : }
2621 :
2622 13893333 : Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
2623 13463445 : if (size > input_buffer_size_) {
2624 429888 : size = size + kInputBufferSizeIncrement + input_buffer_size_;
2625 859776 : input_buffer_ = local_zone()->NewArray<Node*>(size);
2626 429888 : input_buffer_size_ = size;
2627 : }
2628 13463445 : return input_buffer_;
2629 : }
2630 :
2631 14338899 : void BytecodeGraphBuilder::EnterAndExitExceptionHandlers(int current_offset) {
2632 14338899 : Handle<HandlerTable> table = exception_handler_table();
2633 : int num_entries = table->NumberOfRangeEntries();
2634 :
2635 : // Potentially exit exception handlers.
2636 28716606 : while (!exception_handlers_.empty()) {
2637 1256014 : int current_end = exception_handlers_.top().end_offset_;
2638 1256014 : if (current_offset < current_end) break; // Still covered by range.
2639 : exception_handlers_.pop();
2640 : }
2641 :
2642 : // Potentially enter exception handlers.
2643 14377707 : while (current_exception_handler_ < num_entries) {
2644 : int next_start = table->GetRangeStart(current_exception_handler_);
2645 1526645 : if (current_offset < next_start) break; // Not yet covered by range.
2646 77616 : int next_end = table->GetRangeEnd(current_exception_handler_);
2647 77616 : int next_handler = table->GetRangeHandler(current_exception_handler_);
2648 77616 : int context_register = table->GetRangeData(current_exception_handler_);
2649 : exception_handlers_.push(
2650 77616 : {next_start, next_end, next_handler, context_register});
2651 38808 : current_exception_handler_++;
2652 : }
2653 14338899 : }
2654 :
2655 37066777 : Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
2656 : Node* const* value_inputs,
2657 59323472 : bool incomplete) {
2658 : DCHECK_EQ(op->ValueInputCount(), value_input_count);
2659 :
2660 12355599 : bool has_context = OperatorProperties::HasContextInput(op);
2661 12355595 : bool has_frame_state = OperatorProperties::HasFrameStateInput(op);
2662 12355589 : bool has_control = op->ControlInputCount() == 1;
2663 12355589 : bool has_effect = op->EffectInputCount() == 1;
2664 :
2665 : DCHECK_LT(op->ControlInputCount(), 2);
2666 : DCHECK_LT(op->EffectInputCount(), 2);
2667 :
2668 53144214 : Node* result = nullptr;
2669 12355589 : if (!has_context && !has_frame_state && !has_control && !has_effect) {
2670 2156778 : result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
2671 : } else {
2672 11277200 : bool inside_handler = !exception_handlers_.empty();
2673 : int input_count_with_deps = value_input_count;
2674 11277200 : if (has_context) ++input_count_with_deps;
2675 11277200 : if (has_frame_state) ++input_count_with_deps;
2676 11277200 : if (has_control) ++input_count_with_deps;
2677 11277200 : if (has_effect) ++input_count_with_deps;
2678 11277200 : Node** buffer = EnsureInputBufferSize(input_count_with_deps);
2679 11277203 : memcpy(buffer, value_inputs, kPointerSize * value_input_count);
2680 11277203 : Node** current_input = buffer + value_input_count;
2681 11277203 : if (has_context) {
2682 9315406 : *current_input++ = environment()->Context();
2683 : }
2684 11277203 : if (has_frame_state) {
2685 : // The frame state will be inserted later. Here we misuse the {Dead} node
2686 : // as a sentinel to be later overwritten with the real frame state by the
2687 : // calls to {PrepareFrameState} within individual visitor methods.
2688 11862044 : *current_input++ = jsgraph()->Dead();
2689 : }
2690 11277206 : if (has_effect) {
2691 16070612 : *current_input++ = environment()->GetEffectDependency();
2692 : }
2693 11277206 : if (has_control) {
2694 10583663 : *current_input++ = environment()->GetControlDependency();
2695 : }
2696 22554412 : result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
2697 : // Update the current control dependency for control-producing nodes.
2698 22554446 : if (result->op()->ControlOutputCount() > 0) {
2699 : environment()->UpdateControlDependency(result);
2700 : }
2701 : // Update the current effect dependency for effect-producing nodes.
2702 22554446 : if (result->op()->EffectOutputCount() > 0) {
2703 : environment()->UpdateEffectDependency(result);
2704 : }
2705 : // Add implicit exception continuation for throwing nodes.
2706 11277223 : if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
2707 289592 : int handler_offset = exception_handlers_.top().handler_offset_;
2708 289592 : int context_index = exception_handlers_.top().context_register_;
2709 : interpreter::Register context_register(context_index);
2710 289592 : Environment* success_env = environment()->Copy();
2711 289592 : const Operator* op = common()->IfException();
2712 289592 : Node* effect = environment()->GetEffectDependency();
2713 : Node* on_exception = graph()->NewNode(op, effect, result);
2714 289592 : Node* context = environment()->LookupRegister(context_register);
2715 : environment()->UpdateControlDependency(on_exception);
2716 : environment()->UpdateEffectDependency(on_exception);
2717 289592 : environment()->BindAccumulator(on_exception);
2718 : environment()->SetContext(context);
2719 289592 : MergeIntoSuccessorEnvironment(handler_offset);
2720 : set_environment(success_env);
2721 : }
2722 : // Add implicit success continuation for throwing nodes.
2723 11277223 : if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
2724 289592 : const Operator* if_success = common()->IfSuccess();
2725 : Node* on_success = graph()->NewNode(if_success, result);
2726 : environment()->UpdateControlDependency(on_success);
2727 : }
2728 : // Ensure checkpoints are created after operations with side-effects.
2729 19312545 : if (has_effect && !result->op()->HasProperty(Operator::kNoWrite)) {
2730 : mark_as_needing_eager_checkpoint(true);
2731 : }
2732 : }
2733 :
2734 12355612 : return result;
2735 : }
2736 :
2737 :
2738 3524306 : Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) {
2739 1762153 : const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
2740 1762153 : Node** buffer = EnsureInputBufferSize(count + 1);
2741 : MemsetPointer(buffer, input, count);
2742 1762153 : buffer[count] = control;
2743 1762153 : return graph()->NewNode(phi_op, count + 1, buffer, true);
2744 : }
2745 :
2746 :
2747 424108 : Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input,
2748 848216 : Node* control) {
2749 424108 : const Operator* phi_op = common()->EffectPhi(count);
2750 424108 : Node** buffer = EnsureInputBufferSize(count + 1);
2751 : MemsetPointer(buffer, input, count);
2752 424108 : buffer[count] = control;
2753 424108 : return graph()->NewNode(phi_op, count + 1, buffer, true);
2754 : }
2755 :
2756 :
2757 1540072 : Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
2758 1540072 : int inputs = control->op()->ControlInputCount() + 1;
2759 770036 : if (control->opcode() == IrOpcode::kLoop) {
2760 : // Control node for loop exists, add input.
2761 50238 : const Operator* op = common()->Loop(inputs);
2762 50238 : control->AppendInput(graph_zone(), other);
2763 50238 : NodeProperties::ChangeOp(control, op);
2764 719798 : } else if (control->opcode() == IrOpcode::kMerge) {
2765 : // Control node for merge exists, add input.
2766 719798 : const Operator* op = common()->Merge(inputs);
2767 719798 : control->AppendInput(graph_zone(), other);
2768 719798 : NodeProperties::ChangeOp(control, op);
2769 : } else {
2770 : // Control node is a singleton, introduce a merge.
2771 0 : const Operator* op = common()->Merge(inputs);
2772 0 : Node* merge_inputs[] = {control, other};
2773 0 : control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true);
2774 : }
2775 770036 : return control;
2776 : }
2777 :
2778 :
2779 1540074 : Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
2780 1130103 : Node* control) {
2781 770037 : int inputs = control->op()->ControlInputCount();
2782 1142822 : if (value->opcode() == IrOpcode::kEffectPhi &&
2783 372785 : NodeProperties::GetControlInput(value) == control) {
2784 : // Phi already exists, add input.
2785 720132 : value->InsertInput(graph_zone(), inputs - 1, other);
2786 360066 : NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
2787 409971 : } else if (value != other) {
2788 : // Phi does not exist yet, introduce one.
2789 378135 : value = NewEffectPhi(inputs, value, control);
2790 378135 : value->ReplaceInput(inputs - 1, other);
2791 : }
2792 770037 : return value;
2793 : }
2794 :
2795 :
2796 31303208 : Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
2797 19093067 : Node* control) {
2798 15651604 : int inputs = control->op()->ControlInputCount();
2799 21742657 : if (value->opcode() == IrOpcode::kPhi &&
2800 6091050 : NodeProperties::GetControlInput(value) == control) {
2801 : // Phi already exists, add input.
2802 6882908 : value->InsertInput(graph_zone(), inputs - 1, other);
2803 : NodeProperties::ChangeOp(
2804 3441463 : value, common()->Phi(MachineRepresentation::kTagged, inputs));
2805 12210153 : } else if (value != other) {
2806 : // Phi does not exist yet, introduce one.
2807 1381173 : value = NewPhi(inputs, value, control);
2808 1381171 : value->ReplaceInput(inputs - 1, other);
2809 : }
2810 15651602 : return value;
2811 : }
2812 :
2813 14338874 : void BytecodeGraphBuilder::UpdateCurrentSourcePosition(
2814 32383050 : SourcePositionTableIterator* it, int offset) {
2815 28677751 : if (it->done()) return;
2816 :
2817 13139909 : if (it->code_offset() == offset) {
2818 : source_positions_->SetCurrentPosition(SourcePosition(
2819 4904267 : it->source_position().ScriptOffset(), start_position_.InliningId()));
2820 4904267 : it->Advance();
2821 : } else {
2822 : DCHECK_GT(it->code_offset(), offset);
2823 : }
2824 : }
2825 :
2826 : } // namespace compiler
2827 : } // namespace internal
2828 : } // namespace v8
|