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,
29 : interpreter::Register incoming_new_target_or_generator,
30 : Node* control_dependency);
31 :
32 : // Specifies whether environment binding methods should attach frame state
33 : // inputs to nodes representing the value being bound. This is done because
34 : // the {OutputFrameStateCombine} is closely related to the binding method.
35 : enum FrameStateAttachmentMode { kAttachFrameState, kDontAttachFrameState };
36 :
37 : int parameter_count() const { return parameter_count_; }
38 : int register_count() const { return register_count_; }
39 :
40 : Node* LookupAccumulator() const;
41 : Node* LookupRegister(interpreter::Register the_register) const;
42 :
43 : void BindAccumulator(Node* node,
44 : FrameStateAttachmentMode mode = kDontAttachFrameState);
45 : void BindRegister(interpreter::Register the_register, Node* node,
46 : FrameStateAttachmentMode mode = kDontAttachFrameState);
47 : void BindRegistersToProjections(
48 : interpreter::Register first_reg, Node* node,
49 : FrameStateAttachmentMode mode = kDontAttachFrameState);
50 : void RecordAfterState(Node* node,
51 : FrameStateAttachmentMode mode = kDontAttachFrameState);
52 :
53 : // Effect dependency tracked by this environment.
54 : Node* GetEffectDependency() { return effect_dependency_; }
55 : void UpdateEffectDependency(Node* dependency) {
56 9980706 : effect_dependency_ = dependency;
57 : }
58 :
59 : // Preserve a checkpoint of the environment for the IR graph. Any
60 : // further mutation of the environment will not affect checkpoints.
61 : Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine,
62 : const BytecodeLivenessState* liveness);
63 :
64 : // Control dependency tracked by this environment.
65 : Node* GetControlDependency() const { return control_dependency_; }
66 : void UpdateControlDependency(Node* dependency) {
67 7980381 : control_dependency_ = dependency;
68 : }
69 :
70 : Node* Context() const { return context_; }
71 260714 : void SetContext(Node* new_context) { context_ = new_context; }
72 :
73 : Environment* Copy();
74 : void Merge(Environment* other, const BytecodeLivenessState* liveness);
75 :
76 : void FillWithOsrValues();
77 : void PrepareForLoop(const BytecodeLoopAssignments& assignments,
78 : const BytecodeLivenessState* liveness);
79 : void PrepareForLoopExit(Node* loop,
80 : const BytecodeLoopAssignments& assignments,
81 : const BytecodeLivenessState* liveness);
82 :
83 : private:
84 : explicit Environment(const Environment* copy);
85 :
86 : bool StateValuesRequireUpdate(Node** state_values, Node** values, int count);
87 : void UpdateStateValues(Node** state_values, Node** values, int count);
88 : Node* GetStateValuesFromCache(Node** values, int count,
89 : const BitVector* liveness, int liveness_offset);
90 :
91 : int RegisterToValuesIndex(interpreter::Register the_register) const;
92 :
93 1581256 : Zone* zone() const { return builder_->local_zone(); }
94 10100050 : Graph* graph() const { return builder_->graph(); }
95 10093728 : CommonOperatorBuilder* common() const { return builder_->common(); }
96 : BytecodeGraphBuilder* builder() const { return builder_; }
97 : const NodeVector* values() const { return &values_; }
98 : NodeVector* values() { return &values_; }
99 : int register_base() const { return register_base_; }
100 : int accumulator_base() const { return accumulator_base_; }
101 :
102 : BytecodeGraphBuilder* builder_;
103 : int register_count_;
104 : int parameter_count_;
105 : Node* context_;
106 : Node* control_dependency_;
107 : Node* effect_dependency_;
108 : NodeVector values_;
109 : Node* parameters_state_values_;
110 : int register_base_;
111 : int accumulator_base_;
112 : };
113 :
114 : // A helper for creating a temporary sub-environment for simple branches.
115 : struct BytecodeGraphBuilder::SubEnvironment final {
116 : public:
117 574234 : explicit SubEnvironment(BytecodeGraphBuilder* builder)
118 574234 : : builder_(builder), parent_(builder->environment()->Copy()) {}
119 :
120 : ~SubEnvironment() { builder_->set_environment(parent_); }
121 :
122 : private:
123 : BytecodeGraphBuilder* builder_;
124 : BytecodeGraphBuilder::Environment* parent_;
125 : };
126 :
127 : // Issues:
128 : // - Scopes - intimately tied to AST. Need to eval what is needed.
129 : // - Need to resolve closure parameter treatment.
130 504908 : BytecodeGraphBuilder::Environment::Environment(
131 3330940 : BytecodeGraphBuilder* builder, int register_count, int parameter_count,
132 : interpreter::Register incoming_new_target_or_generator,
133 4642243 : Node* control_dependency)
134 : : builder_(builder),
135 : register_count_(register_count),
136 : parameter_count_(parameter_count),
137 : control_dependency_(control_dependency),
138 : effect_dependency_(control_dependency),
139 : values_(builder->local_zone()),
140 1009816 : parameters_state_values_(nullptr) {
141 : // The layout of values_ is:
142 : //
143 : // [receiver] [parameters] [registers] [accumulator]
144 : //
145 : // parameter[0] is the receiver (this), parameters 1..N are the
146 : // parameters supplied to the method (arg0..argN-1). The accumulator
147 : // is stored separately.
148 :
149 : // Parameters including the receiver
150 2300435 : for (int i = 0; i < parameter_count; i++) {
151 1795525 : const char* debug_name = (i == 0) ? "%this" : nullptr;
152 1795525 : const Operator* op = common()->Parameter(i, debug_name);
153 3591051 : Node* parameter = builder->graph()->NewNode(op, graph()->start());
154 1795527 : values()->push_back(parameter);
155 : }
156 :
157 : // Registers
158 1009820 : register_base_ = static_cast<int>(values()->size());
159 504910 : Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
160 1009820 : values()->insert(values()->end(), register_count, undefined_constant);
161 :
162 : // Accumulator
163 1009820 : accumulator_base_ = static_cast<int>(values()->size());
164 504910 : values()->push_back(undefined_constant);
165 :
166 : // Context
167 : int context_index = Linkage::GetJSCallContextParamIndex(parameter_count);
168 504907 : const Operator* op = common()->Parameter(context_index, "%context");
169 1009819 : context_ = builder->graph()->NewNode(op, graph()->start());
170 :
171 : // Incoming new.target or generator register
172 504910 : if (incoming_new_target_or_generator.is_valid()) {
173 : int new_target_index =
174 : Linkage::GetJSCallNewTargetParamIndex(parameter_count);
175 20689 : const Operator* op = common()->Parameter(new_target_index, "%new.target");
176 20689 : Node* new_target_node = builder->graph()->NewNode(op, graph()->start());
177 :
178 : int values_index = RegisterToValuesIndex(incoming_new_target_or_generator);
179 41378 : values()->at(values_index) = new_target_node;
180 : }
181 504910 : }
182 :
183 790628 : BytecodeGraphBuilder::Environment::Environment(
184 790628 : const BytecodeGraphBuilder::Environment* other)
185 : : builder_(other->builder_),
186 : register_count_(other->register_count_),
187 : parameter_count_(other->parameter_count_),
188 : context_(other->context_),
189 : control_dependency_(other->control_dependency_),
190 : effect_dependency_(other->effect_dependency_),
191 : values_(other->zone()),
192 : parameters_state_values_(other->parameters_state_values_),
193 : register_base_(other->register_base_),
194 1581256 : accumulator_base_(other->accumulator_base_) {
195 : values_ = other->values_;
196 790626 : }
197 :
198 :
199 0 : int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
200 9803742 : interpreter::Register the_register) const {
201 9803742 : if (the_register.is_parameter()) {
202 945313 : return the_register.ToParameterIndex(parameter_count());
203 : } else {
204 8858429 : return the_register.index() + register_base();
205 : }
206 : }
207 :
208 6976793 : Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
209 13953586 : return values()->at(accumulator_base_);
210 : }
211 :
212 :
213 5690251 : Node* BytecodeGraphBuilder::Environment::LookupRegister(
214 129315 : interpreter::Register the_register) const {
215 5690251 : if (the_register.is_current_context()) {
216 32157 : return Context();
217 5658094 : } else if (the_register.is_function_closure()) {
218 97158 : return builder()->GetFunctionClosure();
219 : } else {
220 : int values_index = RegisterToValuesIndex(the_register);
221 11121872 : return values()->at(values_index);
222 : }
223 : }
224 :
225 7845854 : void BytecodeGraphBuilder::Environment::BindAccumulator(
226 2917315 : Node* node, FrameStateAttachmentMode mode) {
227 7845854 : if (mode == FrameStateAttachmentMode::kAttachFrameState) {
228 2917315 : builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0));
229 : }
230 15691696 : values()->at(accumulator_base_) = node;
231 7845848 : }
232 :
233 4220226 : void BytecodeGraphBuilder::Environment::BindRegister(
234 : interpreter::Register the_register, Node* node,
235 49000 : FrameStateAttachmentMode mode) {
236 : int values_index = RegisterToValuesIndex(the_register);
237 4220225 : if (mode == FrameStateAttachmentMode::kAttachFrameState) {
238 : builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
239 98000 : accumulator_base_ - values_index));
240 : }
241 8440450 : values()->at(values_index) = node;
242 4220225 : }
243 :
244 1888 : void BytecodeGraphBuilder::Environment::BindRegistersToProjections(
245 7183 : interpreter::Register first_reg, Node* node,
246 10959 : FrameStateAttachmentMode mode) {
247 : int values_index = RegisterToValuesIndex(first_reg);
248 1888 : if (mode == FrameStateAttachmentMode::kAttachFrameState) {
249 : builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
250 738 : accumulator_base_ - values_index));
251 : }
252 19661 : for (int i = 0; i < node->op()->ValueOutputCount(); i++) {
253 5295 : values()->at(values_index + i) =
254 15885 : builder()->NewNode(common()->Projection(i), node);
255 : }
256 1888 : }
257 :
258 0 : void BytecodeGraphBuilder::Environment::RecordAfterState(
259 1152907 : Node* node, FrameStateAttachmentMode mode) {
260 0 : if (mode == FrameStateAttachmentMode::kAttachFrameState) {
261 1152907 : builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore());
262 : }
263 0 : }
264 :
265 790628 : BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::Environment::Copy() {
266 790628 : return new (zone()) Environment(this);
267 : }
268 :
269 484602 : void BytecodeGraphBuilder::Environment::Merge(
270 969204 : BytecodeGraphBuilder::Environment* other,
271 28483010 : const BytecodeLivenessState* liveness) {
272 : // Create a merge of the control dependencies of both environments and update
273 : // the current environment's control dependency accordingly.
274 : Node* control = builder()->MergeControl(GetControlDependency(),
275 484602 : other->GetControlDependency());
276 : UpdateControlDependency(control);
277 :
278 : // Create a merge of the effect dependencies of both environments and update
279 : // the current environment's effect dependency accordingly.
280 : Node* effect = builder()->MergeEffect(GetEffectDependency(),
281 484602 : other->GetEffectDependency(), control);
282 : UpdateEffectDependency(effect);
283 :
284 : // Introduce Phi nodes for values that are live and have differing inputs at
285 : // the merge point, potentially extending an existing Phi node if possible.
286 969204 : context_ = builder()->MergeValue(context_, other->context_, control);
287 3350562 : for (int i = 0; i < parameter_count(); i++) {
288 14638810 : values_[i] = builder()->MergeValue(values_[i], other->values_[i], control);
289 : }
290 15624227 : for (int i = 0; i < register_count(); i++) {
291 7569813 : int index = register_base() + i;
292 15086133 : if (liveness == nullptr || liveness->RegisterIsLive(i)) {
293 : DCHECK_NE(values_[index], builder()->jsgraph()->OptimizedOutConstant());
294 : DCHECK_NE(other->values_[index],
295 : builder()->jsgraph()->OptimizedOutConstant());
296 :
297 1571376 : values_[index] =
298 3142752 : builder()->MergeValue(values_[index], other->values_[index], control);
299 :
300 : } else {
301 11996874 : values_[index] = builder()->jsgraph()->OptimizedOutConstant();
302 : }
303 : }
304 :
305 964318 : if (liveness == nullptr || liveness->AccumulatorIsLive()) {
306 : DCHECK_NE(values_[accumulator_base()],
307 : builder()->jsgraph()->OptimizedOutConstant());
308 : DCHECK_NE(other->values_[accumulator_base()],
309 : builder()->jsgraph()->OptimizedOutConstant());
310 :
311 250307 : values_[accumulator_base()] =
312 : builder()->MergeValue(values_[accumulator_base()],
313 500614 : other->values_[accumulator_base()], control);
314 : } else {
315 468590 : values_[accumulator_base()] = builder()->jsgraph()->OptimizedOutConstant();
316 : }
317 484602 : }
318 :
319 44453 : void BytecodeGraphBuilder::Environment::PrepareForLoop(
320 : const BytecodeLoopAssignments& assignments,
321 1075814 : const BytecodeLivenessState* liveness) {
322 : // Create a control node for the loop header.
323 44453 : Node* control = builder()->NewLoop();
324 :
325 : // Create a Phi for external effects.
326 44453 : Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control);
327 : UpdateEffectDependency(effect);
328 :
329 : // Create Phis for any values that are live on entry to the loop and may be
330 : // updated by the end of the loop.
331 88906 : context_ = builder()->NewPhi(1, context_, control);
332 277094 : for (int i = 0; i < parameter_count(); i++) {
333 94094 : if (assignments.ContainsParameter(i)) {
334 86478 : values_[i] = builder()->NewPhi(1, values_[i], control);
335 : }
336 : }
337 979803 : for (int i = 0; i < register_count(); i++) {
338 935350 : if (assignments.ContainsLocal(i) &&
339 219053 : (liveness == nullptr || liveness->RegisterIsLive(i))) {
340 77757 : int index = register_base() + i;
341 233271 : values_[index] = builder()->NewPhi(1, values_[index], control);
342 : }
343 : }
344 : // The accumulator should not be live on entry.
345 : DCHECK_IMPLIES(liveness != nullptr, !liveness->AccumulatorIsLive());
346 :
347 : // Connect to the loop end.
348 : Node* terminate = builder()->graph()->NewNode(
349 177812 : builder()->common()->Terminate(), effect, control);
350 44453 : builder()->exit_controls_.push_back(terminate);
351 44453 : }
352 :
353 197502 : void BytecodeGraphBuilder::Environment::FillWithOsrValues() {
354 5809 : Node* start = graph()->start();
355 :
356 : // Create OSR values for each environment value.
357 : SetContext(graph()->NewNode(
358 5809 : common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), start));
359 11618 : int size = static_cast<int>(values()->size());
360 52280 : for (int i = 0; i < size; i++) {
361 : int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly.
362 46471 : if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount;
363 46471 : if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex;
364 139413 : values()->at(i) = graph()->NewNode(common()->OsrValue(idx), start);
365 : }
366 5809 : }
367 :
368 6255428 : bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
369 : Node** state_values, Node** values, int count) {
370 6255428 : if (*state_values == nullptr) {
371 : return true;
372 : }
373 : Node::Inputs inputs = (*state_values)->inputs();
374 5899054 : if (inputs.count() != count) return true;
375 12871198 : for (int i = 0; i < count; i++) {
376 12882552 : if (inputs[i] != values[i]) {
377 : return true;
378 : }
379 : }
380 : return false;
381 : }
382 :
383 125815 : void BytecodeGraphBuilder::Environment::PrepareForLoopExit(
384 : Node* loop, const BytecodeLoopAssignments& assignments,
385 4495645 : const BytecodeLivenessState* liveness) {
386 : DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);
387 :
388 : Node* control = GetControlDependency();
389 :
390 : // Create the loop exit node.
391 125815 : Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop);
392 : UpdateControlDependency(loop_exit);
393 :
394 : // Rename the effect.
395 : Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
396 125815 : GetEffectDependency(), loop_exit);
397 : UpdateEffectDependency(effect_rename);
398 :
399 : // TODO(jarin) We should also rename context here. However, unconditional
400 : // renaming confuses global object and native context specialization.
401 : // We should only rename if the context is assigned in the loop.
402 :
403 : // Rename the environment values if they were assigned in the loop and are
404 : // live after exiting the loop.
405 760992 : for (int i = 0; i < parameter_count(); i++) {
406 254681 : if (assignments.ContainsParameter(i)) {
407 : Node* rename =
408 501768 : graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit);
409 2715 : values_[i] = rename;
410 : }
411 : }
412 5123471 : for (int i = 0; i < register_count(); i++) {
413 4997656 : if (assignments.ContainsLocal(i) &&
414 1180458 : (liveness == nullptr || liveness->RegisterIsLive(i))) {
415 : Node* rename = graph()->NewNode(common()->LoopExitValue(),
416 501699 : values_[register_base() + i], loop_exit);
417 334466 : values_[register_base() + i] = rename;
418 : }
419 : }
420 250925 : if (liveness == nullptr || liveness->AccumulatorIsLive()) {
421 : Node* rename = graph()->NewNode(common()->LoopExitValue(),
422 234663 : values_[accumulator_base()], loop_exit);
423 156442 : values_[accumulator_base()] = rename;
424 : }
425 125815 : }
426 :
427 6255428 : void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
428 : Node** values,
429 735457 : int count) {
430 6255428 : if (StateValuesRequireUpdate(state_values, values, count)) {
431 367728 : const Operator* op = common()->StateValues(count, SparseInputMask::Dense());
432 367729 : (*state_values) = graph()->NewNode(op, count, values);
433 : }
434 6255430 : }
435 :
436 0 : Node* BytecodeGraphBuilder::Environment::GetStateValuesFromCache(
437 : Node** values, int count, const BitVector* liveness, int liveness_offset) {
438 : return builder_->state_values_cache_.GetNodeForValues(
439 7451202 : values, static_cast<size_t>(count), liveness, liveness_offset);
440 : }
441 :
442 6853315 : Node* BytecodeGraphBuilder::Environment::Checkpoint(
443 : BailoutId bailout_id, OutputFrameStateCombine combine,
444 47973190 : const BytecodeLivenessState* liveness) {
445 6853315 : if (parameter_count() == register_count()) {
446 : // Re-use the state-value cache if the number of local registers happens
447 : // to match the parameter count.
448 : parameters_state_values_ = GetStateValuesFromCache(
449 597886 : &values()->at(0), parameter_count(), nullptr, 0);
450 : } else {
451 : UpdateStateValues(¶meters_state_values_, &values()->at(0),
452 6255429 : parameter_count());
453 : }
454 :
455 : Node* registers_state_values =
456 6853316 : GetStateValuesFromCache(&values()->at(register_base()), register_count(),
457 6853316 : liveness ? &liveness->bit_vector() : nullptr, 0);
458 :
459 13639555 : bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive();
460 : Node* accumulator_state_value =
461 3302953 : accumulator_is_live && combine != OutputFrameStateCombine::PokeAt(0)
462 1259798 : ? values()->at(accumulator_base())
463 13706620 : : builder()->jsgraph()->OptimizedOutConstant();
464 :
465 : const Operator* op = common()->FrameState(
466 13706628 : bailout_id, combine, builder()->frame_state_function_info());
467 : Node* result = graph()->NewNode(
468 : op, parameters_state_values_, registers_state_values,
469 : accumulator_state_value, Context(), builder()->GetFunctionClosure(),
470 20559937 : builder()->graph()->start());
471 :
472 6853314 : return result;
473 : }
474 :
475 504909 : BytecodeGraphBuilder::BytecodeGraphBuilder(
476 : Zone* local_zone, Handle<SharedFunctionInfo> shared_info,
477 : Handle<FeedbackVector> feedback_vector, BailoutId osr_offset,
478 : JSGraph* jsgraph, CallFrequency invocation_frequency,
479 : SourcePositionTable* source_positions, Handle<Context> native_context,
480 504909 : int inlining_id, JSTypeHintLowering::Flags flags, bool stack_check)
481 : : local_zone_(local_zone),
482 : jsgraph_(jsgraph),
483 : invocation_frequency_(invocation_frequency),
484 : bytecode_array_(handle(shared_info->bytecode_array())),
485 : exception_handler_table_(
486 : handle(HandlerTable::cast(bytecode_array()->handler_table()))),
487 : feedback_vector_(feedback_vector),
488 : type_hint_lowering_(jsgraph, feedback_vector, flags),
489 : frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
490 : FrameStateType::kInterpretedFunction,
491 : bytecode_array()->parameter_count(),
492 504909 : bytecode_array()->register_count(), shared_info)),
493 : bytecode_iterator_(nullptr),
494 : bytecode_analysis_(nullptr),
495 : environment_(nullptr),
496 : osr_offset_(osr_offset),
497 : currently_peeled_loop_offset_(-1),
498 : stack_check_(stack_check),
499 : merge_environments_(local_zone),
500 : exception_handlers_(local_zone),
501 : current_exception_handler_(0),
502 : input_buffer_size_(0),
503 : input_buffer_(nullptr),
504 : needs_eager_checkpoint_(true),
505 : exit_controls_(local_zone),
506 : state_values_cache_(jsgraph),
507 : source_positions_(source_positions),
508 : start_position_(shared_info->start_position(), inlining_id),
509 3534368 : native_context_(native_context) {}
510 :
511 8008383 : Node* BytecodeGraphBuilder::GetFunctionClosure() {
512 7002691 : if (!function_closure_.is_set()) {
513 : int index = Linkage::kJSCallClosureParamIndex;
514 502845 : const Operator* op = common()->Parameter(index, "%closure");
515 502847 : Node* node = NewNode(op, graph()->start());
516 : function_closure_.set(node);
517 : }
518 7002691 : return function_closure_.get();
519 : }
520 :
521 18866 : Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
522 : const Operator* op =
523 9433 : javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
524 : Node* native_context = NewNode(op);
525 18866 : Node* result = NewNode(javascript()->LoadContext(0, index, true));
526 9433 : NodeProperties::ReplaceContextInput(result, native_context);
527 9433 : return result;
528 : }
529 :
530 0 : VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
531 0 : return VectorSlotPair(feedback_vector(), feedback_vector()->ToSlot(slot_id));
532 : }
533 :
534 4039277 : void BytecodeGraphBuilder::CreateGraph() {
535 504909 : SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
536 :
537 : // Set up the basic structure of the graph. Outputs for {Start} are the formal
538 : // parameters (including the receiver) plus new target, number of arguments,
539 : // context and closure.
540 504909 : int actual_parameter_count = bytecode_array()->parameter_count() + 4;
541 504909 : graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
542 :
543 : Environment env(this, bytecode_array()->register_count(),
544 : bytecode_array()->parameter_count(),
545 : bytecode_array()->incoming_new_target_or_generator_register(),
546 1009820 : graph()->start());
547 : set_environment(&env);
548 :
549 504910 : VisitBytecodes();
550 :
551 : // Finish the basic structure of the graph.
552 : DCHECK_NE(0u, exit_controls_.size());
553 1009820 : int const input_count = static_cast<int>(exit_controls_.size());
554 : Node** const inputs = &exit_controls_.front();
555 1514729 : Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
556 : graph()->SetEnd(end);
557 504910 : }
558 :
559 17125502 : void BytecodeGraphBuilder::PrepareEagerCheckpoint() {
560 3955437 : if (needs_eager_checkpoint()) {
561 : // Create an explicit checkpoint node for before the operation. This only
562 : // needs to happen if we aren't effect-dominated by a {Checkpoint} already.
563 : mark_as_needing_eager_checkpoint(false);
564 3292517 : Node* node = NewNode(common()->Checkpoint());
565 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
566 : DCHECK_EQ(IrOpcode::kDead,
567 : NodeProperties::GetFrameStateInput(node)->opcode());
568 3292516 : BailoutId bailout_id(bytecode_iterator().current_offset());
569 :
570 : const BytecodeLivenessState* liveness_before =
571 : bytecode_analysis()->GetInLivenessFor(
572 3292516 : bytecode_iterator().current_offset());
573 :
574 : Node* frame_state_before = environment()->Checkpoint(
575 3292516 : bailout_id, OutputFrameStateCombine::Ignore(), liveness_before);
576 3292515 : NodeProperties::ReplaceFrameStateInput(node, frame_state_before);
577 : #ifdef DEBUG
578 : } else {
579 : // In case we skipped checkpoint creation above, we must be able to find an
580 : // existing checkpoint that effect-dominates the nodes about to be created.
581 : // Starting a search from the current effect-dependency has to succeed.
582 : Node* effect = environment()->GetEffectDependency();
583 : while (effect->opcode() != IrOpcode::kCheckpoint) {
584 : DCHECK(effect->op()->HasProperty(Operator::kNoWrite));
585 : DCHECK_EQ(1, effect->op()->EffectInputCount());
586 : effect = NodeProperties::GetEffectInput(effect);
587 : }
588 : }
589 : #else
590 : }
591 : #endif // DEBUG
592 3955433 : }
593 :
594 4119590 : void BytecodeGraphBuilder::PrepareFrameState(Node* node,
595 10682409 : OutputFrameStateCombine combine) {
596 4119590 : if (OperatorProperties::HasFrameStateInput(node->op())) {
597 : // Add the frame state for after the operation. The node in question has
598 : // already been created and had a {Dead} frame state input up until now.
599 : DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
600 : DCHECK_EQ(IrOpcode::kDead,
601 : NodeProperties::GetFrameStateInput(node)->opcode());
602 3560803 : BailoutId bailout_id(bytecode_iterator().current_offset());
603 :
604 : const BytecodeLivenessState* liveness_after =
605 : bytecode_analysis()->GetOutLivenessFor(
606 3560803 : bytecode_iterator().current_offset());
607 :
608 : Node* frame_state_after =
609 3560803 : environment()->Checkpoint(bailout_id, combine, liveness_after);
610 3560800 : NodeProperties::ReplaceFrameStateInput(node, frame_state_after);
611 : }
612 4119587 : }
613 :
614 : // Stores the state of the SourcePosition iterator, and the index to the
615 : // current exception handlers stack. We need, during the OSR graph generation,
616 : // to backup the states of these iterators at the LoopHeader offset of each
617 : // outer loop which contains the OSR loop. The iterators are then restored when
618 : // peeling the loops, so that both exception handling and synchronisation with
619 : // the source position can be achieved.
620 : class BytecodeGraphBuilder::OsrIteratorState {
621 : public:
622 : OsrIteratorState(interpreter::BytecodeArrayIterator* iterator,
623 : SourcePositionTableIterator* source_position_iterator,
624 5809 : BytecodeGraphBuilder* graph_builder)
625 : : iterator_(iterator),
626 : source_position_iterator_(source_position_iterator),
627 : graph_builder_(graph_builder),
628 11618 : saved_states_(graph_builder->local_zone()) {}
629 :
630 5809 : void ProcessOsrPrelude() {
631 12490 : ZoneVector<int> outer_loop_offsets(graph_builder_->local_zone());
632 :
633 5809 : const BytecodeAnalysis& bytecode_analysis =
634 : *(graph_builder_->bytecode_analysis());
635 : int osr_offset = bytecode_analysis.osr_entry_point();
636 :
637 : // We find here the outermost loop which contains the OSR loop.
638 5809 : int outermost_loop_offset = osr_offset;
639 12490 : while ((outermost_loop_offset =
640 6681 : bytecode_analysis.GetLoopInfoFor(outermost_loop_offset)
641 13362 : .parent_offset()) != -1) {
642 872 : outer_loop_offsets.push_back(outermost_loop_offset);
643 : }
644 : outermost_loop_offset =
645 5809 : outer_loop_offsets.empty() ? osr_offset : outer_loop_offsets.back();
646 :
647 : // We will not processs any bytecode before the outermost_loop_offset, but
648 : // the source_position_iterator needs to be advanced step by step through
649 : // the bytecode.
650 209953 : for (; iterator_->current_offset() != outermost_loop_offset;
651 96263 : iterator_->Advance()) {
652 : graph_builder_->UpdateSourcePosition(source_position_iterator_,
653 215954 : iterator_->current_offset());
654 : }
655 :
656 : // We save some iterators states at the offsets of the loop headers of the
657 : // outer loops (the ones containing the OSR loop). They will be used for
658 : // jumping back in the bytecode.
659 6681 : for (ZoneVector<int>::const_reverse_iterator it =
660 : outer_loop_offsets.crbegin();
661 : it != outer_loop_offsets.crend(); ++it) {
662 872 : int next_loop_offset = *it;
663 9042 : for (; iterator_->current_offset() != next_loop_offset;
664 3213 : iterator_->Advance()) {
665 : graph_builder_->UpdateSourcePosition(source_position_iterator_,
666 3213 : iterator_->current_offset());
667 : }
668 : graph_builder_->ExitThenEnterExceptionHandlers(
669 872 : iterator_->current_offset());
670 : saved_states_.push(
671 : IteratorsStates(graph_builder_->current_exception_handler(),
672 2616 : source_position_iterator_->GetState()));
673 : }
674 :
675 : // Finishing by advancing to the OSR entry
676 21259 : for (; iterator_->current_offset() != osr_offset; iterator_->Advance()) {
677 : graph_builder_->UpdateSourcePosition(source_position_iterator_,
678 7725 : iterator_->current_offset());
679 : }
680 :
681 : // Enters all remaining exception handler which end before the OSR loop
682 : // so that on next call of VisitSingleBytecode they will get popped from
683 : // the exception handlers stack.
684 5809 : graph_builder_->ExitThenEnterExceptionHandlers(osr_offset);
685 : graph_builder_->set_currently_peeled_loop_offset(
686 5809 : bytecode_analysis.GetLoopInfoFor(osr_offset).parent_offset());
687 5809 : }
688 :
689 872 : void RestoreState(int target_offset, int new_parent_offset) {
690 872 : iterator_->SetOffset(target_offset);
691 : // In case of a return, we must not build loop exits for
692 : // not-yet-built outer loops.
693 872 : graph_builder_->set_currently_peeled_loop_offset(new_parent_offset);
694 872 : IteratorsStates saved_state = saved_states_.top();
695 872 : source_position_iterator_->RestoreState(saved_state.source_iterator_state_);
696 : graph_builder_->set_current_exception_handler(
697 872 : saved_state.exception_handler_index_);
698 : saved_states_.pop();
699 872 : }
700 :
701 : private:
702 : struct IteratorsStates {
703 : int exception_handler_index_;
704 : SourcePositionTableIterator::IndexAndPosition source_iterator_state_;
705 :
706 : IteratorsStates(
707 : int exception_handler_index,
708 : SourcePositionTableIterator::IndexAndPosition source_iterator_state)
709 : : exception_handler_index_(exception_handler_index),
710 872 : source_iterator_state_(source_iterator_state) {}
711 : };
712 :
713 : interpreter::BytecodeArrayIterator* iterator_;
714 : SourcePositionTableIterator* source_position_iterator_;
715 : BytecodeGraphBuilder* graph_builder_;
716 : ZoneStack<IteratorsStates> saved_states_;
717 : };
718 :
719 872 : void BytecodeGraphBuilder::RemoveMergeEnvironmentsBeforeOffset(
720 : int limit_offset) {
721 872 : if (!merge_environments_.empty()) {
722 : ZoneMap<int, Environment*>::iterator it = merge_environments_.begin();
723 : ZoneMap<int, Environment*>::iterator stop_it = merge_environments_.end();
724 3829 : while (it != stop_it && it->first <= limit_offset) {
725 : it = merge_environments_.erase(it);
726 : }
727 : }
728 872 : }
729 :
730 : // We will iterate through the OSR loop, then its parent, and so on
731 : // until we have reached the outmost loop containing the OSR loop. We do
732 : // not generate nodes for anything before the outermost loop.
733 5809 : void BytecodeGraphBuilder::AdvanceToOsrEntryAndPeelLoops(
734 : interpreter::BytecodeArrayIterator* iterator,
735 11618 : SourcePositionTableIterator* source_position_iterator) {
736 5809 : const BytecodeAnalysis& analysis = *(bytecode_analysis());
737 : int osr_offset = analysis.osr_entry_point();
738 : OsrIteratorState iterator_states(iterator, source_position_iterator, this);
739 :
740 5809 : iterator_states.ProcessOsrPrelude();
741 : DCHECK_EQ(iterator->current_offset(), osr_offset);
742 :
743 5809 : environment()->FillWithOsrValues();
744 :
745 : // Suppose we have n nested loops, loop_0 being the outermost one, and
746 : // loop_n being the OSR loop. We start iterating the bytecode at the header
747 : // of loop_n (the OSR loop), and then we peel the part of the the body of
748 : // loop_{n-1} following the end of loop_n. We then rewind the iterator to
749 : // the header of loop_{n-1}, and so on until we have partly peeled loop 0.
750 : // The full loop_0 body will be generating with the rest of the function,
751 : // outside the OSR generation.
752 :
753 : // To do so, if we are visiting a loop, we continue to visit what's left
754 : // of its parent, and then when reaching the parent's JumpLoop, we do not
755 : // create any jump for that but rewind the bytecode iterator to visit the
756 : // parent loop entirely, and so on.
757 :
758 : int current_parent_offset =
759 5809 : analysis.GetLoopInfoFor(osr_offset).parent_offset();
760 12490 : while (current_parent_offset != -1) {
761 : LoopInfo current_parent_loop =
762 872 : analysis.GetLoopInfoFor(current_parent_offset);
763 : // We iterate until the back edge of the parent loop, which we detect by
764 : // the offset that the JumpLoop targets.
765 23578 : for (; !iterator->done(); iterator->Advance()) {
766 28430 : if (iterator->current_bytecode() == interpreter::Bytecode::kJumpLoop &&
767 2236 : iterator->GetJumpTargetOffset() == current_parent_offset) {
768 : // Reached the end of the current parent loop.
769 : break;
770 : }
771 22706 : VisitSingleBytecode(source_position_iterator);
772 : }
773 : DCHECK(!iterator->done()); // Should have found the loop's jump target.
774 :
775 : // We also need to take care of the merge environments and exceptions
776 : // handlers here because the omitted JumpLoop bytecode can still be the
777 : // target of jumps or the first bytecode after a try block.
778 872 : ExitThenEnterExceptionHandlers(iterator->current_offset());
779 872 : SwitchToMergeEnvironment(iterator->current_offset());
780 :
781 : // This jump is the jump of our parent loop, which is not yet created.
782 : // So we do not build the jump nodes, but restore the bytecode and the
783 : // SourcePosition iterators to the values they had when we were visiting
784 : // the offset pointed at by the JumpLoop we've just reached.
785 : // We have already built nodes for inner loops, but now we will
786 : // iterate again over them and build new nodes corresponding to the same
787 : // bytecode offsets. Any jump or reference to this inner loops must now
788 : // point to the new nodes we will build, hence we clear the relevant part
789 : // of the environment.
790 : // Completely clearing the environment is not possible because merge
791 : // environments for forward jumps out of the loop need to be preserved
792 : // (e.g. a return or a labeled break in the middle of a loop).
793 872 : RemoveMergeEnvironmentsBeforeOffset(iterator->current_offset());
794 : iterator_states.RestoreState(current_parent_offset,
795 872 : current_parent_loop.parent_offset());
796 : current_parent_offset = current_parent_loop.parent_offset();
797 : }
798 5809 : }
799 :
800 16070096 : void BytecodeGraphBuilder::VisitSingleBytecode(
801 46138005 : SourcePositionTableIterator* source_position_iterator) {
802 : const interpreter::BytecodeArrayIterator& iterator = bytecode_iterator();
803 16070096 : int current_offset = iterator.current_offset();
804 16070096 : UpdateSourcePosition(source_position_iterator, current_offset);
805 16070103 : ExitThenEnterExceptionHandlers(current_offset);
806 : DCHECK_GE(exception_handlers_.empty() ? current_offset
807 : : exception_handlers_.top().end_offset_,
808 : current_offset);
809 16070100 : SwitchToMergeEnvironment(current_offset);
810 :
811 16070102 : if (environment() != nullptr) {
812 13997803 : BuildLoopHeaderEnvironment(current_offset);
813 :
814 : // Skip the first stack check if stack_check is false
815 14070349 : if (!stack_check() &&
816 72542 : iterator.current_bytecode() == interpreter::Bytecode::kStackCheck) {
817 : set_stack_check(true);
818 16070110 : return;
819 : }
820 :
821 13936279 : switch (iterator.current_bytecode()) {
822 : #define BYTECODE_CASE(name, ...) \
823 : case interpreter::Bytecode::k##name: \
824 : Visit##name(); \
825 : break;
826 204154 : BYTECODE_LIST(BYTECODE_CASE)
827 : #undef BYTECODE_CODE
828 : }
829 : }
830 : }
831 :
832 1009814 : void BytecodeGraphBuilder::VisitBytecodes() {
833 504907 : BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone(),
834 1009814 : FLAG_analyze_environment_liveness);
835 504909 : bytecode_analysis.Analyze(osr_offset_);
836 : set_bytecode_analysis(&bytecode_analysis);
837 :
838 504908 : interpreter::BytecodeArrayIterator iterator(bytecode_array());
839 : set_bytecode_iterator(&iterator);
840 : SourcePositionTableIterator source_position_iterator(
841 1009819 : handle(bytecode_array()->SourcePositionTable()));
842 :
843 504909 : if (FLAG_trace_environment_liveness) {
844 0 : OFStream of(stdout);
845 :
846 0 : bytecode_analysis.PrintLivenessTo(of);
847 : }
848 :
849 504909 : if (bytecode_analysis.HasOsrEntryPoint()) {
850 : // We peel the OSR loop and any outer loop containing it except that we
851 : // leave the nodes corresponding to the whole outermost loop (including
852 : // the last copies of the loops it contains) to be generated by the normal
853 : // bytecode iteration below.
854 5809 : AdvanceToOsrEntryAndPeelLoops(&iterator, &source_position_iterator);
855 : }
856 :
857 16047388 : for (; !iterator.done(); iterator.Advance()) {
858 16047391 : VisitSingleBytecode(&source_position_iterator);
859 : }
860 : set_bytecode_analysis(nullptr);
861 : set_bytecode_iterator(nullptr);
862 504910 : DCHECK(exception_handlers_.empty());
863 504910 : }
864 :
865 548100 : void BytecodeGraphBuilder::VisitLdaZero() {
866 274050 : Node* node = jsgraph()->ZeroConstant();
867 274050 : environment()->BindAccumulator(node);
868 274050 : }
869 :
870 2514734 : void BytecodeGraphBuilder::VisitLdaSmi() {
871 1676489 : Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
872 838245 : environment()->BindAccumulator(node);
873 838244 : }
874 :
875 1704513 : void BytecodeGraphBuilder::VisitLdaConstant() {
876 : Node* node =
877 1136342 : jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
878 568171 : environment()->BindAccumulator(node);
879 568171 : }
880 :
881 312794 : void BytecodeGraphBuilder::VisitLdaUndefined() {
882 156397 : Node* node = jsgraph()->UndefinedConstant();
883 156397 : environment()->BindAccumulator(node);
884 156397 : }
885 :
886 12280 : void BytecodeGraphBuilder::VisitLdaNull() {
887 6140 : Node* node = jsgraph()->NullConstant();
888 6140 : environment()->BindAccumulator(node);
889 6140 : }
890 :
891 188906 : void BytecodeGraphBuilder::VisitLdaTheHole() {
892 94453 : Node* node = jsgraph()->TheHoleConstant();
893 94453 : environment()->BindAccumulator(node);
894 94453 : }
895 :
896 86460 : void BytecodeGraphBuilder::VisitLdaTrue() {
897 43230 : Node* node = jsgraph()->TrueConstant();
898 43230 : environment()->BindAccumulator(node);
899 43230 : }
900 :
901 109066 : void BytecodeGraphBuilder::VisitLdaFalse() {
902 54533 : Node* node = jsgraph()->FalseConstant();
903 54533 : environment()->BindAccumulator(node);
904 54533 : }
905 :
906 2284674 : void BytecodeGraphBuilder::VisitLdar() {
907 : Node* value =
908 1523116 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
909 761558 : environment()->BindAccumulator(value);
910 761558 : }
911 :
912 11149046 : void BytecodeGraphBuilder::VisitStar() {
913 3716348 : Node* value = environment()->LookupAccumulator();
914 7432698 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value);
915 3716350 : }
916 :
917 1440350 : void BytecodeGraphBuilder::VisitMov() {
918 : Node* value =
919 720175 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
920 720175 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value);
921 360087 : }
922 :
923 602021 : Node* BytecodeGraphBuilder::BuildLoadGlobal(Handle<Name> name,
924 : uint32_t feedback_slot_index,
925 602021 : TypeofMode typeof_mode) {
926 602021 : VectorSlotPair feedback = CreateVectorSlotPair(feedback_slot_index);
927 : DCHECK(IsLoadGlobalICKind(feedback_vector()->GetKind(feedback.slot())));
928 602021 : const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
929 602021 : return NewNode(op);
930 : }
931 :
932 2151220 : void BytecodeGraphBuilder::VisitLdaGlobal() {
933 537805 : PrepareEagerCheckpoint();
934 : Handle<Name> name =
935 537805 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
936 537805 : uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
937 : Node* node =
938 537805 : BuildLoadGlobal(name, feedback_slot_index, TypeofMode::NOT_INSIDE_TYPEOF);
939 537805 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
940 537805 : }
941 :
942 1116 : void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() {
943 279 : PrepareEagerCheckpoint();
944 : Handle<Name> name =
945 279 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
946 279 : uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
947 : Node* node =
948 279 : BuildLoadGlobal(name, feedback_slot_index, TypeofMode::INSIDE_TYPEOF);
949 279 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
950 279 : }
951 :
952 1109826 : void BytecodeGraphBuilder::BuildStoreGlobal(LanguageMode language_mode) {
953 184971 : PrepareEagerCheckpoint();
954 : Handle<Name> name =
955 184971 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
956 : VectorSlotPair feedback =
957 184971 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
958 184971 : Node* value = environment()->LookupAccumulator();
959 :
960 184971 : const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback);
961 : Node* node = NewNode(op, value);
962 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
963 184971 : }
964 :
965 0 : void BytecodeGraphBuilder::VisitStaGlobalSloppy() {
966 167549 : BuildStoreGlobal(LanguageMode::kSloppy);
967 0 : }
968 :
969 0 : void BytecodeGraphBuilder::VisitStaGlobalStrict() {
970 17422 : BuildStoreGlobal(LanguageMode::kStrict);
971 0 : }
972 :
973 607343 : void BytecodeGraphBuilder::VisitStaDataPropertyInLiteral() {
974 55213 : PrepareEagerCheckpoint();
975 :
976 : Node* object =
977 110426 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
978 : Node* name =
979 110426 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
980 55213 : Node* value = environment()->LookupAccumulator();
981 55213 : int flags = bytecode_iterator().GetFlagOperand(2);
982 : VectorSlotPair feedback =
983 55213 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(3));
984 :
985 55213 : const Operator* op = javascript()->StoreDataPropertyInLiteral(feedback);
986 55213 : Node* node = NewNode(op, object, name, value, jsgraph()->Constant(flags));
987 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
988 55213 : }
989 :
990 287 : void BytecodeGraphBuilder::VisitCollectTypeProfile() {
991 41 : PrepareEagerCheckpoint();
992 :
993 : Node* position =
994 82 : jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
995 41 : Node* value = environment()->LookupAccumulator();
996 41 : Node* vector = jsgraph()->Constant(feedback_vector());
997 :
998 41 : const Operator* op = javascript()->CallRuntime(Runtime::kCollectTypeProfile);
999 :
1000 : Node* node = NewNode(op, position, value, vector);
1001 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
1002 41 : }
1003 :
1004 58536 : void BytecodeGraphBuilder::VisitLdaContextSlot() {
1005 : const Operator* op = javascript()->LoadContext(
1006 9756 : bytecode_iterator().GetUnsignedImmediateOperand(2),
1007 29268 : bytecode_iterator().GetIndexOperand(1), false);
1008 : Node* node = NewNode(op);
1009 : Node* context =
1010 19512 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1011 9756 : NodeProperties::ReplaceContextInput(node, context);
1012 9756 : environment()->BindAccumulator(node);
1013 9756 : }
1014 :
1015 58662 : void BytecodeGraphBuilder::VisitLdaImmutableContextSlot() {
1016 : const Operator* op = javascript()->LoadContext(
1017 9777 : bytecode_iterator().GetUnsignedImmediateOperand(2),
1018 29331 : bytecode_iterator().GetIndexOperand(1), true);
1019 : Node* node = NewNode(op);
1020 : Node* context =
1021 19554 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1022 9777 : NodeProperties::ReplaceContextInput(node, context);
1023 9777 : environment()->BindAccumulator(node);
1024 9777 : }
1025 :
1026 520710 : void BytecodeGraphBuilder::VisitLdaCurrentContextSlot() {
1027 : const Operator* op = javascript()->LoadContext(
1028 347140 : 0, bytecode_iterator().GetIndexOperand(0), false);
1029 : Node* node = NewNode(op);
1030 173570 : environment()->BindAccumulator(node);
1031 173570 : }
1032 :
1033 935619 : void BytecodeGraphBuilder::VisitLdaImmutableCurrentContextSlot() {
1034 : const Operator* op = javascript()->LoadContext(
1035 623746 : 0, bytecode_iterator().GetIndexOperand(0), true);
1036 : Node* node = NewNode(op);
1037 311873 : environment()->BindAccumulator(node);
1038 311873 : }
1039 :
1040 8658 : void BytecodeGraphBuilder::VisitStaContextSlot() {
1041 : const Operator* op = javascript()->StoreContext(
1042 1443 : bytecode_iterator().GetUnsignedImmediateOperand(2),
1043 4329 : bytecode_iterator().GetIndexOperand(1));
1044 1443 : Node* value = environment()->LookupAccumulator();
1045 : Node* node = NewNode(op, value);
1046 : Node* context =
1047 2886 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1048 1443 : NodeProperties::ReplaceContextInput(node, context);
1049 1443 : }
1050 :
1051 1032048 : void BytecodeGraphBuilder::VisitStaCurrentContextSlot() {
1052 : const Operator* op =
1053 688032 : javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(0));
1054 344016 : Node* value = environment()->LookupAccumulator();
1055 : NewNode(op, value);
1056 344016 : }
1057 :
1058 7580 : void BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) {
1059 1516 : PrepareEagerCheckpoint();
1060 : Node* name =
1061 3032 : jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
1062 : const Operator* op =
1063 : javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
1064 : ? Runtime::kLoadLookupSlot
1065 3032 : : Runtime::kLoadLookupSlotInsideTypeof);
1066 : Node* value = NewNode(op, name);
1067 1516 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1068 1516 : }
1069 :
1070 0 : void BytecodeGraphBuilder::VisitLdaLookupSlot() {
1071 1503 : BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF);
1072 0 : }
1073 :
1074 0 : void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
1075 13 : BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF);
1076 0 : }
1077 :
1078 64893 : BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions(
1079 294868 : uint32_t depth) {
1080 : // Output environment where the context has an extension
1081 : Environment* slow_environment = nullptr;
1082 :
1083 : // We only need to check up to the last-but-one depth, because the an eval
1084 : // in the same scope as the variable itself has no way of shadowing it.
1085 135650 : for (uint32_t d = 0; d < depth; d++) {
1086 : Node* extension_slot =
1087 141514 : NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false));
1088 :
1089 : Node* check_no_extension =
1090 : NewNode(simplified()->ReferenceEqual(), extension_slot,
1091 141514 : jsgraph()->TheHoleConstant());
1092 :
1093 70757 : NewBranch(check_no_extension);
1094 :
1095 : {
1096 : SubEnvironment sub_environment(this);
1097 :
1098 70757 : NewIfFalse();
1099 : // If there is an extension, merge into the slow path.
1100 70757 : if (slow_environment == nullptr) {
1101 : slow_environment = environment();
1102 64837 : NewMerge();
1103 : } else {
1104 : slow_environment->Merge(environment(),
1105 : bytecode_analysis()->GetInLivenessFor(
1106 17760 : bytecode_iterator().current_offset()));
1107 : }
1108 : }
1109 :
1110 70757 : NewIfTrue();
1111 : // Do nothing on if there is no extension, eventually falling through to
1112 : // the fast path.
1113 : }
1114 :
1115 : // The depth can be zero, in which case no slow-path checks are built, and
1116 : // the slow path environment can be null.
1117 : DCHECK(depth == 0 || slow_environment != nullptr);
1118 :
1119 64893 : return slow_environment;
1120 : }
1121 :
1122 11432 : void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) {
1123 956 : uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
1124 :
1125 : // Check if any context in the depth has an extension.
1126 956 : Environment* slow_environment = CheckContextExtensions(depth);
1127 :
1128 : // Fast path, do a context load.
1129 : {
1130 956 : uint32_t slot_index = bytecode_iterator().GetIndexOperand(1);
1131 :
1132 1912 : const Operator* op = javascript()->LoadContext(depth, slot_index, false);
1133 956 : environment()->BindAccumulator(NewNode(op));
1134 : }
1135 :
1136 : // Only build the slow path if there were any slow-path checks.
1137 956 : if (slow_environment != nullptr) {
1138 : // Add a merge to the fast environment.
1139 951 : NewMerge();
1140 : Environment* fast_environment = environment();
1141 :
1142 : // Slow path, do a runtime load lookup.
1143 : set_environment(slow_environment);
1144 : {
1145 : Node* name = jsgraph()->Constant(
1146 1902 : bytecode_iterator().GetConstantForIndexOperand(0));
1147 :
1148 : const Operator* op =
1149 : javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
1150 : ? Runtime::kLoadLookupSlot
1151 1902 : : Runtime::kLoadLookupSlotInsideTypeof);
1152 : Node* value = NewNode(op, name);
1153 951 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1154 : }
1155 :
1156 : fast_environment->Merge(environment(),
1157 : bytecode_analysis()->GetOutLivenessFor(
1158 2853 : bytecode_iterator().current_offset()));
1159 : set_environment(fast_environment);
1160 : mark_as_needing_eager_checkpoint(true);
1161 : }
1162 956 : }
1163 :
1164 0 : void BytecodeGraphBuilder::VisitLdaLookupContextSlot() {
1165 953 : BuildLdaLookupContextSlot(TypeofMode::NOT_INSIDE_TYPEOF);
1166 0 : }
1167 :
1168 0 : void BytecodeGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() {
1169 3 : BuildLdaLookupContextSlot(TypeofMode::INSIDE_TYPEOF);
1170 0 : }
1171 :
1172 766836 : void BytecodeGraphBuilder::BuildLdaLookupGlobalSlot(TypeofMode typeof_mode) {
1173 63937 : uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2);
1174 :
1175 : // Check if any context in the depth has an extension.
1176 63937 : Environment* slow_environment = CheckContextExtensions(depth);
1177 :
1178 : // Fast path, do a global load.
1179 : {
1180 63937 : PrepareEagerCheckpoint();
1181 : Handle<Name> name =
1182 63937 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
1183 63937 : uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1);
1184 63937 : Node* node = BuildLoadGlobal(name, feedback_slot_index, typeof_mode);
1185 63937 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1186 : }
1187 :
1188 : // Only build the slow path if there were any slow-path checks.
1189 63937 : if (slow_environment != nullptr) {
1190 : // Add a merge to the fast environment.
1191 63886 : NewMerge();
1192 : Environment* fast_environment = environment();
1193 :
1194 : // Slow path, do a runtime load lookup.
1195 : set_environment(slow_environment);
1196 : {
1197 : Node* name = jsgraph()->Constant(
1198 127772 : bytecode_iterator().GetConstantForIndexOperand(0));
1199 :
1200 : const Operator* op =
1201 : javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
1202 : ? Runtime::kLoadLookupSlot
1203 127772 : : Runtime::kLoadLookupSlotInsideTypeof);
1204 : Node* value = NewNode(op, name);
1205 63886 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1206 : }
1207 :
1208 : fast_environment->Merge(environment(),
1209 : bytecode_analysis()->GetOutLivenessFor(
1210 191658 : bytecode_iterator().current_offset()));
1211 : set_environment(fast_environment);
1212 : mark_as_needing_eager_checkpoint(true);
1213 : }
1214 63937 : }
1215 :
1216 0 : void BytecodeGraphBuilder::VisitLdaLookupGlobalSlot() {
1217 63885 : BuildLdaLookupGlobalSlot(TypeofMode::NOT_INSIDE_TYPEOF);
1218 0 : }
1219 :
1220 0 : void BytecodeGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() {
1221 52 : BuildLdaLookupGlobalSlot(TypeofMode::INSIDE_TYPEOF);
1222 0 : }
1223 :
1224 44100 : void BytecodeGraphBuilder::VisitStaLookupSlot() {
1225 6300 : PrepareEagerCheckpoint();
1226 6300 : Node* value = environment()->LookupAccumulator();
1227 : Node* name =
1228 12600 : jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
1229 6300 : int bytecode_flags = bytecode_iterator().GetFlagOperand(1);
1230 : LanguageMode language_mode = static_cast<LanguageMode>(
1231 : interpreter::StoreLookupSlotFlags::LanguageModeBit::decode(
1232 : bytecode_flags));
1233 : LookupHoistingMode lookup_hoisting_mode = static_cast<LookupHoistingMode>(
1234 : interpreter::StoreLookupSlotFlags::LookupHoistingModeBit::decode(
1235 6300 : bytecode_flags));
1236 : DCHECK_IMPLIES(lookup_hoisting_mode == LookupHoistingMode::kLegacySloppy,
1237 : is_sloppy(language_mode));
1238 : const Operator* op = javascript()->CallRuntime(
1239 : is_strict(language_mode)
1240 : ? Runtime::kStoreLookupSlot_Strict
1241 : : lookup_hoisting_mode == LookupHoistingMode::kLegacySloppy
1242 : ? Runtime::kStoreLookupSlot_SloppyHoisting
1243 12600 : : Runtime::kStoreLookupSlot_Sloppy);
1244 : Node* store = NewNode(op, name, value);
1245 6300 : environment()->BindAccumulator(store, Environment::kAttachFrameState);
1246 6300 : }
1247 :
1248 4187241 : void BytecodeGraphBuilder::VisitLdaNamedProperty() {
1249 598904 : PrepareEagerCheckpoint();
1250 : Node* object =
1251 1197810 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1252 : Handle<Name> name =
1253 598905 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
1254 : VectorSlotPair feedback =
1255 598905 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1256 598905 : const Operator* op = javascript()->LoadNamed(name, feedback);
1257 :
1258 : JSTypeHintLowering::LoweringResult lowering =
1259 598905 : TryBuildSimplifiedLoadNamed(op, object, feedback.slot());
1260 603998 : if (lowering.IsExit()) return;
1261 :
1262 : Node* node = nullptr;
1263 593812 : if (lowering.IsSideEffectFree()) {
1264 0 : node = lowering.value();
1265 : } else {
1266 : DCHECK(!lowering.Changed());
1267 : node = NewNode(op, object);
1268 : }
1269 593812 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1270 : }
1271 :
1272 384637 : void BytecodeGraphBuilder::VisitLdaKeyedProperty() {
1273 55016 : PrepareEagerCheckpoint();
1274 55016 : Node* key = environment()->LookupAccumulator();
1275 : Node* object =
1276 110032 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1277 : VectorSlotPair feedback =
1278 55016 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
1279 55016 : const Operator* op = javascript()->LoadProperty(feedback);
1280 :
1281 : JSTypeHintLowering::LoweringResult lowering =
1282 55016 : TryBuildSimplifiedLoadKeyed(op, object, key, feedback.slot());
1283 55491 : if (lowering.IsExit()) return;
1284 :
1285 : Node* node = nullptr;
1286 54541 : if (lowering.IsSideEffectFree()) {
1287 0 : node = lowering.value();
1288 : } else {
1289 : DCHECK(!lowering.Changed());
1290 : node = NewNode(op, object, key);
1291 : }
1292 54541 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1293 : }
1294 :
1295 2485295 : void BytecodeGraphBuilder::BuildNamedStore(StoreMode store_mode) {
1296 310724 : PrepareEagerCheckpoint();
1297 310724 : Node* value = environment()->LookupAccumulator();
1298 : Node* object =
1299 621448 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1300 : Handle<Name> name =
1301 310724 : Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
1302 : VectorSlotPair feedback =
1303 310724 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1304 :
1305 : const Operator* op;
1306 310724 : if (store_mode == StoreMode::kOwn) {
1307 : DCHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
1308 : feedback.vector()->GetKind(feedback.slot()));
1309 44348 : op = javascript()->StoreNamedOwn(name, feedback);
1310 : } else {
1311 : DCHECK_EQ(StoreMode::kNormal, store_mode);
1312 : LanguageMode language_mode =
1313 : feedback.vector()->GetLanguageMode(feedback.slot());
1314 266376 : op = javascript()->StoreNamed(language_mode, name, feedback);
1315 : }
1316 :
1317 : JSTypeHintLowering::LoweringResult lowering =
1318 310724 : TryBuildSimplifiedStoreNamed(op, object, value, feedback.slot());
1319 311221 : if (lowering.IsExit()) return;
1320 :
1321 : Node* node = nullptr;
1322 310227 : if (lowering.IsSideEffectFree()) {
1323 0 : node = lowering.value();
1324 : } else {
1325 : DCHECK(!lowering.Changed());
1326 : node = NewNode(op, object, value);
1327 : }
1328 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
1329 : }
1330 :
1331 0 : void BytecodeGraphBuilder::VisitStaNamedProperty() {
1332 266376 : BuildNamedStore(StoreMode::kNormal);
1333 0 : }
1334 :
1335 0 : void BytecodeGraphBuilder::VisitStaNamedOwnProperty() {
1336 44348 : BuildNamedStore(StoreMode::kOwn);
1337 0 : }
1338 :
1339 568228 : void BytecodeGraphBuilder::VisitStaKeyedProperty() {
1340 63175 : PrepareEagerCheckpoint();
1341 63175 : Node* value = environment()->LookupAccumulator();
1342 : Node* object =
1343 126350 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1344 : Node* key =
1345 126350 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1346 : VectorSlotPair feedback =
1347 63175 : CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
1348 : LanguageMode language_mode =
1349 : feedback.vector()->GetLanguageMode(feedback.slot());
1350 63175 : const Operator* op = javascript()->StoreProperty(language_mode, feedback);
1351 :
1352 : JSTypeHintLowering::LoweringResult lowering =
1353 63175 : TryBuildSimplifiedStoreKeyed(op, object, key, value, feedback.slot());
1354 63522 : if (lowering.IsExit()) return;
1355 :
1356 : Node* node = nullptr;
1357 62828 : if (lowering.IsSideEffectFree()) {
1358 0 : node = lowering.value();
1359 : } else {
1360 : DCHECK(!lowering.Changed());
1361 : node = NewNode(op, object, key, value);
1362 : }
1363 :
1364 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
1365 : }
1366 :
1367 1400 : void BytecodeGraphBuilder::VisitLdaModuleVariable() {
1368 280 : int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
1369 280 : uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
1370 : Node* module =
1371 560 : NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true));
1372 280 : Node* value = NewNode(javascript()->LoadModule(cell_index), module);
1373 280 : environment()->BindAccumulator(value);
1374 280 : }
1375 :
1376 34415 : void BytecodeGraphBuilder::VisitStaModuleVariable() {
1377 6883 : int32_t cell_index = bytecode_iterator().GetImmediateOperand(0);
1378 6883 : uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1);
1379 : Node* module =
1380 13766 : NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true));
1381 6883 : Node* value = environment()->LookupAccumulator();
1382 6883 : NewNode(javascript()->StoreModule(cell_index), module, value);
1383 6883 : }
1384 :
1385 233968 : void BytecodeGraphBuilder::VisitPushContext() {
1386 58492 : Node* new_context = environment()->LookupAccumulator();
1387 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0),
1388 175476 : environment()->Context());
1389 : environment()->SetContext(new_context);
1390 58492 : }
1391 :
1392 73416 : void BytecodeGraphBuilder::VisitPopContext() {
1393 : Node* context =
1394 48944 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1395 : environment()->SetContext(context);
1396 24472 : }
1397 :
1398 2927529 : void BytecodeGraphBuilder::VisitCreateClosure() {
1399 : Handle<SharedFunctionInfo> shared_info = Handle<SharedFunctionInfo>::cast(
1400 585505 : bytecode_iterator().GetConstantForIndexOperand(0));
1401 585506 : int const slot_id = bytecode_iterator().GetIndexOperand(1);
1402 585506 : VectorSlotPair pair = CreateVectorSlotPair(slot_id);
1403 : PretenureFlag tenured =
1404 : interpreter::CreateClosureFlags::PretenuredBit::decode(
1405 585506 : bytecode_iterator().GetFlagOperand(2))
1406 : ? TENURED
1407 585506 : : NOT_TENURED;
1408 585506 : const Operator* op = javascript()->CreateClosure(shared_info, pair, tenured);
1409 : Node* closure = NewNode(op);
1410 585506 : environment()->BindAccumulator(closure);
1411 585506 : }
1412 :
1413 35524 : void BytecodeGraphBuilder::VisitCreateBlockContext() {
1414 : Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(
1415 8881 : bytecode_iterator().GetConstantForIndexOperand(0));
1416 :
1417 8881 : const Operator* op = javascript()->CreateBlockContext(scope_info);
1418 8881 : Node* context = NewNode(op, environment()->LookupAccumulator());
1419 8881 : environment()->BindAccumulator(context);
1420 8881 : }
1421 :
1422 72183 : void BytecodeGraphBuilder::VisitCreateFunctionContext() {
1423 24061 : uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(0);
1424 : const Operator* op =
1425 48122 : javascript()->CreateFunctionContext(slots, FUNCTION_SCOPE);
1426 24061 : Node* context = NewNode(op, GetFunctionClosure());
1427 24061 : environment()->BindAccumulator(context);
1428 24061 : }
1429 :
1430 9807 : void BytecodeGraphBuilder::VisitCreateEvalContext() {
1431 3269 : uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(0);
1432 6538 : const Operator* op = javascript()->CreateFunctionContext(slots, EVAL_SCOPE);
1433 3269 : Node* context = NewNode(op, GetFunctionClosure());
1434 3269 : environment()->BindAccumulator(context);
1435 3269 : }
1436 :
1437 130669 : void BytecodeGraphBuilder::VisitCreateCatchContext() {
1438 18667 : interpreter::Register reg = bytecode_iterator().GetRegisterOperand(0);
1439 18667 : Node* exception = environment()->LookupRegister(reg);
1440 : Handle<String> name =
1441 18667 : Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(1));
1442 : Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(
1443 18667 : bytecode_iterator().GetConstantForIndexOperand(2));
1444 18667 : Node* closure = environment()->LookupAccumulator();
1445 :
1446 18667 : const Operator* op = javascript()->CreateCatchContext(name, scope_info);
1447 : Node* context = NewNode(op, exception, closure);
1448 18667 : environment()->BindAccumulator(context);
1449 18667 : }
1450 :
1451 2958 : void BytecodeGraphBuilder::VisitCreateWithContext() {
1452 : Node* object =
1453 986 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1454 : Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(
1455 493 : bytecode_iterator().GetConstantForIndexOperand(1));
1456 :
1457 493 : const Operator* op = javascript()->CreateWithContext(scope_info);
1458 493 : Node* context = NewNode(op, object, environment()->LookupAccumulator());
1459 493 : environment()->BindAccumulator(context);
1460 493 : }
1461 :
1462 35902 : void BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) {
1463 17951 : const Operator* op = javascript()->CreateArguments(type);
1464 17951 : Node* object = NewNode(op, GetFunctionClosure());
1465 17951 : environment()->BindAccumulator(object, Environment::kAttachFrameState);
1466 17951 : }
1467 :
1468 0 : void BytecodeGraphBuilder::VisitCreateMappedArguments() {
1469 10463 : BuildCreateArguments(CreateArgumentsType::kMappedArguments);
1470 0 : }
1471 :
1472 0 : void BytecodeGraphBuilder::VisitCreateUnmappedArguments() {
1473 6575 : BuildCreateArguments(CreateArgumentsType::kUnmappedArguments);
1474 0 : }
1475 :
1476 0 : void BytecodeGraphBuilder::VisitCreateRestParameter() {
1477 913 : BuildCreateArguments(CreateArgumentsType::kRestParameter);
1478 0 : }
1479 :
1480 50850 : void BytecodeGraphBuilder::VisitCreateRegExpLiteral() {
1481 : Handle<String> constant_pattern =
1482 10170 : Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
1483 10170 : int const slot_id = bytecode_iterator().GetIndexOperand(1);
1484 10170 : VectorSlotPair pair = CreateVectorSlotPair(slot_id);
1485 10170 : int literal_flags = bytecode_iterator().GetFlagOperand(2);
1486 : Node* literal = NewNode(
1487 10170 : javascript()->CreateLiteralRegExp(constant_pattern, pair, literal_flags));
1488 10170 : environment()->BindAccumulator(literal, Environment::kAttachFrameState);
1489 10170 : }
1490 :
1491 102630 : void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
1492 : Handle<ConstantElementsPair> constant_elements =
1493 : Handle<ConstantElementsPair>::cast(
1494 20526 : bytecode_iterator().GetConstantForIndexOperand(0));
1495 20526 : int const slot_id = bytecode_iterator().GetIndexOperand(1);
1496 20526 : VectorSlotPair pair = CreateVectorSlotPair(slot_id);
1497 20526 : int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
1498 : int literal_flags =
1499 : interpreter::CreateArrayLiteralFlags::FlagsBits::decode(bytecode_flags);
1500 : // Disable allocation site mementos. Only unoptimized code will collect
1501 : // feedback about allocation site. Once the code is optimized we expect the
1502 : // data to converge. So, we disable allocation site mementos in optimized
1503 : // code. We can revisit this when we have data to the contrary.
1504 20526 : literal_flags |= ArrayLiteral::kDisableMementos;
1505 : // TODO(mstarzinger): Thread through number of elements. The below number is
1506 : // only an estimate and does not match {ArrayLiteral::values::length}.
1507 : int number_of_elements = constant_elements->constant_values()->length();
1508 : Node* literal = NewNode(javascript()->CreateLiteralArray(
1509 20526 : constant_elements, pair, literal_flags, number_of_elements));
1510 20526 : environment()->BindAccumulator(literal, Environment::kAttachFrameState);
1511 20526 : }
1512 :
1513 69660 : void BytecodeGraphBuilder::VisitCreateEmptyArrayLiteral() {
1514 23220 : int const slot_id = bytecode_iterator().GetIndexOperand(0);
1515 23220 : VectorSlotPair pair = CreateVectorSlotPair(slot_id);
1516 23220 : Node* literal = NewNode(javascript()->CreateEmptyLiteralArray(pair));
1517 23220 : environment()->BindAccumulator(literal);
1518 23220 : }
1519 :
1520 247062 : void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
1521 : Handle<BoilerplateDescription> constant_properties =
1522 : Handle<BoilerplateDescription>::cast(
1523 41177 : bytecode_iterator().GetConstantForIndexOperand(0));
1524 41177 : int const slot_id = bytecode_iterator().GetIndexOperand(1);
1525 41177 : VectorSlotPair pair = CreateVectorSlotPair(slot_id);
1526 41177 : int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
1527 : int literal_flags =
1528 : interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
1529 : // TODO(mstarzinger): Thread through number of properties. The below number is
1530 : // only an estimate and does not match {ObjectLiteral::properties_count}.
1531 41177 : int number_of_properties = constant_properties->size();
1532 : Node* literal = NewNode(javascript()->CreateLiteralObject(
1533 41177 : constant_properties, pair, literal_flags, number_of_properties));
1534 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(3),
1535 82354 : literal, Environment::kAttachFrameState);
1536 41177 : }
1537 :
1538 20664 : void BytecodeGraphBuilder::VisitCreateEmptyObjectLiteral() {
1539 : Node* literal =
1540 13776 : NewNode(javascript()->CreateEmptyLiteralObject(), GetFunctionClosure());
1541 6888 : environment()->BindAccumulator(literal);
1542 6888 : }
1543 :
1544 846 : void BytecodeGraphBuilder::VisitGetTemplateObject() {
1545 : Handle<TemplateObjectDescription> description =
1546 : Handle<TemplateObjectDescription>::cast(
1547 282 : bytecode_iterator().GetConstantForIndexOperand(0));
1548 : // It's not observable when the template object is created, so we
1549 : // can just create it eagerly during graph building and bake in
1550 : // the JSArray constant here.
1551 : Node* template_object =
1552 : jsgraph()->HeapConstant(TemplateObjectDescription::GetTemplateObject(
1553 564 : description, native_context()));
1554 282 : environment()->BindAccumulator(template_object);
1555 282 : }
1556 :
1557 67140 : Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegisters(
1558 : Node* callee, Node* receiver, interpreter::Register first_arg,
1559 632638 : int arg_count) {
1560 : // The arity of the Call node -- includes the callee, receiver and function
1561 : // arguments.
1562 67140 : int arity = 2 + arg_count;
1563 :
1564 67140 : Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
1565 :
1566 67140 : all[0] = callee;
1567 67140 : all[1] = receiver;
1568 :
1569 : // The function arguments are in consecutive registers.
1570 : int arg_base = first_arg.index();
1571 632638 : for (int i = 0; i < arg_count; ++i) {
1572 565498 : all[2 + i] =
1573 1130996 : environment()->LookupRegister(interpreter::Register(arg_base + i));
1574 : }
1575 :
1576 67140 : return all;
1577 : }
1578 :
1579 0 : Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
1580 : Node* const* args,
1581 : int arg_count) {
1582 566198 : return MakeNode(call_op, arg_count, args, false);
1583 : }
1584 :
1585 0 : Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
1586 : Node* callee,
1587 : interpreter::Register receiver,
1588 0 : size_t reg_count) {
1589 0 : Node* receiver_node = environment()->LookupRegister(receiver);
1590 : // The receiver is followed by the arguments in the consecutive registers.
1591 : DCHECK_GE(reg_count, 1);
1592 0 : interpreter::Register first_arg = interpreter::Register(receiver.index() + 1);
1593 0 : int arg_count = static_cast<int>(reg_count) - 1;
1594 :
1595 : Node* const* call_args = GetCallArgumentsFromRegisters(callee, receiver_node,
1596 0 : first_arg, arg_count);
1597 0 : return ProcessCallArguments(call_op, call_args, 2 + arg_count);
1598 : }
1599 :
1600 580738 : void BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode,
1601 : Node* const* args, size_t arg_count,
1602 1136464 : int slot_id) {
1603 : DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode(
1604 : bytecode_iterator().current_bytecode()),
1605 : receiver_mode);
1606 580738 : PrepareEagerCheckpoint();
1607 :
1608 580738 : VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1609 :
1610 580738 : CallFrequency frequency = ComputeCallFrequency(slot_id);
1611 : const Operator* op =
1612 580738 : javascript()->Call(arg_count, frequency, feedback, receiver_mode);
1613 : JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall(
1614 580738 : op, args, static_cast<int>(arg_count), feedback.slot());
1615 605750 : if (lowering.IsExit()) return;
1616 :
1617 : Node* node = nullptr;
1618 555726 : if (lowering.IsSideEffectFree()) {
1619 0 : node = lowering.value();
1620 : } else {
1621 : DCHECK(!lowering.Changed());
1622 : node = ProcessCallArguments(op, args, static_cast<int>(arg_count));
1623 : }
1624 555726 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1625 : }
1626 :
1627 66101 : Node* const* BytecodeGraphBuilder::ProcessCallVarArgs(
1628 : ConvertReceiverMode receiver_mode, Node* callee,
1629 66101 : interpreter::Register first_reg, int arg_count) {
1630 : DCHECK_GE(arg_count, 0);
1631 : Node* receiver_node;
1632 : interpreter::Register first_arg;
1633 :
1634 66101 : if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
1635 : // The receiver is implicit (and undefined), the arguments are in
1636 : // consecutive registers.
1637 56062 : receiver_node = jsgraph()->UndefinedConstant();
1638 56062 : first_arg = first_reg;
1639 : } else {
1640 : // The receiver is the first register, followed by the arguments in the
1641 : // consecutive registers.
1642 10039 : receiver_node = environment()->LookupRegister(first_reg);
1643 10039 : first_arg = interpreter::Register(first_reg.index() + 1);
1644 : }
1645 :
1646 : Node* const* call_args = GetCallArgumentsFromRegisters(callee, receiver_node,
1647 66101 : first_arg, arg_count);
1648 66101 : return call_args;
1649 : }
1650 :
1651 283340 : void BytecodeGraphBuilder::BuildCallVarArgs(ConvertReceiverMode receiver_mode) {
1652 : DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode(
1653 : bytecode_iterator().current_bytecode()),
1654 : receiver_mode);
1655 : Node* callee =
1656 113336 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1657 56668 : interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
1658 56668 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1659 56668 : int const slot_id = bytecode_iterator().GetIndexOperand(3);
1660 :
1661 : int arg_count = receiver_mode == ConvertReceiverMode::kNullOrUndefined
1662 : ? static_cast<int>(reg_count)
1663 56668 : : static_cast<int>(reg_count) - 1;
1664 : Node* const* call_args =
1665 56668 : ProcessCallVarArgs(receiver_mode, callee, first_reg, arg_count);
1666 56668 : BuildCall(receiver_mode, call_args, static_cast<size_t>(2 + arg_count),
1667 56668 : slot_id);
1668 56668 : }
1669 :
1670 0 : void BytecodeGraphBuilder::VisitCallAnyReceiver() {
1671 471 : BuildCallVarArgs(ConvertReceiverMode::kAny);
1672 0 : }
1673 :
1674 0 : void BytecodeGraphBuilder::VisitCallProperty() {
1675 9568 : BuildCallVarArgs(ConvertReceiverMode::kNotNullOrUndefined);
1676 0 : }
1677 :
1678 136310 : void BytecodeGraphBuilder::VisitCallProperty0() {
1679 : Node* callee =
1680 54524 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1681 : Node* receiver =
1682 54524 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1683 27262 : int const slot_id = bytecode_iterator().GetIndexOperand(2);
1684 : BuildCall(ConvertReceiverMode::kNotNullOrUndefined, {callee, receiver},
1685 54524 : slot_id);
1686 27262 : }
1687 :
1688 799932 : void BytecodeGraphBuilder::VisitCallProperty1() {
1689 : Node* callee =
1690 228552 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1691 : Node* receiver =
1692 228552 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1693 : Node* arg0 =
1694 228552 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
1695 114276 : int const slot_id = bytecode_iterator().GetIndexOperand(3);
1696 : BuildCall(ConvertReceiverMode::kNotNullOrUndefined, {callee, receiver, arg0},
1697 228552 : slot_id);
1698 114276 : }
1699 :
1700 225234 : void BytecodeGraphBuilder::VisitCallProperty2() {
1701 : Node* callee =
1702 50052 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1703 : Node* receiver =
1704 50052 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1705 : Node* arg0 =
1706 50052 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
1707 : Node* arg1 =
1708 50052 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(3));
1709 25026 : int const slot_id = bytecode_iterator().GetIndexOperand(4);
1710 : BuildCall(ConvertReceiverMode::kNotNullOrUndefined,
1711 50052 : {callee, receiver, arg0, arg1}, slot_id);
1712 25026 : }
1713 :
1714 0 : void BytecodeGraphBuilder::VisitCallUndefinedReceiver() {
1715 46629 : BuildCallVarArgs(ConvertReceiverMode::kNullOrUndefined);
1716 0 : }
1717 :
1718 130459 : void BytecodeGraphBuilder::VisitCallUndefinedReceiver0() {
1719 : Node* callee =
1720 65229 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1721 32615 : Node* receiver = jsgraph()->UndefinedConstant();
1722 32615 : int const slot_id = bytecode_iterator().GetIndexOperand(1);
1723 65229 : BuildCall(ConvertReceiverMode::kNullOrUndefined, {callee, receiver}, slot_id);
1724 32614 : }
1725 :
1726 945936 : void BytecodeGraphBuilder::VisitCallUndefinedReceiver1() {
1727 : Node* callee =
1728 315312 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1729 157656 : Node* receiver = jsgraph()->UndefinedConstant();
1730 : Node* arg0 =
1731 315312 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1732 157656 : int const slot_id = bytecode_iterator().GetIndexOperand(2);
1733 : BuildCall(ConvertReceiverMode::kNullOrUndefined, {callee, receiver, arg0},
1734 315312 : slot_id);
1735 157656 : }
1736 :
1737 1337880 : void BytecodeGraphBuilder::VisitCallUndefinedReceiver2() {
1738 : Node* callee =
1739 334470 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1740 167235 : Node* receiver = jsgraph()->UndefinedConstant();
1741 : Node* arg0 =
1742 334470 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
1743 : Node* arg1 =
1744 334470 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
1745 167235 : int const slot_id = bytecode_iterator().GetIndexOperand(3);
1746 : BuildCall(ConvertReceiverMode::kNullOrUndefined,
1747 334470 : {callee, receiver, arg0, arg1}, slot_id);
1748 167235 : }
1749 :
1750 9351 : void BytecodeGraphBuilder::VisitCallWithSpread() {
1751 1039 : PrepareEagerCheckpoint();
1752 : Node* callee =
1753 2078 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
1754 1039 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1755 1039 : Node* receiver_node = environment()->LookupRegister(receiver);
1756 1039 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1757 1039 : interpreter::Register first_arg = interpreter::Register(receiver.index() + 1);
1758 1039 : int arg_count = static_cast<int>(reg_count) - 1;
1759 : Node* const* args = GetCallArgumentsFromRegisters(callee, receiver_node,
1760 1039 : first_arg, arg_count);
1761 1039 : int const slot_id = bytecode_iterator().GetIndexOperand(3);
1762 1039 : VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1763 :
1764 1039 : CallFrequency frequency = ComputeCallFrequency(slot_id);
1765 : const Operator* op = javascript()->CallWithSpread(
1766 2078 : static_cast<int>(reg_count + 1), frequency, feedback);
1767 :
1768 : JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall(
1769 1039 : op, args, static_cast<int>(arg_count), feedback.slot());
1770 1039 : if (lowering.IsExit()) return;
1771 :
1772 : Node* node = nullptr;
1773 1039 : if (lowering.IsSideEffectFree()) {
1774 0 : node = lowering.value();
1775 : } else {
1776 : DCHECK(!lowering.Changed());
1777 1039 : node = ProcessCallArguments(op, args, 2 + arg_count);
1778 : }
1779 1039 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1780 : }
1781 :
1782 56598 : void BytecodeGraphBuilder::VisitCallJSRuntime() {
1783 9433 : PrepareEagerCheckpoint();
1784 : Node* callee = BuildLoadNativeContextField(
1785 9433 : bytecode_iterator().GetNativeContextIndexOperand(0));
1786 9433 : interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
1787 9433 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1788 9433 : int arg_count = static_cast<int>(reg_count);
1789 :
1790 28299 : const Operator* call = javascript()->Call(2 + arg_count);
1791 : Node* const* call_args = ProcessCallVarArgs(
1792 9433 : ConvertReceiverMode::kNullOrUndefined, callee, first_reg, arg_count);
1793 : Node* value = ProcessCallArguments(call, call_args, 2 + arg_count);
1794 9433 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1795 9433 : }
1796 :
1797 168033 : Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
1798 : const Operator* call_runtime_op, interpreter::Register receiver,
1799 492945 : size_t reg_count) {
1800 168033 : int arg_count = static_cast<int>(reg_count);
1801 : // arity is args.
1802 : int arity = arg_count;
1803 168033 : Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
1804 : int first_arg_index = receiver.index();
1805 492945 : for (int i = 0; i < static_cast<int>(reg_count); ++i) {
1806 324912 : all[i] = environment()->LookupRegister(
1807 649824 : interpreter::Register(first_arg_index + i));
1808 : }
1809 168033 : Node* value = MakeNode(call_runtime_op, arity, all, false);
1810 168033 : return value;
1811 : }
1812 :
1813 757866 : void BytecodeGraphBuilder::VisitCallRuntime() {
1814 126311 : PrepareEagerCheckpoint();
1815 126311 : Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
1816 126311 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1817 126311 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1818 :
1819 : // Create node to perform the runtime call.
1820 126311 : const Operator* call = javascript()->CallRuntime(functionId, reg_count);
1821 126311 : Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count);
1822 126311 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1823 126311 : }
1824 :
1825 2583 : void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
1826 369 : PrepareEagerCheckpoint();
1827 369 : Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
1828 369 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1829 369 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1830 : interpreter::Register first_return =
1831 369 : bytecode_iterator().GetRegisterOperand(3);
1832 :
1833 : // Create node to perform the runtime call.
1834 369 : const Operator* call = javascript()->CallRuntime(functionId, reg_count);
1835 369 : Node* return_pair = ProcessCallRuntimeArguments(call, receiver, reg_count);
1836 : environment()->BindRegistersToProjections(first_return, return_pair,
1837 369 : Environment::kAttachFrameState);
1838 369 : }
1839 :
1840 38495 : Node* const* BytecodeGraphBuilder::GetConstructArgumentsFromRegister(
1841 : Node* target, Node* new_target, interpreter::Register first_arg,
1842 219425 : int arg_count) {
1843 : // arity is args + callee and new target.
1844 38495 : int arity = arg_count + 2;
1845 38495 : Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
1846 38495 : all[0] = target;
1847 : int first_arg_index = first_arg.index();
1848 219425 : for (int i = 0; i < arg_count; ++i) {
1849 180930 : all[1 + i] = environment()->LookupRegister(
1850 361860 : interpreter::Register(first_arg_index + i));
1851 : }
1852 38495 : all[arity - 1] = new_target;
1853 38495 : return all;
1854 : }
1855 :
1856 0 : Node* BytecodeGraphBuilder::ProcessConstructArguments(const Operator* op,
1857 : Node* const* args,
1858 : int arg_count) {
1859 37656 : return MakeNode(op, arg_count, args, false);
1860 : }
1861 :
1862 302481 : void BytecodeGraphBuilder::VisitConstruct() {
1863 37915 : PrepareEagerCheckpoint();
1864 37915 : interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
1865 37915 : interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
1866 37915 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1867 37915 : int const slot_id = bytecode_iterator().GetIndexOperand(3);
1868 37915 : VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1869 :
1870 37915 : Node* new_target = environment()->LookupAccumulator();
1871 37915 : Node* callee = environment()->LookupRegister(callee_reg);
1872 :
1873 37915 : CallFrequency frequency = ComputeCallFrequency(slot_id);
1874 : const Operator* op = javascript()->Construct(
1875 75830 : static_cast<uint32_t>(reg_count + 2), frequency, feedback);
1876 37915 : int arg_count = static_cast<int>(reg_count);
1877 : Node* const* args = GetConstructArgumentsFromRegister(callee, new_target,
1878 37915 : first_reg, arg_count);
1879 : JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedConstruct(
1880 37915 : op, args, static_cast<int>(arg_count), feedback.slot());
1881 38754 : if (lowering.IsExit()) return;
1882 :
1883 : Node* node = nullptr;
1884 37076 : if (lowering.IsSideEffectFree()) {
1885 0 : node = lowering.value();
1886 : } else {
1887 : DCHECK(!lowering.Changed());
1888 37076 : node = ProcessConstructArguments(op, args, 2 + arg_count);
1889 : }
1890 37076 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1891 : }
1892 :
1893 4640 : void BytecodeGraphBuilder::VisitConstructWithSpread() {
1894 580 : PrepareEagerCheckpoint();
1895 580 : interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
1896 580 : interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
1897 580 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1898 580 : int const slot_id = bytecode_iterator().GetIndexOperand(3);
1899 580 : VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
1900 :
1901 580 : Node* new_target = environment()->LookupAccumulator();
1902 580 : Node* callee = environment()->LookupRegister(callee_reg);
1903 :
1904 580 : CallFrequency frequency = ComputeCallFrequency(slot_id);
1905 : const Operator* op = javascript()->ConstructWithSpread(
1906 1160 : static_cast<uint32_t>(reg_count + 2), frequency, feedback);
1907 580 : int arg_count = static_cast<int>(reg_count);
1908 : Node* const* args = GetConstructArgumentsFromRegister(callee, new_target,
1909 580 : first_reg, arg_count);
1910 : JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedConstruct(
1911 580 : op, args, static_cast<int>(arg_count), feedback.slot());
1912 580 : if (lowering.IsExit()) return;
1913 :
1914 : Node* node = nullptr;
1915 580 : if (lowering.IsSideEffectFree()) {
1916 0 : node = lowering.value();
1917 : } else {
1918 : DCHECK(!lowering.Changed());
1919 580 : node = ProcessConstructArguments(op, args, 2 + arg_count);
1920 : }
1921 580 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
1922 : }
1923 :
1924 248118 : void BytecodeGraphBuilder::VisitInvokeIntrinsic() {
1925 41353 : PrepareEagerCheckpoint();
1926 41353 : Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0);
1927 41353 : interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
1928 41353 : size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
1929 :
1930 : // Create node to perform the runtime call. Turbofan will take care of the
1931 : // lowering.
1932 41353 : const Operator* call = javascript()->CallRuntime(functionId, reg_count);
1933 41353 : Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count);
1934 41353 : environment()->BindAccumulator(value, Environment::kAttachFrameState);
1935 41353 : }
1936 :
1937 85200 : void BytecodeGraphBuilder::VisitThrow() {
1938 : BuildLoopExitsForFunctionExit(bytecode_analysis()->GetOutLivenessFor(
1939 28400 : bytecode_iterator().current_offset()));
1940 14200 : Node* value = environment()->LookupAccumulator();
1941 14200 : Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value);
1942 14200 : environment()->BindAccumulator(call, Environment::kAttachFrameState);
1943 14200 : Node* control = NewNode(common()->Throw());
1944 : MergeControlToLeaveFunction(control);
1945 14200 : }
1946 :
1947 9915 : void BytecodeGraphBuilder::VisitAbort() {
1948 : BuildLoopExitsForFunctionExit(bytecode_analysis()->GetOutLivenessFor(
1949 3966 : bytecode_iterator().current_offset()));
1950 : BailoutReason reason =
1951 1983 : static_cast<BailoutReason>(bytecode_iterator().GetIndexOperand(0));
1952 1983 : NewNode(simplified()->RuntimeAbort(reason));
1953 1983 : Node* control = NewNode(common()->Throw());
1954 : MergeControlToLeaveFunction(control);
1955 1983 : }
1956 :
1957 38460 : void BytecodeGraphBuilder::VisitReThrow() {
1958 : BuildLoopExitsForFunctionExit(bytecode_analysis()->GetOutLivenessFor(
1959 15384 : bytecode_iterator().current_offset()));
1960 7692 : Node* value = environment()->LookupAccumulator();
1961 7692 : NewNode(javascript()->CallRuntime(Runtime::kReThrow), value);
1962 7692 : Node* control = NewNode(common()->Throw());
1963 : MergeControlToLeaveFunction(control);
1964 7692 : }
1965 :
1966 57024 : void BytecodeGraphBuilder::BuildHoleCheckAndThrow(
1967 285120 : Node* condition, Runtime::FunctionId runtime_id, Node* name) {
1968 57024 : Node* accumulator = environment()->LookupAccumulator();
1969 57024 : NewBranch(condition, BranchHint::kFalse);
1970 : {
1971 : SubEnvironment sub_environment(this);
1972 :
1973 57024 : NewIfTrue();
1974 : Node* node;
1975 57024 : const Operator* op = javascript()->CallRuntime(runtime_id);
1976 57024 : if (runtime_id == Runtime::kThrowReferenceError) {
1977 : DCHECK_NOT_NULL(name);
1978 : node = NewNode(op, name);
1979 : } else {
1980 : DCHECK(runtime_id == Runtime::kThrowSuperAlreadyCalledError ||
1981 : runtime_id == Runtime::kThrowSuperNotCalled);
1982 : node = NewNode(op);
1983 : }
1984 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
1985 57024 : Node* control = NewNode(common()->Throw());
1986 : MergeControlToLeaveFunction(control);
1987 : }
1988 57024 : NewIfFalse();
1989 57024 : environment()->BindAccumulator(accumulator);
1990 57024 : }
1991 :
1992 204990 : void BytecodeGraphBuilder::VisitThrowReferenceErrorIfHole() {
1993 40998 : Node* accumulator = environment()->LookupAccumulator();
1994 : Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator,
1995 81996 : jsgraph()->TheHoleConstant());
1996 : Node* name =
1997 81996 : jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0));
1998 40998 : BuildHoleCheckAndThrow(check_for_hole, Runtime::kThrowReferenceError, name);
1999 40998 : }
2000 :
2001 35730 : void BytecodeGraphBuilder::VisitThrowSuperNotCalledIfHole() {
2002 11910 : Node* accumulator = environment()->LookupAccumulator();
2003 : Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator,
2004 23820 : jsgraph()->TheHoleConstant());
2005 11910 : BuildHoleCheckAndThrow(check_for_hole, Runtime::kThrowSuperNotCalled);
2006 11910 : }
2007 :
2008 16464 : void BytecodeGraphBuilder::VisitThrowSuperAlreadyCalledIfNotHole() {
2009 4116 : Node* accumulator = environment()->LookupAccumulator();
2010 : Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator,
2011 8232 : jsgraph()->TheHoleConstant());
2012 : Node* check_for_not_hole =
2013 4116 : NewNode(simplified()->BooleanNot(), check_for_hole);
2014 : BuildHoleCheckAndThrow(check_for_not_hole,
2015 4116 : Runtime::kThrowSuperAlreadyCalledError);
2016 4116 : }
2017 :
2018 1449584 : void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) {
2019 243579 : PrepareEagerCheckpoint();
2020 : Node* left =
2021 487158 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2022 243579 : Node* right = environment()->LookupAccumulator();
2023 :
2024 : FeedbackSlot slot = feedback_vector()->ToSlot(
2025 243579 : bytecode_iterator().GetIndexOperand(kBinaryOperationHintIndex));
2026 : JSTypeHintLowering::LoweringResult lowering =
2027 243579 : TryBuildSimplifiedBinaryOp(op, left, right, slot);
2028 255469 : if (lowering.IsExit()) return;
2029 :
2030 : Node* node = nullptr;
2031 231689 : if (lowering.IsSideEffectFree()) {
2032 117574 : node = lowering.value();
2033 : } else {
2034 : DCHECK(!lowering.Changed());
2035 : node = NewNode(op, left, right);
2036 : }
2037 :
2038 231689 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2039 : }
2040 :
2041 : // Helper function to create binary operation hint from the recorded type
2042 : // feedback.
2043 243920 : BinaryOperationHint BytecodeGraphBuilder::GetBinaryOperationHint(
2044 243920 : int operand_index) {
2045 : FeedbackSlot slot = feedback_vector()->ToSlot(
2046 243920 : bytecode_iterator().GetIndexOperand(operand_index));
2047 : DCHECK_EQ(FeedbackSlotKind::kBinaryOp, feedback_vector()->GetKind(slot));
2048 : BinaryOpICNexus nexus(feedback_vector(), slot);
2049 243920 : return nexus.GetBinaryOperationFeedback();
2050 : }
2051 :
2052 : // Helper function to create compare operation hint from the recorded type
2053 : // feedback.
2054 285565 : CompareOperationHint BytecodeGraphBuilder::GetCompareOperationHint() {
2055 285565 : int slot_index = bytecode_iterator().GetIndexOperand(1);
2056 : FeedbackSlot slot = feedback_vector()->ToSlot(slot_index);
2057 : DCHECK_EQ(FeedbackSlotKind::kCompareOp, feedback_vector()->GetKind(slot));
2058 : CompareICNexus nexus(feedback_vector(), slot);
2059 285565 : return nexus.GetCompareOperationFeedback();
2060 : }
2061 :
2062 : // Helper function to create for-in mode from the recorded type feedback.
2063 3222 : ForInMode BytecodeGraphBuilder::GetForInMode(int operand_index) {
2064 : FeedbackSlot slot = feedback_vector()->ToSlot(
2065 3222 : bytecode_iterator().GetIndexOperand(operand_index));
2066 : ForInICNexus nexus(feedback_vector(), slot);
2067 3222 : switch (nexus.GetForInFeedback()) {
2068 : case ForInHint::kNone:
2069 : case ForInHint::kEnumCacheKeysAndIndices:
2070 : return ForInMode::kUseEnumCacheKeysAndIndices;
2071 : case ForInHint::kEnumCacheKeys:
2072 0 : return ForInMode::kUseEnumCacheKeys;
2073 : case ForInHint::kAny:
2074 834 : return ForInMode::kGeneric;
2075 : }
2076 0 : UNREACHABLE();
2077 : }
2078 :
2079 620271 : CallFrequency BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const {
2080 620271 : if (invocation_frequency_.IsUnknown()) return CallFrequency();
2081 : CallICNexus nexus(feedback_vector(), feedback_vector()->ToSlot(slot_id));
2082 618715 : return CallFrequency(nexus.ComputeCallFrequency() *
2083 618716 : invocation_frequency_.value());
2084 : }
2085 :
2086 99833 : void BytecodeGraphBuilder::VisitNegate() {
2087 16640 : PrepareEagerCheckpoint();
2088 :
2089 : // TODO(adamk): Create a JSNegate operator, as this desugaring is
2090 : // invalid for BigInts.
2091 16640 : const Operator* op = javascript()->Multiply();
2092 16640 : Node* operand = environment()->LookupAccumulator();
2093 : Node* multiplier = jsgraph()->SmiConstant(-1);
2094 :
2095 : FeedbackSlot slot = feedback_vector()->ToSlot(
2096 16640 : bytecode_iterator().GetIndexOperand(kUnaryOperationHintIndex));
2097 : JSTypeHintLowering::LoweringResult lowering =
2098 16640 : TryBuildSimplifiedBinaryOp(op, operand, multiplier, slot);
2099 16647 : if (lowering.IsExit()) return;
2100 :
2101 : Node* node = nullptr;
2102 16633 : if (lowering.IsSideEffectFree()) {
2103 13403 : node = lowering.value();
2104 : } else {
2105 : DCHECK(!lowering.Changed());
2106 : node = NewNode(op, operand, multiplier);
2107 : }
2108 :
2109 16633 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2110 : }
2111 :
2112 2490 : void BytecodeGraphBuilder::VisitBitwiseNot() {
2113 415 : PrepareEagerCheckpoint();
2114 :
2115 : // TODO(adamk): Create a JSBitwiseNot operator, as this desugaring is
2116 : // invalid for BigInts.
2117 415 : const Operator* op = javascript()->BitwiseXor();
2118 415 : Node* operand = environment()->LookupAccumulator();
2119 : Node* xor_value = jsgraph()->SmiConstant(-1);
2120 :
2121 : FeedbackSlot slot = feedback_vector()->ToSlot(
2122 415 : bytecode_iterator().GetIndexOperand(kUnaryOperationHintIndex));
2123 : JSTypeHintLowering::LoweringResult lowering =
2124 415 : TryBuildSimplifiedBinaryOp(op, operand, xor_value, slot);
2125 415 : if (lowering.IsExit()) return;
2126 :
2127 : Node* node = nullptr;
2128 415 : if (lowering.IsSideEffectFree()) {
2129 308 : node = lowering.value();
2130 : } else {
2131 : DCHECK(!lowering.Changed());
2132 : node = NewNode(op, operand, xor_value);
2133 : }
2134 :
2135 415 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2136 : }
2137 :
2138 341268 : void BytecodeGraphBuilder::VisitAdd() {
2139 : BuildBinaryOp(
2140 341268 : javascript()->Add(GetBinaryOperationHint(kBinaryOperationHintIndex)));
2141 170634 : }
2142 :
2143 6704 : void BytecodeGraphBuilder::VisitSub() {
2144 6704 : BuildBinaryOp(javascript()->Subtract());
2145 6704 : }
2146 :
2147 6557 : void BytecodeGraphBuilder::VisitMul() {
2148 6557 : BuildBinaryOp(javascript()->Multiply());
2149 6557 : }
2150 :
2151 69476 : void BytecodeGraphBuilder::VisitDiv() { BuildBinaryOp(javascript()->Divide()); }
2152 :
2153 1884 : void BytecodeGraphBuilder::VisitMod() {
2154 1884 : BuildBinaryOp(javascript()->Modulus());
2155 1884 : }
2156 :
2157 8490 : void BytecodeGraphBuilder::VisitBitwiseOr() {
2158 8490 : BuildBinaryOp(javascript()->BitwiseOr());
2159 8490 : }
2160 :
2161 1936 : void BytecodeGraphBuilder::VisitBitwiseXor() {
2162 1936 : BuildBinaryOp(javascript()->BitwiseXor());
2163 1936 : }
2164 :
2165 7109 : void BytecodeGraphBuilder::VisitBitwiseAnd() {
2166 7109 : BuildBinaryOp(javascript()->BitwiseAnd());
2167 7109 : }
2168 :
2169 2097 : void BytecodeGraphBuilder::VisitShiftLeft() {
2170 2097 : BuildBinaryOp(javascript()->ShiftLeft());
2171 2097 : }
2172 :
2173 1564 : void BytecodeGraphBuilder::VisitShiftRight() {
2174 1564 : BuildBinaryOp(javascript()->ShiftRight());
2175 1564 : }
2176 :
2177 1866 : void BytecodeGraphBuilder::VisitShiftRightLogical() {
2178 1866 : BuildBinaryOp(javascript()->ShiftRightLogical());
2179 1866 : }
2180 :
2181 775185 : void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) {
2182 129373 : PrepareEagerCheckpoint();
2183 129373 : Node* left = environment()->LookupAccumulator();
2184 258746 : Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
2185 :
2186 : FeedbackSlot slot = feedback_vector()->ToSlot(
2187 129373 : bytecode_iterator().GetIndexOperand(kBinaryOperationSmiHintIndex));
2188 : JSTypeHintLowering::LoweringResult lowering =
2189 129373 : TryBuildSimplifiedBinaryOp(op, left, right, slot);
2190 130426 : if (lowering.IsExit()) return;
2191 :
2192 : Node* node = nullptr;
2193 128320 : if (lowering.IsSideEffectFree()) {
2194 96624 : node = lowering.value();
2195 : } else {
2196 : DCHECK(!lowering.Changed());
2197 : node = NewNode(op, left, right);
2198 : }
2199 128320 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2200 : }
2201 :
2202 146572 : void BytecodeGraphBuilder::VisitAddSmi() {
2203 : BuildBinaryOpWithImmediate(
2204 146572 : javascript()->Add(GetBinaryOperationHint(kBinaryOperationSmiHintIndex)));
2205 73286 : }
2206 :
2207 7040 : void BytecodeGraphBuilder::VisitSubSmi() {
2208 7040 : BuildBinaryOpWithImmediate(javascript()->Subtract());
2209 7040 : }
2210 :
2211 5388 : void BytecodeGraphBuilder::VisitMulSmi() {
2212 5388 : BuildBinaryOpWithImmediate(javascript()->Multiply());
2213 5388 : }
2214 :
2215 6775 : void BytecodeGraphBuilder::VisitDivSmi() {
2216 6775 : BuildBinaryOpWithImmediate(javascript()->Divide());
2217 6775 : }
2218 :
2219 3901 : void BytecodeGraphBuilder::VisitModSmi() {
2220 3901 : BuildBinaryOpWithImmediate(javascript()->Modulus());
2221 3901 : }
2222 :
2223 17118 : void BytecodeGraphBuilder::VisitBitwiseOrSmi() {
2224 17118 : BuildBinaryOpWithImmediate(javascript()->BitwiseOr());
2225 17118 : }
2226 :
2227 223 : void BytecodeGraphBuilder::VisitBitwiseXorSmi() {
2228 223 : BuildBinaryOpWithImmediate(javascript()->BitwiseXor());
2229 223 : }
2230 :
2231 5353 : void BytecodeGraphBuilder::VisitBitwiseAndSmi() {
2232 5353 : BuildBinaryOpWithImmediate(javascript()->BitwiseAnd());
2233 5353 : }
2234 :
2235 1780 : void BytecodeGraphBuilder::VisitShiftLeftSmi() {
2236 1780 : BuildBinaryOpWithImmediate(javascript()->ShiftLeft());
2237 1780 : }
2238 :
2239 6171 : void BytecodeGraphBuilder::VisitShiftRightSmi() {
2240 6171 : BuildBinaryOpWithImmediate(javascript()->ShiftRight());
2241 6171 : }
2242 :
2243 2338 : void BytecodeGraphBuilder::VisitShiftRightLogicalSmi() {
2244 2338 : BuildBinaryOpWithImmediate(javascript()->ShiftRightLogical());
2245 2338 : }
2246 :
2247 283826 : void BytecodeGraphBuilder::VisitInc() {
2248 47457 : PrepareEagerCheckpoint();
2249 : // Note: Use subtract -1 here instead of add 1 to ensure we always convert to
2250 : // a number, not a string.
2251 47457 : Node* left = environment()->LookupAccumulator();
2252 47457 : Node* right = jsgraph()->Constant(-1);
2253 47457 : const Operator* op = javascript()->Subtract();
2254 :
2255 : FeedbackSlot slot = feedback_vector()->ToSlot(
2256 47457 : bytecode_iterator().GetIndexOperand(kCountOperationHintIndex));
2257 : JSTypeHintLowering::LoweringResult lowering =
2258 47457 : TryBuildSimplifiedBinaryOp(op, left, right, slot);
2259 48373 : if (lowering.IsExit()) return;
2260 :
2261 : Node* node = nullptr;
2262 46541 : if (lowering.IsSideEffectFree()) {
2263 27385 : node = lowering.value();
2264 : } else {
2265 : DCHECK(!lowering.Changed());
2266 : node = NewNode(op, left, right);
2267 : }
2268 46541 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2269 : }
2270 :
2271 86453 : void BytecodeGraphBuilder::VisitDec() {
2272 14423 : PrepareEagerCheckpoint();
2273 14423 : Node* left = environment()->LookupAccumulator();
2274 14423 : Node* right = jsgraph()->OneConstant();
2275 14423 : const Operator* op = javascript()->Subtract();
2276 :
2277 : FeedbackSlot slot = feedback_vector()->ToSlot(
2278 14423 : bytecode_iterator().GetIndexOperand(kCountOperationHintIndex));
2279 : JSTypeHintLowering::LoweringResult lowering =
2280 14423 : TryBuildSimplifiedBinaryOp(op, left, right, slot);
2281 14508 : if (lowering.IsExit()) return;
2282 :
2283 : Node* node = nullptr;
2284 14338 : if (lowering.IsSideEffectFree()) {
2285 11518 : node = lowering.value();
2286 : } else {
2287 : DCHECK(!lowering.Changed());
2288 : node = NewNode(op, left, right);
2289 : }
2290 14338 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2291 : }
2292 :
2293 9834 : void BytecodeGraphBuilder::VisitLogicalNot() {
2294 3278 : Node* value = environment()->LookupAccumulator();
2295 3278 : Node* node = NewNode(simplified()->BooleanNot(), value);
2296 3278 : environment()->BindAccumulator(node);
2297 3278 : }
2298 :
2299 23928 : void BytecodeGraphBuilder::VisitToBooleanLogicalNot() {
2300 : Node* value = NewNode(simplified()->ToBoolean(ToBooleanHint::kAny),
2301 17946 : environment()->LookupAccumulator());
2302 5982 : Node* node = NewNode(simplified()->BooleanNot(), value);
2303 5982 : environment()->BindAccumulator(node);
2304 5982 : }
2305 :
2306 123567 : void BytecodeGraphBuilder::VisitTypeOf() {
2307 : Node* node =
2308 82378 : NewNode(simplified()->TypeOf(), environment()->LookupAccumulator());
2309 41189 : environment()->BindAccumulator(node);
2310 41189 : }
2311 :
2312 10822 : void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) {
2313 1546 : PrepareEagerCheckpoint();
2314 1546 : Node* key = environment()->LookupAccumulator();
2315 : Node* object =
2316 3092 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2317 3092 : Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode));
2318 1546 : Node* node = NewNode(javascript()->DeleteProperty(), object, key, mode);
2319 1546 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2320 1546 : }
2321 :
2322 0 : void BytecodeGraphBuilder::VisitDeletePropertyStrict() {
2323 799 : BuildDelete(LanguageMode::kStrict);
2324 0 : }
2325 :
2326 0 : void BytecodeGraphBuilder::VisitDeletePropertySloppy() {
2327 747 : BuildDelete(LanguageMode::kSloppy);
2328 0 : }
2329 :
2330 18272 : void BytecodeGraphBuilder::VisitGetSuperConstructor() {
2331 : Node* node = NewNode(javascript()->GetSuperConstructor(),
2332 9136 : environment()->LookupAccumulator());
2333 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node,
2334 9136 : Environment::kAttachFrameState);
2335 4568 : }
2336 :
2337 1697182 : void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) {
2338 285565 : PrepareEagerCheckpoint();
2339 : Node* left =
2340 571130 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2341 285565 : Node* right = environment()->LookupAccumulator();
2342 :
2343 285565 : int slot_index = bytecode_iterator().GetIndexOperand(1);
2344 285565 : FeedbackSlot slot = feedback_vector()->ToSlot(slot_index);
2345 : JSTypeHintLowering::LoweringResult lowering =
2346 285565 : TryBuildSimplifiedBinaryOp(op, left, right, slot);
2347 301773 : if (lowering.IsExit()) return;
2348 :
2349 : Node* node = nullptr;
2350 269357 : if (lowering.IsSideEffectFree()) {
2351 64780 : node = lowering.value();
2352 : } else {
2353 : DCHECK(!lowering.Changed());
2354 : node = NewNode(op, left, right);
2355 : }
2356 269357 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2357 : }
2358 :
2359 59606 : void BytecodeGraphBuilder::VisitTestEqual() {
2360 59606 : BuildCompareOp(javascript()->Equal(GetCompareOperationHint()));
2361 29803 : }
2362 :
2363 346486 : void BytecodeGraphBuilder::VisitTestEqualStrict() {
2364 346486 : BuildCompareOp(javascript()->StrictEqual(GetCompareOperationHint()));
2365 173243 : }
2366 :
2367 63984 : void BytecodeGraphBuilder::VisitTestLessThan() {
2368 63984 : BuildCompareOp(javascript()->LessThan(GetCompareOperationHint()));
2369 31992 : }
2370 :
2371 87500 : void BytecodeGraphBuilder::VisitTestGreaterThan() {
2372 87500 : BuildCompareOp(javascript()->GreaterThan(GetCompareOperationHint()));
2373 43750 : }
2374 :
2375 5934 : void BytecodeGraphBuilder::VisitTestLessThanOrEqual() {
2376 5934 : BuildCompareOp(javascript()->LessThanOrEqual(GetCompareOperationHint()));
2377 2967 : }
2378 :
2379 7620 : void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() {
2380 7620 : BuildCompareOp(javascript()->GreaterThanOrEqual(GetCompareOperationHint()));
2381 3810 : }
2382 :
2383 39750 : void BytecodeGraphBuilder::VisitTestEqualStrictNoFeedback() {
2384 : // TODO(5310): Currently this is used with both Smi operands and with
2385 : // string operands. We pass string operands for static property check in
2386 : // VisitClassLiteralProperties. This should be changed, so we only use this
2387 : // for Smi operations and lower it to SpeculativeNumberEqual[kSignedSmall]
2388 6625 : PrepareEagerCheckpoint();
2389 : Node* left =
2390 13250 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2391 6625 : Node* right = environment()->LookupAccumulator();
2392 :
2393 : Node* node = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
2394 6625 : left, right);
2395 6625 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2396 6625 : }
2397 :
2398 32465 : void BytecodeGraphBuilder::BuildTestingOp(const Operator* op) {
2399 6493 : PrepareEagerCheckpoint();
2400 : Node* left =
2401 12986 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2402 6493 : Node* right = environment()->LookupAccumulator();
2403 : Node* node = NewNode(op, left, right);
2404 6493 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2405 6493 : }
2406 :
2407 2746 : void BytecodeGraphBuilder::VisitTestIn() {
2408 2746 : BuildTestingOp(javascript()->HasProperty());
2409 2746 : }
2410 :
2411 3747 : void BytecodeGraphBuilder::VisitTestInstanceOf() {
2412 3747 : BuildTestingOp(javascript()->InstanceOf());
2413 3747 : }
2414 :
2415 14436 : void BytecodeGraphBuilder::VisitTestUndetectable() {
2416 4812 : Node* object = environment()->LookupAccumulator();
2417 4812 : Node* node = NewNode(jsgraph()->simplified()->ObjectIsUndetectable(), object);
2418 4812 : environment()->BindAccumulator(node);
2419 4812 : }
2420 :
2421 764 : void BytecodeGraphBuilder::VisitTestNull() {
2422 191 : Node* object = environment()->LookupAccumulator();
2423 : Node* result = NewNode(simplified()->ReferenceEqual(), object,
2424 382 : jsgraph()->NullConstant());
2425 191 : environment()->BindAccumulator(result);
2426 191 : }
2427 :
2428 5660 : void BytecodeGraphBuilder::VisitTestUndefined() {
2429 1415 : Node* object = environment()->LookupAccumulator();
2430 : Node* result = NewNode(simplified()->ReferenceEqual(), object,
2431 2830 : jsgraph()->UndefinedConstant());
2432 1415 : environment()->BindAccumulator(result);
2433 1415 : }
2434 :
2435 210822 : void BytecodeGraphBuilder::VisitTestTypeOf() {
2436 34405 : Node* object = environment()->LookupAccumulator();
2437 : auto literal_flag = interpreter::TestTypeOfFlags::Decode(
2438 34405 : bytecode_iterator().GetFlagOperand(0));
2439 : Node* result;
2440 34405 : switch (literal_flag) {
2441 : case interpreter::TestTypeOfFlags::LiteralFlag::kNumber:
2442 9838 : result = NewNode(simplified()->ObjectIsNumber(), object);
2443 9838 : break;
2444 : case interpreter::TestTypeOfFlags::LiteralFlag::kString:
2445 2261 : result = NewNode(simplified()->ObjectIsString(), object);
2446 2261 : break;
2447 : case interpreter::TestTypeOfFlags::LiteralFlag::kSymbol:
2448 132 : result = NewNode(simplified()->ObjectIsSymbol(), object);
2449 132 : break;
2450 : case interpreter::TestTypeOfFlags::LiteralFlag::kBoolean:
2451 : result = NewNode(common()->Select(MachineRepresentation::kTagged),
2452 : NewNode(simplified()->ReferenceEqual(), object,
2453 : jsgraph()->TrueConstant()),
2454 : jsgraph()->TrueConstant(),
2455 : NewNode(simplified()->ReferenceEqual(), object,
2456 834 : jsgraph()->FalseConstant()));
2457 139 : break;
2458 : case interpreter::TestTypeOfFlags::LiteralFlag::kUndefined:
2459 : result = graph()->NewNode(
2460 : common()->Select(MachineRepresentation::kTagged),
2461 : graph()->NewNode(simplified()->ReferenceEqual(), object,
2462 : jsgraph()->NullConstant()),
2463 : jsgraph()->FalseConstant(),
2464 5520 : graph()->NewNode(simplified()->ObjectIsUndetectable(), object));
2465 1104 : break;
2466 : case interpreter::TestTypeOfFlags::LiteralFlag::kFunction:
2467 : result =
2468 13623 : graph()->NewNode(simplified()->ObjectIsDetectableCallable(), object);
2469 13623 : break;
2470 : case interpreter::TestTypeOfFlags::LiteralFlag::kObject:
2471 : result = graph()->NewNode(
2472 : common()->Select(MachineRepresentation::kTagged),
2473 : graph()->NewNode(simplified()->ObjectIsNonCallable(), object),
2474 : jsgraph()->TrueConstant(),
2475 : graph()->NewNode(simplified()->ReferenceEqual(), object,
2476 36540 : jsgraph()->NullConstant()));
2477 7308 : break;
2478 : case interpreter::TestTypeOfFlags::LiteralFlag::kOther:
2479 0 : UNREACHABLE(); // Should never be emitted.
2480 : break;
2481 : }
2482 34405 : environment()->BindAccumulator(result);
2483 34405 : }
2484 :
2485 9765 : void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) {
2486 3255 : Node* value = NewNode(js_op, environment()->LookupAccumulator());
2487 : environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value,
2488 6510 : Environment::kAttachFrameState);
2489 3255 : }
2490 :
2491 1214 : void BytecodeGraphBuilder::VisitToName() {
2492 1214 : BuildCastOperator(javascript()->ToName());
2493 1214 : }
2494 :
2495 2041 : void BytecodeGraphBuilder::VisitToObject() {
2496 2041 : BuildCastOperator(javascript()->ToObject());
2497 2041 : }
2498 :
2499 137014 : void BytecodeGraphBuilder::VisitToNumber() {
2500 31388 : PrepareEagerCheckpoint();
2501 31388 : Node* object = environment()->LookupAccumulator();
2502 :
2503 : FeedbackSlot slot =
2504 31388 : feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(0));
2505 : JSTypeHintLowering::LoweringResult lowering =
2506 31388 : TryBuildSimplifiedToNumber(object, slot);
2507 :
2508 : Node* node = nullptr;
2509 31388 : if (lowering.IsSideEffectFree()) {
2510 19926 : node = lowering.value();
2511 : } else {
2512 : DCHECK(!lowering.Changed());
2513 11462 : node = NewNode(javascript()->ToNumber(), object);
2514 : }
2515 :
2516 31388 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2517 31388 : }
2518 :
2519 0 : void BytecodeGraphBuilder::VisitToNumeric() {
2520 : // TODO(neis): This is currently only correct in the absence of bigints.
2521 : DCHECK(!FLAG_harmony_bigint);
2522 15850 : VisitToNumber();
2523 0 : }
2524 :
2525 86634 : void BytecodeGraphBuilder::VisitJump() { BuildJump(); }
2526 :
2527 2242 : void BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); }
2528 :
2529 84542 : void BytecodeGraphBuilder::VisitJumpIfTrue() { BuildJumpIfTrue(); }
2530 :
2531 1132 : void BytecodeGraphBuilder::VisitJumpIfTrueConstant() { BuildJumpIfTrue(); }
2532 :
2533 213770 : void BytecodeGraphBuilder::VisitJumpIfFalse() { BuildJumpIfFalse(); }
2534 :
2535 3196 : void BytecodeGraphBuilder::VisitJumpIfFalseConstant() { BuildJumpIfFalse(); }
2536 :
2537 0 : void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() {
2538 39428 : BuildJumpIfToBooleanTrue();
2539 0 : }
2540 :
2541 0 : void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() {
2542 748 : BuildJumpIfToBooleanTrue();
2543 0 : }
2544 :
2545 0 : void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() {
2546 56317 : BuildJumpIfToBooleanFalse();
2547 0 : }
2548 :
2549 0 : void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() {
2550 127 : BuildJumpIfToBooleanFalse();
2551 0 : }
2552 :
2553 4255 : void BytecodeGraphBuilder::VisitJumpIfJSReceiver() { BuildJumpIfJSReceiver(); }
2554 :
2555 0 : void BytecodeGraphBuilder::VisitJumpIfJSReceiverConstant() {
2556 0 : BuildJumpIfJSReceiver();
2557 0 : }
2558 :
2559 2655 : void BytecodeGraphBuilder::VisitJumpIfNull() {
2560 2655 : BuildJumpIfEqual(jsgraph()->NullConstant());
2561 2655 : }
2562 :
2563 41 : void BytecodeGraphBuilder::VisitJumpIfNullConstant() {
2564 41 : BuildJumpIfEqual(jsgraph()->NullConstant());
2565 41 : }
2566 :
2567 2666 : void BytecodeGraphBuilder::VisitJumpIfNotNull() {
2568 2666 : BuildJumpIfNotEqual(jsgraph()->NullConstant());
2569 2666 : }
2570 :
2571 0 : void BytecodeGraphBuilder::VisitJumpIfNotNullConstant() {
2572 0 : BuildJumpIfNotEqual(jsgraph()->NullConstant());
2573 0 : }
2574 :
2575 9763 : void BytecodeGraphBuilder::VisitJumpIfUndefined() {
2576 9763 : BuildJumpIfEqual(jsgraph()->UndefinedConstant());
2577 9763 : }
2578 :
2579 91 : void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() {
2580 91 : BuildJumpIfEqual(jsgraph()->UndefinedConstant());
2581 91 : }
2582 :
2583 11619 : void BytecodeGraphBuilder::VisitJumpIfNotUndefined() {
2584 11619 : BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
2585 11619 : }
2586 :
2587 5 : void BytecodeGraphBuilder::VisitJumpIfNotUndefinedConstant() {
2588 5 : BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
2589 5 : }
2590 :
2591 42226 : void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); }
2592 :
2593 7006 : void BytecodeGraphBuilder::BuildSwitchOnSmi(Node* condition) {
2594 : interpreter::JumpTableTargetOffsets offsets =
2595 7006 : bytecode_iterator().GetJumpTableTargetOffsets();
2596 :
2597 7006 : NewSwitch(condition, offsets.size() + 1);
2598 23104 : for (const auto& entry : offsets) {
2599 : SubEnvironment sub_environment(this);
2600 16098 : NewIfValue(entry.case_value);
2601 16098 : MergeIntoSuccessorEnvironment(entry.target_offset);
2602 : }
2603 7006 : NewIfDefault();
2604 7006 : }
2605 :
2606 21018 : void BytecodeGraphBuilder::VisitSwitchOnSmiNoFeedback() {
2607 7006 : PrepareEagerCheckpoint();
2608 :
2609 7006 : Node* acc = environment()->LookupAccumulator();
2610 7006 : Node* acc_smi = NewNode(simplified()->CheckSmi(), acc);
2611 7006 : BuildSwitchOnSmi(acc_smi);
2612 7006 : }
2613 :
2614 1446120 : void BytecodeGraphBuilder::VisitStackCheck() {
2615 482039 : PrepareEagerCheckpoint();
2616 482040 : Node* node = NewNode(javascript()->StackCheck());
2617 : environment()->RecordAfterState(node, Environment::kAttachFrameState);
2618 482040 : }
2619 :
2620 108280 : void BytecodeGraphBuilder::VisitSetPendingMessage() {
2621 27070 : Node* previous_message = NewNode(javascript()->LoadMessage());
2622 54140 : NewNode(javascript()->StoreMessage(), environment()->LookupAccumulator());
2623 27070 : environment()->BindAccumulator(previous_message);
2624 27070 : }
2625 :
2626 3115622 : void BytecodeGraphBuilder::VisitReturn() {
2627 : BuildLoopExitsForFunctionExit(bytecode_analysis()->GetInLivenessFor(
2628 1246248 : bytecode_iterator().current_offset()));
2629 623124 : Node* pop_node = jsgraph()->ZeroConstant();
2630 : Node* control =
2631 1246250 : NewNode(common()->Return(), pop_node, environment()->LookupAccumulator());
2632 : MergeControlToLeaveFunction(control);
2633 623125 : }
2634 :
2635 1686 : void BytecodeGraphBuilder::VisitDebugger() {
2636 562 : PrepareEagerCheckpoint();
2637 562 : Node* call = NewNode(javascript()->Debugger());
2638 : environment()->RecordAfterState(call, Environment::kAttachFrameState);
2639 562 : }
2640 :
2641 : // We cannot create a graph from the debugger copy of the bytecode array.
2642 : #define DEBUG_BREAK(Name, ...) \
2643 : void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); }
2644 0 : DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
2645 : #undef DEBUG_BREAK
2646 :
2647 208 : void BytecodeGraphBuilder::VisitIncBlockCounter() {
2648 52 : Node* closure = GetFunctionClosure();
2649 : Node* coverage_array_slot =
2650 104 : jsgraph()->Constant(bytecode_iterator().GetIndexOperand(0));
2651 :
2652 52 : const Operator* op = javascript()->CallRuntime(Runtime::kIncBlockCounter);
2653 :
2654 : NewNode(op, closure, coverage_array_slot);
2655 52 : }
2656 :
2657 6192 : void BytecodeGraphBuilder::VisitForInEnumerate() {
2658 : Node* receiver =
2659 3096 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2660 1548 : Node* enumerator = NewNode(javascript()->ForInEnumerate(), receiver);
2661 1548 : environment()->BindAccumulator(enumerator, Environment::kAttachFrameState);
2662 1548 : }
2663 :
2664 9201 : void BytecodeGraphBuilder::VisitForInPrepare() {
2665 1548 : PrepareEagerCheckpoint();
2666 1548 : Node* enumerator = environment()->LookupAccumulator();
2667 :
2668 : FeedbackSlot slot =
2669 1548 : feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(1));
2670 : JSTypeHintLowering::LoweringResult lowering =
2671 1548 : TryBuildSimplifiedForInPrepare(enumerator, slot);
2672 1577 : if (lowering.IsExit()) return;
2673 : DCHECK(!lowering.Changed());
2674 3038 : Node* node = NewNode(javascript()->ForInPrepare(GetForInMode(1)), enumerator);
2675 : environment()->BindRegistersToProjections(
2676 3038 : bytecode_iterator().GetRegisterOperand(0), node);
2677 : }
2678 :
2679 11970 : void BytecodeGraphBuilder::VisitForInContinue() {
2680 1710 : PrepareEagerCheckpoint();
2681 : Node* index =
2682 3420 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2683 : Node* cache_length =
2684 3420 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2685 : Node* exit_cond = NewNode(simplified()->SpeculativeNumberLessThan(
2686 : NumberOperationHint::kSignedSmall),
2687 1710 : index, cache_length);
2688 1710 : environment()->BindAccumulator(exit_cond);
2689 1710 : }
2690 :
2691 23926 : void BytecodeGraphBuilder::VisitForInNext() {
2692 1710 : PrepareEagerCheckpoint();
2693 : Node* receiver =
2694 3420 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2695 : Node* index =
2696 3420 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
2697 3420 : int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index();
2698 : Node* cache_type = environment()->LookupRegister(
2699 1710 : interpreter::Register(catch_reg_pair_index));
2700 : Node* cache_array = environment()->LookupRegister(
2701 3420 : interpreter::Register(catch_reg_pair_index + 1));
2702 :
2703 : // We need to rename the {index} here, as in case of OSR we loose the
2704 : // information that the {index} is always a valid unsigned Smi value.
2705 : index = graph()->NewNode(common()->TypeGuard(Type::UnsignedSmall()), index,
2706 3420 : environment()->GetControlDependency());
2707 :
2708 : FeedbackSlot slot =
2709 1710 : feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(3));
2710 : JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedForInNext(
2711 1710 : receiver, cache_array, cache_type, index, slot);
2712 1717 : if (lowering.IsExit()) return;
2713 :
2714 : DCHECK(!lowering.Changed());
2715 : Node* node = NewNode(javascript()->ForInNext(GetForInMode(3)), receiver,
2716 3406 : cache_array, cache_type, index);
2717 1703 : environment()->BindAccumulator(node, Environment::kAttachFrameState);
2718 : }
2719 :
2720 10446 : void BytecodeGraphBuilder::VisitForInStep() {
2721 1741 : PrepareEagerCheckpoint();
2722 : Node* index =
2723 3482 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2724 : index = NewNode(simplified()->SpeculativeSafeIntegerAdd(
2725 : NumberOperationHint::kSignedSmall),
2726 3482 : index, jsgraph()->OneConstant());
2727 1741 : environment()->BindAccumulator(index, Environment::kAttachFrameState);
2728 1741 : }
2729 :
2730 86504 : void BytecodeGraphBuilder::VisitSuspendGenerator() {
2731 : Node* generator = environment()->LookupRegister(
2732 10144 : bytecode_iterator().GetRegisterOperand(0));
2733 5072 : interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
2734 : // We assume we are storing a range starting from index 0.
2735 5072 : CHECK_EQ(0, first_reg.index());
2736 : int register_count =
2737 5072 : static_cast<int>(bytecode_iterator().GetRegisterCountOperand(2));
2738 : Node* suspend_id = jsgraph()->SmiConstant(
2739 5072 : bytecode_iterator().GetUnsignedImmediateOperand(3));
2740 :
2741 : // The offsets used by the bytecode iterator are relative to a different base
2742 : // than what is used in the interpreter, hence the addition.
2743 : Node* offset =
2744 5072 : jsgraph()->Constant(bytecode_iterator().current_offset() +
2745 10144 : (BytecodeArray::kHeaderSize - kHeapObjectTag));
2746 :
2747 5072 : int value_input_count = 3 + register_count;
2748 :
2749 5072 : Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count);
2750 5072 : value_inputs[0] = generator;
2751 5072 : value_inputs[1] = suspend_id;
2752 5072 : value_inputs[2] = offset;
2753 40856 : for (int i = 0; i < register_count; ++i) {
2754 35784 : value_inputs[3 + i] =
2755 35784 : environment()->LookupRegister(interpreter::Register(i));
2756 : }
2757 :
2758 : MakeNode(javascript()->GeneratorStore(register_count), value_input_count,
2759 5072 : value_inputs, false);
2760 5072 : }
2761 :
2762 6344 : void BytecodeGraphBuilder::VisitRestoreGeneratorState() {
2763 : Node* generator = environment()->LookupRegister(
2764 3172 : bytecode_iterator().GetRegisterOperand(0));
2765 :
2766 : Node* state =
2767 1586 : NewNode(javascript()->GeneratorRestoreContinuation(), generator);
2768 :
2769 1586 : environment()->BindAccumulator(state, Environment::kAttachFrameState);
2770 1586 : }
2771 :
2772 93146 : void BytecodeGraphBuilder::VisitRestoreGeneratorRegisters() {
2773 : Node* generator =
2774 10276 : environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
2775 5138 : interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
2776 : // We assume we are restoring registers starting fromm index 0.
2777 5138 : CHECK_EQ(0, first_reg.index());
2778 : int register_count =
2779 5138 : static_cast<int>(bytecode_iterator().GetRegisterCountOperand(2));
2780 :
2781 : // Bijection between registers and array indices must match that used in
2782 : // InterpreterAssembler::ExportRegisterFile.
2783 41435 : for (int i = 0; i < register_count; ++i) {
2784 36297 : Node* value = NewNode(javascript()->GeneratorRestoreRegister(i), generator);
2785 36297 : environment()->BindRegister(interpreter::Register(i), value);
2786 : }
2787 5138 : }
2788 :
2789 0 : void BytecodeGraphBuilder::VisitWide() {
2790 : // Consumed by the BytecodeArrayIterator.
2791 0 : UNREACHABLE();
2792 : }
2793 :
2794 0 : void BytecodeGraphBuilder::VisitExtraWide() {
2795 : // Consumed by the BytecodeArrayIterator.
2796 0 : UNREACHABLE();
2797 : }
2798 :
2799 0 : void BytecodeGraphBuilder::VisitIllegal() {
2800 : // Not emitted in valid bytecode.
2801 0 : UNREACHABLE();
2802 : }
2803 :
2804 16878958 : void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) {
2805 : auto it = merge_environments_.find(current_offset);
2806 16070973 : if (it != merge_environments_.end()) {
2807 : mark_as_needing_eager_checkpoint(true);
2808 493096 : if (environment() != nullptr) {
2809 : it->second->Merge(environment(),
2810 472335 : bytecode_analysis()->GetInLivenessFor(current_offset));
2811 : }
2812 493096 : set_environment(it->second);
2813 : }
2814 16070973 : }
2815 :
2816 28173420 : void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) {
2817 27995608 : if (bytecode_analysis()->IsLoopHeader(current_offset)) {
2818 : mark_as_needing_eager_checkpoint(true);
2819 : const LoopInfo& loop_info =
2820 88906 : bytecode_analysis()->GetLoopInfoFor(current_offset);
2821 : const BytecodeLivenessState* liveness =
2822 88906 : bytecode_analysis()->GetInLivenessFor(current_offset);
2823 :
2824 : // Add loop header.
2825 88906 : environment()->PrepareForLoop(loop_info.assignments(), liveness);
2826 :
2827 : // Store a copy of the environment so we can connect merged back edge inputs
2828 : // to the loop header.
2829 88906 : merge_environments_[current_offset] = environment()->Copy();
2830 : }
2831 13997807 : }
2832 :
2833 1755392 : void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) {
2834 749496 : BuildLoopExitsForBranch(target_offset);
2835 749495 : Environment*& merge_environment = merge_environments_[target_offset];
2836 :
2837 749496 : if (merge_environment == nullptr) {
2838 : // Append merge nodes to the environment. We may merge here with another
2839 : // environment. So add a place holder for merge nodes. We may add redundant
2840 : // but will be eliminated in a later pass.
2841 : // TODO(mstarzinger): Be smarter about this!
2842 493096 : NewMerge();
2843 493096 : merge_environment = environment();
2844 : } else {
2845 : // Merge any values which are live coming into the successor.
2846 : merge_environment->Merge(
2847 769200 : environment(), bytecode_analysis()->GetInLivenessFor(target_offset));
2848 : }
2849 : set_environment(nullptr);
2850 749496 : }
2851 :
2852 0 : void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) {
2853 766482 : exit_controls_.push_back(exit);
2854 : set_environment(nullptr);
2855 0 : }
2856 :
2857 2164036 : void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) {
2858 749496 : int origin_offset = bytecode_iterator().current_offset();
2859 : // Only build loop exits for forward edges.
2860 749496 : if (target_offset > origin_offset) {
2861 : BuildLoopExitsUntilLoop(
2862 : bytecode_analysis()->GetLoopOffsetFor(target_offset),
2863 1414540 : bytecode_analysis()->GetInLivenessFor(target_offset));
2864 : }
2865 749495 : }
2866 :
2867 1354269 : void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(
2868 2960168 : int loop_offset, const BytecodeLivenessState* liveness) {
2869 1354269 : int origin_offset = bytecode_iterator().current_offset();
2870 1354269 : int current_loop = bytecode_analysis()->GetLoopOffsetFor(origin_offset);
2871 : // The limit_offset is the stop offset for building loop exists, used for OSR.
2872 : // It prevents the creations of loopexits for loops which do not exist.
2873 2708536 : loop_offset = std::max(loop_offset, currently_peeled_loop_offset_);
2874 :
2875 2834351 : while (loop_offset < current_loop) {
2876 125815 : Node* loop_node = merge_environments_[current_loop]->GetControlDependency();
2877 125815 : const LoopInfo& loop_info =
2878 251630 : bytecode_analysis()->GetLoopInfoFor(current_loop);
2879 125815 : environment()->PrepareForLoopExit(loop_node, loop_info.assignments(),
2880 125815 : liveness);
2881 125815 : current_loop = loop_info.parent_offset();
2882 : }
2883 1354268 : }
2884 :
2885 0 : void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit(
2886 : const BytecodeLivenessState* liveness) {
2887 647000 : BuildLoopExitsUntilLoop(-1, liveness);
2888 0 : }
2889 :
2890 131102 : void BytecodeGraphBuilder::BuildJump() {
2891 131102 : MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
2892 131102 : }
2893 :
2894 113962 : void BytecodeGraphBuilder::BuildJumpIf(Node* condition) {
2895 56981 : NewBranch(condition);
2896 : {
2897 : SubEnvironment sub_environment(this);
2898 56981 : NewIfTrue();
2899 56981 : MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
2900 : }
2901 56981 : NewIfFalse();
2902 56981 : }
2903 :
2904 141468 : void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) {
2905 70734 : NewBranch(condition);
2906 : {
2907 : SubEnvironment sub_environment(this);
2908 70734 : NewIfFalse();
2909 70734 : MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
2910 : }
2911 70734 : NewIfTrue();
2912 70734 : }
2913 :
2914 25100 : void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
2915 12550 : Node* accumulator = environment()->LookupAccumulator();
2916 : Node* condition =
2917 12550 : NewNode(simplified()->ReferenceEqual(), accumulator, comperand);
2918 12550 : BuildJumpIf(condition);
2919 12550 : }
2920 :
2921 28580 : void BytecodeGraphBuilder::BuildJumpIfNotEqual(Node* comperand) {
2922 14290 : Node* accumulator = environment()->LookupAccumulator();
2923 : Node* condition =
2924 14290 : NewNode(simplified()->ReferenceEqual(), accumulator, comperand);
2925 14290 : BuildJumpIfNot(condition);
2926 14290 : }
2927 :
2928 1301796 : void BytecodeGraphBuilder::BuildJumpIfFalse() {
2929 216966 : NewBranch(environment()->LookupAccumulator());
2930 : {
2931 : SubEnvironment sub_environment(this);
2932 216966 : NewIfFalse();
2933 433932 : environment()->BindAccumulator(jsgraph()->FalseConstant());
2934 216966 : MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
2935 : }
2936 216966 : NewIfTrue();
2937 433932 : environment()->BindAccumulator(jsgraph()->TrueConstant());
2938 216966 : }
2939 :
2940 514044 : void BytecodeGraphBuilder::BuildJumpIfTrue() {
2941 85674 : NewBranch(environment()->LookupAccumulator());
2942 : {
2943 : SubEnvironment sub_environment(this);
2944 85674 : NewIfTrue();
2945 171348 : environment()->BindAccumulator(jsgraph()->TrueConstant());
2946 85674 : MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
2947 : }
2948 85674 : NewIfFalse();
2949 171348 : environment()->BindAccumulator(jsgraph()->FalseConstant());
2950 85674 : }
2951 :
2952 80352 : void BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() {
2953 40176 : Node* accumulator = environment()->LookupAccumulator();
2954 : Node* condition =
2955 80352 : NewNode(simplified()->ToBoolean(ToBooleanHint::kAny), accumulator);
2956 40176 : BuildJumpIf(condition);
2957 40176 : }
2958 :
2959 112888 : void BytecodeGraphBuilder::BuildJumpIfToBooleanFalse() {
2960 56444 : Node* accumulator = environment()->LookupAccumulator();
2961 : Node* condition =
2962 112888 : NewNode(simplified()->ToBoolean(ToBooleanHint::kAny), accumulator);
2963 56444 : BuildJumpIfNot(condition);
2964 56444 : }
2965 :
2966 0 : void BytecodeGraphBuilder::BuildJumpIfNotHole() {
2967 0 : Node* accumulator = environment()->LookupAccumulator();
2968 : Node* condition = NewNode(simplified()->ReferenceEqual(), accumulator,
2969 0 : jsgraph()->TheHoleConstant());
2970 0 : BuildJumpIfNot(condition);
2971 0 : }
2972 :
2973 8510 : void BytecodeGraphBuilder::BuildJumpIfJSReceiver() {
2974 4255 : Node* accumulator = environment()->LookupAccumulator();
2975 4255 : Node* condition = NewNode(simplified()->ObjectIsReceiver(), accumulator);
2976 4255 : BuildJumpIf(condition);
2977 4255 : }
2978 :
2979 : JSTypeHintLowering::LoweringResult
2980 737452 : BytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op, Node* left,
2981 : Node* right,
2982 737452 : FeedbackSlot slot) {
2983 737452 : Node* effect = environment()->GetEffectDependency();
2984 737452 : Node* control = environment()->GetControlDependency();
2985 : JSTypeHintLowering::LoweringResult result =
2986 737452 : type_hint_lowering().ReduceBinaryOperation(op, left, right, effect,
2987 737452 : control, slot);
2988 737452 : ApplyEarlyReduction(result);
2989 737452 : return result;
2990 : }
2991 :
2992 : JSTypeHintLowering::LoweringResult
2993 1710 : BytecodeGraphBuilder::TryBuildSimplifiedForInNext(Node* receiver,
2994 : Node* cache_array,
2995 : Node* cache_type, Node* index,
2996 1710 : FeedbackSlot slot) {
2997 1710 : Node* effect = environment()->GetEffectDependency();
2998 1710 : Node* control = environment()->GetControlDependency();
2999 : JSTypeHintLowering::LoweringResult result =
3000 1710 : type_hint_lowering().ReduceForInNextOperation(
3001 1710 : receiver, cache_array, cache_type, index, effect, control, slot);
3002 1710 : ApplyEarlyReduction(result);
3003 1710 : return result;
3004 : }
3005 :
3006 : JSTypeHintLowering::LoweringResult
3007 1548 : BytecodeGraphBuilder::TryBuildSimplifiedForInPrepare(Node* enumerator,
3008 1548 : FeedbackSlot slot) {
3009 1548 : Node* effect = environment()->GetEffectDependency();
3010 1548 : Node* control = environment()->GetControlDependency();
3011 : JSTypeHintLowering::LoweringResult result =
3012 1548 : type_hint_lowering().ReduceForInPrepareOperation(enumerator, effect,
3013 1548 : control, slot);
3014 1548 : ApplyEarlyReduction(result);
3015 1548 : return result;
3016 : }
3017 :
3018 : JSTypeHintLowering::LoweringResult
3019 31388 : BytecodeGraphBuilder::TryBuildSimplifiedToNumber(Node* value,
3020 31388 : FeedbackSlot slot) {
3021 31388 : Node* effect = environment()->GetEffectDependency();
3022 31388 : Node* control = environment()->GetControlDependency();
3023 : JSTypeHintLowering::LoweringResult result =
3024 31388 : type_hint_lowering().ReduceToNumberOperation(value, effect, control,
3025 31388 : slot);
3026 31388 : ApplyEarlyReduction(result);
3027 31388 : return result;
3028 : }
3029 :
3030 581777 : JSTypeHintLowering::LoweringResult BytecodeGraphBuilder::TryBuildSimplifiedCall(
3031 581777 : const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot) {
3032 581777 : Node* effect = environment()->GetEffectDependency();
3033 581777 : Node* control = environment()->GetControlDependency();
3034 : JSTypeHintLowering::LoweringResult result =
3035 581777 : type_hint_lowering().ReduceCallOperation(op, args, arg_count, effect,
3036 581777 : control, slot);
3037 581776 : ApplyEarlyReduction(result);
3038 581777 : return result;
3039 : }
3040 :
3041 : JSTypeHintLowering::LoweringResult
3042 38495 : BytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op,
3043 : Node* const* args,
3044 : int arg_count,
3045 38495 : FeedbackSlot slot) {
3046 38495 : Node* effect = environment()->GetEffectDependency();
3047 38495 : Node* control = environment()->GetControlDependency();
3048 : JSTypeHintLowering::LoweringResult result =
3049 38495 : type_hint_lowering().ReduceConstructOperation(op, args, arg_count, effect,
3050 38495 : control, slot);
3051 38495 : ApplyEarlyReduction(result);
3052 38495 : return result;
3053 : }
3054 :
3055 : JSTypeHintLowering::LoweringResult
3056 598905 : BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op,
3057 : Node* receiver,
3058 598905 : FeedbackSlot slot) {
3059 598905 : Node* effect = environment()->GetEffectDependency();
3060 598905 : Node* control = environment()->GetControlDependency();
3061 : JSTypeHintLowering::LoweringResult early_reduction =
3062 598905 : type_hint_lowering().ReduceLoadNamedOperation(op, receiver, effect,
3063 598905 : control, slot);
3064 598905 : ApplyEarlyReduction(early_reduction);
3065 598905 : return early_reduction;
3066 : }
3067 :
3068 : JSTypeHintLowering::LoweringResult
3069 55016 : BytecodeGraphBuilder::TryBuildSimplifiedLoadKeyed(const Operator* op,
3070 : Node* receiver, Node* key,
3071 55016 : FeedbackSlot slot) {
3072 55016 : Node* effect = environment()->GetEffectDependency();
3073 55016 : Node* control = environment()->GetControlDependency();
3074 : JSTypeHintLowering::LoweringResult result =
3075 55016 : type_hint_lowering().ReduceLoadKeyedOperation(op, receiver, key, effect,
3076 55016 : control, slot);
3077 55016 : ApplyEarlyReduction(result);
3078 55016 : return result;
3079 : }
3080 :
3081 : JSTypeHintLowering::LoweringResult
3082 310724 : BytecodeGraphBuilder::TryBuildSimplifiedStoreNamed(const Operator* op,
3083 : Node* receiver, Node* value,
3084 310724 : FeedbackSlot slot) {
3085 310724 : Node* effect = environment()->GetEffectDependency();
3086 310724 : Node* control = environment()->GetControlDependency();
3087 : JSTypeHintLowering::LoweringResult result =
3088 310724 : type_hint_lowering().ReduceStoreNamedOperation(op, receiver, value,
3089 310724 : effect, control, slot);
3090 310724 : ApplyEarlyReduction(result);
3091 310724 : return result;
3092 : }
3093 :
3094 : JSTypeHintLowering::LoweringResult
3095 63175 : BytecodeGraphBuilder::TryBuildSimplifiedStoreKeyed(const Operator* op,
3096 : Node* receiver, Node* key,
3097 : Node* value,
3098 63175 : FeedbackSlot slot) {
3099 63175 : Node* effect = environment()->GetEffectDependency();
3100 63175 : Node* control = environment()->GetControlDependency();
3101 : JSTypeHintLowering::LoweringResult result =
3102 63175 : type_hint_lowering().ReduceStoreKeyedOperation(op, receiver, key, value,
3103 63175 : effect, control, slot);
3104 63175 : ApplyEarlyReduction(result);
3105 63175 : return result;
3106 : }
3107 :
3108 2420187 : void BytecodeGraphBuilder::ApplyEarlyReduction(
3109 703036 : JSTypeHintLowering::LoweringResult reduction) {
3110 2420187 : if (reduction.IsExit()) {
3111 : MergeControlToLeaveFunction(reduction.control());
3112 2357729 : } else if (reduction.IsSideEffectFree()) {
3113 351518 : environment()->UpdateEffectDependency(reduction.effect());
3114 : environment()->UpdateControlDependency(reduction.control());
3115 : } else {
3116 : DCHECK(!reduction.Changed());
3117 : // At the moment, we assume side-effect free reduction. To support
3118 : // side-effects, we would have to invalidate the eager checkpoint,
3119 : // so that deoptimization does not repeat the side effect.
3120 : }
3121 2420187 : }
3122 :
3123 13099922 : Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
3124 12594955 : if (size > input_buffer_size_) {
3125 504967 : size = size + kInputBufferSizeIncrement + input_buffer_size_;
3126 1009935 : input_buffer_ = local_zone()->NewArray<Node*>(size);
3127 504968 : input_buffer_size_ = size;
3128 : }
3129 12594956 : return input_buffer_;
3130 : }
3131 :
3132 16077654 : void BytecodeGraphBuilder::ExitThenEnterExceptionHandlers(int current_offset) {
3133 16077654 : Handle<HandlerTable> table = exception_handler_table();
3134 : int num_entries = table->NumberOfRangeEntries();
3135 :
3136 : // Potentially exit exception handlers.
3137 32181957 : while (!exception_handlers_.empty()) {
3138 644403 : int current_end = exception_handlers_.top().end_offset_;
3139 644403 : if (current_offset < current_end) break; // Still covered by range.
3140 : exception_handlers_.pop();
3141 : }
3142 :
3143 : // Potentially enter exception handlers.
3144 16104303 : while (current_exception_handler_ < num_entries) {
3145 : int next_start = table->GetRangeStart(current_exception_handler_);
3146 988743 : if (current_offset < next_start) break; // Not yet covered by range.
3147 53298 : int next_end = table->GetRangeEnd(current_exception_handler_);
3148 53298 : int next_handler = table->GetRangeHandler(current_exception_handler_);
3149 53298 : int context_register = table->GetRangeData(current_exception_handler_);
3150 : exception_handlers_.push(
3151 53298 : {next_start, next_end, next_handler, context_register});
3152 26649 : current_exception_handler_++;
3153 : }
3154 16077654 : }
3155 :
3156 38164114 : Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
3157 : Node* const* value_inputs,
3158 63422657 : bool incomplete) {
3159 : DCHECK_EQ(op->ValueInputCount(), value_input_count);
3160 :
3161 12721376 : bool has_context = OperatorProperties::HasContextInput(op);
3162 12721373 : bool has_frame_state = OperatorProperties::HasFrameStateInput(op);
3163 12721369 : bool has_control = op->ControlInputCount() == 1;
3164 12721369 : bool has_effect = op->EffectInputCount() == 1;
3165 :
3166 : DCHECK_LT(op->ControlInputCount(), 2);
3167 : DCHECK_LT(op->EffectInputCount(), 2);
3168 :
3169 57204870 : Node* result = nullptr;
3170 12721369 : if (!has_context && !has_frame_state && !has_control && !has_effect) {
3171 1593528 : result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
3172 : } else {
3173 11924605 : bool inside_handler = !exception_handlers_.empty();
3174 : int input_count_with_deps = value_input_count;
3175 11924605 : if (has_context) ++input_count_with_deps;
3176 11924605 : if (has_frame_state) ++input_count_with_deps;
3177 11924605 : if (has_control) ++input_count_with_deps;
3178 11924605 : if (has_effect) ++input_count_with_deps;
3179 11924605 : Node** buffer = EnsureInputBufferSize(input_count_with_deps);
3180 11924602 : memcpy(buffer, value_inputs, kPointerSize * value_input_count);
3181 11924602 : Node** current_input = buffer + value_input_count;
3182 11924602 : if (has_context) {
3183 10994842 : *current_input++ = environment()->Context();
3184 : }
3185 11924602 : if (has_frame_state) {
3186 : // The frame state will be inserted later. Here we misuse the {Dead} node
3187 : // as a sentinel to be later overwritten with the real frame state by the
3188 : // calls to {PrepareFrameState} within individual visitor methods.
3189 13706618 : *current_input++ = jsgraph()->Dead();
3190 : }
3191 11924602 : if (has_effect) {
3192 19012776 : *current_input++ = environment()->GetEffectDependency();
3193 : }
3194 11924602 : if (has_control) {
3195 11303944 : *current_input++ = environment()->GetControlDependency();
3196 : }
3197 23849204 : result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
3198 : // Update the current control dependency for control-producing nodes.
3199 23849236 : if (result->op()->ControlOutputCount() > 0) {
3200 : environment()->UpdateControlDependency(result);
3201 : }
3202 : // Update the current effect dependency for effect-producing nodes.
3203 23849236 : if (result->op()->EffectOutputCount() > 0) {
3204 : environment()->UpdateEffectDependency(result);
3205 : }
3206 : // Add implicit exception continuation for throwing nodes.
3207 11924618 : if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
3208 171941 : int handler_offset = exception_handlers_.top().handler_offset_;
3209 171941 : int context_index = exception_handlers_.top().context_register_;
3210 : interpreter::Register context_register(context_index);
3211 171941 : Environment* success_env = environment()->Copy();
3212 171939 : const Operator* op = common()->IfException();
3213 171940 : Node* effect = environment()->GetEffectDependency();
3214 : Node* on_exception = graph()->NewNode(op, effect, result);
3215 171941 : Node* context = environment()->LookupRegister(context_register);
3216 : environment()->UpdateControlDependency(on_exception);
3217 : environment()->UpdateEffectDependency(on_exception);
3218 171941 : environment()->BindAccumulator(on_exception);
3219 : environment()->SetContext(context);
3220 171941 : MergeIntoSuccessorEnvironment(handler_offset);
3221 : set_environment(success_env);
3222 : }
3223 : // Add implicit success continuation for throwing nodes.
3224 11924618 : if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) {
3225 171941 : const Operator* if_success = common()->IfSuccess();
3226 : Node* on_success = graph()->NewNode(if_success, result);
3227 : environment()->UpdateControlDependency(on_success);
3228 : }
3229 : // Ensure checkpoints are created after operations with side-effects.
3230 21431016 : if (has_effect && !result->op()->HasProperty(Operator::kNoWrite)) {
3231 : mark_as_needing_eager_checkpoint(true);
3232 : }
3233 : }
3234 :
3235 12721384 : return result;
3236 : }
3237 :
3238 :
3239 772384 : Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) {
3240 386192 : const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
3241 386192 : Node** buffer = EnsureInputBufferSize(count + 1);
3242 : MemsetPointer(buffer, input, count);
3243 386192 : buffer[count] = control;
3244 386192 : return graph()->NewNode(phi_op, count + 1, buffer, true);
3245 : }
3246 :
3247 284163 : Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input,
3248 568326 : Node* control) {
3249 284163 : const Operator* phi_op = common()->EffectPhi(count);
3250 284163 : Node** buffer = EnsureInputBufferSize(count + 1);
3251 : MemsetPointer(buffer, input, count);
3252 284163 : buffer[count] = control;
3253 284163 : return graph()->NewNode(phi_op, count + 1, buffer, true);
3254 : }
3255 :
3256 :
3257 969204 : Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
3258 969204 : int inputs = control->op()->ControlInputCount() + 1;
3259 484602 : if (control->opcode() == IrOpcode::kLoop) {
3260 : // Control node for loop exists, add input.
3261 42226 : const Operator* op = common()->Loop(inputs);
3262 42226 : control->AppendInput(graph_zone(), other);
3263 42226 : NodeProperties::ChangeOp(control, op);
3264 442376 : } else if (control->opcode() == IrOpcode::kMerge) {
3265 : // Control node for merge exists, add input.
3266 442376 : const Operator* op = common()->Merge(inputs);
3267 442376 : control->AppendInput(graph_zone(), other);
3268 442376 : NodeProperties::ChangeOp(control, op);
3269 : } else {
3270 : // Control node is a singleton, introduce a merge.
3271 0 : const Operator* op = common()->Merge(inputs);
3272 0 : Node* merge_inputs[] = {control, other};
3273 0 : control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true);
3274 : }
3275 484602 : return control;
3276 : }
3277 :
3278 969204 : Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
3279 697889 : Node* control) {
3280 484602 : int inputs = control->op()->ControlInputCount();
3281 705267 : if (value->opcode() == IrOpcode::kEffectPhi &&
3282 220665 : NodeProperties::GetControlInput(value) == control) {
3283 : // Phi already exists, add input.
3284 426574 : value->InsertInput(graph_zone(), inputs - 1, other);
3285 213287 : NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
3286 271315 : } else if (value != other) {
3287 : // Phi does not exist yet, introduce one.
3288 239710 : value = NewEffectPhi(inputs, value, control);
3289 239710 : value->ReplaceInput(inputs - 1, other);
3290 : }
3291 484602 : return value;
3292 : }
3293 :
3294 6993926 : Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
3295 3984286 : Node* control) {
3296 3496963 : int inputs = control->op()->ControlInputCount();
3297 4735485 : if (value->opcode() == IrOpcode::kPhi &&
3298 1238522 : NodeProperties::GetControlInput(value) == control) {
3299 : // Phi already exists, add input.
3300 974646 : value->InsertInput(graph_zone(), inputs - 1, other);
3301 : NodeProperties::ChangeOp(
3302 487323 : value, common()->Phi(MachineRepresentation::kTagged, inputs));
3303 3009640 : } else if (value != other) {
3304 : // Phi does not exist yet, introduce one.
3305 261075 : value = NewPhi(inputs, value, control);
3306 261075 : value->ReplaceInput(inputs - 1, other);
3307 : }
3308 3496963 : return value;
3309 : }
3310 :
3311 36663272 : void BytecodeGraphBuilder::UpdateSourcePosition(SourcePositionTableIterator* it,
3312 : int offset) {
3313 32354601 : if (it->done()) return;
3314 14320414 : if (it->code_offset() == offset) {
3315 : source_positions_->SetCurrentPosition(SourcePosition(
3316 6165559 : it->source_position().ScriptOffset(), start_position_.InliningId()));
3317 6165559 : it->Advance();
3318 : } else {
3319 : DCHECK_GT(it->code_offset(), offset);
3320 : }
3321 : }
3322 :
3323 : } // namespace compiler
3324 : } // namespace internal
3325 : } // namespace v8
|