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