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/compilation-info.h" 10 #include "src/compiler/compiler-source-position-table.h" 11 #include "src/compiler/js-type-hint-lowering.h" 12 #include "src/compiler/linkage.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/literal-objects.h" 18 19 namespace v8 { 20 namespace internal { 21 namespace compiler { 22 23 // The abstract execution environment simulates the content of the interpreter 24 // register file. The environment performs SSA-renaming of all tracked nodes at 25 // split and merge points in the control flow. 26 class BytecodeGraphBuilder::Environment : public ZoneObject { 27 public: 28 Environment(BytecodeGraphBuilder* builder, int register_count, 29 int parameter_count, Node* control_dependency, Node* context); 30 31 // Specifies whether environment binding methods should attach frame state 32 // inputs to nodes representing the value being bound. This is done because 33 // the {OutputFrameStateCombine} is closely related to the binding method. 34 enum FrameStateAttachmentMode { kAttachFrameState, kDontAttachFrameState }; 35 36 int parameter_count() const { return parameter_count_; } 37 int register_count() const { return register_count_; } 38 39 Node* LookupAccumulator() const; 40 Node* LookupRegister(interpreter::Register the_register) const; 41 42 void BindAccumulator(Node* node, 43 FrameStateAttachmentMode mode = kDontAttachFrameState); 44 void BindRegister(interpreter::Register the_register, Node* node, 45 FrameStateAttachmentMode mode = kDontAttachFrameState); 46 void BindRegistersToProjections( 47 interpreter::Register first_reg, Node* node, 48 FrameStateAttachmentMode mode = kDontAttachFrameState); 49 void RecordAfterState(Node* node, 50 FrameStateAttachmentMode mode = kDontAttachFrameState); 51 52 // Effect dependency tracked by this environment. 53 Node* GetEffectDependency() { return effect_dependency_; } 54 void UpdateEffectDependency(Node* dependency) { 55 effect_dependency_ = dependency; 56 } 57 58 // Preserve a checkpoint of the environment for the IR graph. Any 59 // further mutation of the environment will not affect checkpoints. 60 Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine, 61 bool owner_has_exception, 62 const BytecodeLivenessState* liveness); 63 64 // Control dependency tracked by this environment. 65 Node* GetControlDependency() const { return control_dependency_; } 66 void UpdateControlDependency(Node* dependency) { 67 control_dependency_ = dependency; 68 } 69 70 Node* Context() const { return context_; } 71 void SetContext(Node* new_context) { context_ = new_context; } 72 73 Environment* Copy(); 74 void Merge(Environment* other); 75 76 void PrepareForOsrEntry(); 77 void PrepareForLoop(const BytecodeLoopAssignments& assignments); 78 void PrepareForLoopExit(Node* loop, 79 const BytecodeLoopAssignments& assignments); 80 81 private: 82 explicit Environment(const Environment* copy); 83 84 bool StateValuesRequireUpdate(Node** state_values, Node** values, int count); 85 void UpdateStateValues(Node** state_values, Node** values, int count); 86 void UpdateStateValuesWithCache(Node** state_values, Node** values, int count, 87 const BitVector* liveness, 88 int liveness_offset); 89 90 int RegisterToValuesIndex(interpreter::Register the_register) const; 91 92 Zone* zone() const { return builder_->local_zone(); } 93 Graph* graph() const { return builder_->graph(); } 94 CommonOperatorBuilder* common() const { return builder_->common(); } 95 BytecodeGraphBuilder* builder() const { return builder_; } 96 const NodeVector* values() const { return &values_; } 97 NodeVector* values() { return &values_; } 98 int register_base() const { return register_base_; } 99 int accumulator_base() const { return accumulator_base_; } 100 101 BytecodeGraphBuilder* builder_; 102 int register_count_; 103 int parameter_count_; 104 Node* context_; 105 Node* control_dependency_; 106 Node* effect_dependency_; 107 NodeVector values_; 108 Node* parameters_state_values_; 109 Node* registers_state_values_; 110 Node* accumulator_state_values_; 111 int register_base_; 112 int accumulator_base_; 113 }; 114 115 116 // Issues: 117 // - Scopes - intimately tied to AST. Need to eval what is needed. 118 // - Need to resolve closure parameter treatment. 119 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder, 120 int register_count, 121 int parameter_count, 122 Node* control_dependency, 123 Node* context) 124 : builder_(builder), 125 register_count_(register_count), 126 parameter_count_(parameter_count), 127 context_(context), 128 control_dependency_(control_dependency), 129 effect_dependency_(control_dependency), 130 values_(builder->local_zone()), 131 parameters_state_values_(nullptr), 132 registers_state_values_(nullptr), 133 accumulator_state_values_(nullptr) { 134 // The layout of values_ is: 135 // 136 // [receiver] [parameters] [registers] [accumulator] 137 // 138 // parameter[0] is the receiver (this), parameters 1..N are the 139 // parameters supplied to the method (arg0..argN-1). The accumulator 140 // is stored separately. 141 142 // Parameters including the receiver 143 for (int i = 0; i < parameter_count; i++) { 144 const char* debug_name = (i == 0) ? "%this" : nullptr; 145 const Operator* op = common()->Parameter(i, debug_name); 146 Node* parameter = builder->graph()->NewNode(op, graph()->start()); 147 values()->push_back(parameter); 148 } 149 150 // Registers 151 register_base_ = static_cast<int>(values()->size()); 152 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); 153 values()->insert(values()->end(), register_count, undefined_constant); 154 155 // Accumulator 156 accumulator_base_ = static_cast<int>(values()->size()); 157 values()->push_back(undefined_constant); 158 } 159 160 BytecodeGraphBuilder::Environment::Environment( 161 const BytecodeGraphBuilder::Environment* other) 162 : builder_(other->builder_), 163 register_count_(other->register_count_), 164 parameter_count_(other->parameter_count_), 165 context_(other->context_), 166 control_dependency_(other->control_dependency_), 167 effect_dependency_(other->effect_dependency_), 168 values_(other->zone()), 169 parameters_state_values_(nullptr), 170 registers_state_values_(nullptr), 171 accumulator_state_values_(nullptr), 172 register_base_(other->register_base_), 173 accumulator_base_(other->accumulator_base_) { 174 values_ = other->values_; 175 } 176 177 178 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( 179 interpreter::Register the_register) const { 180 if (the_register.is_parameter()) { 181 return the_register.ToParameterIndex(parameter_count()); 182 } else { 183 return the_register.index() + register_base(); 184 } 185 } 186 187 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { 188 return values()->at(accumulator_base_); 189 } 190 191 192 Node* BytecodeGraphBuilder::Environment::LookupRegister( 193 interpreter::Register the_register) const { 194 if (the_register.is_current_context()) { 195 return Context(); 196 } else if (the_register.is_function_closure()) { 197 return builder()->GetFunctionClosure(); 198 } else if (the_register.is_new_target()) { 199 return builder()->GetNewTarget(); 200 } else { 201 int values_index = RegisterToValuesIndex(the_register); 202 return values()->at(values_index); 203 } 204 } 205 206 void BytecodeGraphBuilder::Environment::BindAccumulator( 207 Node* node, FrameStateAttachmentMode mode) { 208 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 209 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0)); 210 } 211 values()->at(accumulator_base_) = node; 212 } 213 214 void BytecodeGraphBuilder::Environment::BindRegister( 215 interpreter::Register the_register, Node* node, 216 FrameStateAttachmentMode mode) { 217 int values_index = RegisterToValuesIndex(the_register); 218 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 219 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( 220 accumulator_base_ - values_index)); 221 } 222 values()->at(values_index) = node; 223 } 224 225 void BytecodeGraphBuilder::Environment::BindRegistersToProjections( 226 interpreter::Register first_reg, Node* node, 227 FrameStateAttachmentMode mode) { 228 int values_index = RegisterToValuesIndex(first_reg); 229 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 230 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( 231 accumulator_base_ - values_index)); 232 } 233 for (int i = 0; i < node->op()->ValueOutputCount(); i++) { 234 values()->at(values_index + i) = 235 builder()->NewNode(common()->Projection(i), node); 236 } 237 } 238 239 void BytecodeGraphBuilder::Environment::RecordAfterState( 240 Node* node, FrameStateAttachmentMode mode) { 241 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 242 builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore()); 243 } 244 } 245 246 BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::Environment::Copy() { 247 return new (zone()) Environment(this); 248 } 249 250 251 void BytecodeGraphBuilder::Environment::Merge( 252 BytecodeGraphBuilder::Environment* other) { 253 // Create a merge of the control dependencies of both environments and update 254 // the current environment's control dependency accordingly. 255 Node* control = builder()->MergeControl(GetControlDependency(), 256 other->GetControlDependency()); 257 UpdateControlDependency(control); 258 259 // Create a merge of the effect dependencies of both environments and update 260 // the current environment's effect dependency accordingly. 261 Node* effect = builder()->MergeEffect(GetEffectDependency(), 262 other->GetEffectDependency(), control); 263 UpdateEffectDependency(effect); 264 265 // Introduce Phi nodes for values that have differing input at merge points, 266 // potentially extending an existing Phi node if possible. 267 context_ = builder()->MergeValue(context_, other->context_, control); 268 for (size_t i = 0; i < values_.size(); i++) { 269 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control); 270 } 271 } 272 273 void BytecodeGraphBuilder::Environment::PrepareForLoop( 274 const BytecodeLoopAssignments& assignments) { 275 // Create a control node for the loop header. 276 Node* control = builder()->NewLoop(); 277 278 // Create a Phi for external effects. 279 Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control); 280 UpdateEffectDependency(effect); 281 282 // Create Phis for any values that may be updated by the end of the loop. 283 context_ = builder()->NewPhi(1, context_, control); 284 for (int i = 0; i < parameter_count(); i++) { 285 if (assignments.ContainsParameter(i)) { 286 values_[i] = builder()->NewPhi(1, values_[i], control); 287 } 288 } 289 for (int i = 0; i < register_count(); i++) { 290 if (assignments.ContainsLocal(i)) { 291 int index = register_base() + i; 292 values_[index] = builder()->NewPhi(1, values_[index], control); 293 } 294 } 295 296 if (assignments.ContainsAccumulator()) { 297 values_[accumulator_base()] = 298 builder()->NewPhi(1, values_[accumulator_base()], control); 299 } 300 301 // Connect to the loop end. 302 Node* terminate = builder()->graph()->NewNode( 303 builder()->common()->Terminate(), effect, control); 304 builder()->exit_controls_.push_back(terminate); 305 } 306 307 void BytecodeGraphBuilder::Environment::PrepareForOsrEntry() { 308 DCHECK_EQ(IrOpcode::kLoop, GetControlDependency()->opcode()); 309 DCHECK_EQ(1, GetControlDependency()->InputCount()); 310 311 Node* start = graph()->start(); 312 313 // Create a control node for the OSR entry point and update the current 314 // environment's dependencies accordingly. 315 Node* entry = graph()->NewNode(common()->OsrLoopEntry(), start, start); 316 UpdateControlDependency(entry); 317 UpdateEffectDependency(entry); 318 319 // Create OSR values for each environment value. 320 SetContext(graph()->NewNode( 321 common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), entry)); 322 int size = static_cast<int>(values()->size()); 323 for (int i = 0; i < size; i++) { 324 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. 325 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; 326 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; 327 values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry); 328 } 329 330 BailoutId loop_id(builder_->bytecode_iterator().current_offset()); 331 Node* frame_state = 332 Checkpoint(loop_id, OutputFrameStateCombine::Ignore(), false, nullptr); 333 Node* checkpoint = 334 graph()->NewNode(common()->Checkpoint(), frame_state, entry, entry); 335 UpdateEffectDependency(checkpoint); 336 337 // Create the OSR guard nodes. 338 const Operator* guard_op = common()->OsrGuard(OsrGuardType::kUninitialized); 339 Node* effect = checkpoint; 340 for (int i = 0; i < size; i++) { 341 values()->at(i) = effect = 342 graph()->NewNode(guard_op, values()->at(i), effect, entry); 343 } 344 Node* context = effect = graph()->NewNode(guard_op, Context(), effect, entry); 345 SetContext(context); 346 UpdateEffectDependency(effect); 347 } 348 349 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( 350 Node** state_values, Node** values, int count) { 351 if (*state_values == nullptr) { 352 return true; 353 } 354 Node::Inputs inputs = (*state_values)->inputs(); 355 if (inputs.count() != count) return true; 356 for (int i = 0; i < count; i++) { 357 if (inputs[i] != values[i]) { 358 return true; 359 } 360 } 361 return false; 362 } 363 364 void BytecodeGraphBuilder::Environment::PrepareForLoopExit( 365 Node* loop, const BytecodeLoopAssignments& assignments) { 366 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); 367 368 Node* control = GetControlDependency(); 369 370 // Create the loop exit node. 371 Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop); 372 UpdateControlDependency(loop_exit); 373 374 // Rename the effect. 375 Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(), 376 GetEffectDependency(), loop_exit); 377 UpdateEffectDependency(effect_rename); 378 379 // TODO(jarin) We should also rename context here. However, unconditional 380 // renaming confuses global object and native context specialization. 381 // We should only rename if the context is assigned in the loop. 382 383 // Rename the environment values if they were assigned in the loop. 384 for (int i = 0; i < parameter_count(); i++) { 385 if (assignments.ContainsParameter(i)) { 386 Node* rename = 387 graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit); 388 values_[i] = rename; 389 } 390 } 391 for (int i = 0; i < register_count(); i++) { 392 if (assignments.ContainsLocal(i)) { 393 Node* rename = graph()->NewNode(common()->LoopExitValue(), 394 values_[register_base() + i], loop_exit); 395 values_[register_base() + i] = rename; 396 } 397 } 398 399 if (assignments.ContainsAccumulator()) { 400 Node* rename = graph()->NewNode(common()->LoopExitValue(), 401 values_[accumulator_base()], loop_exit); 402 values_[accumulator_base()] = rename; 403 } 404 } 405 406 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, 407 Node** values, 408 int count) { 409 if (StateValuesRequireUpdate(state_values, values, count)) { 410 const Operator* op = common()->StateValues(count, SparseInputMask::Dense()); 411 (*state_values) = graph()->NewNode(op, count, values); 412 } 413 } 414 415 void BytecodeGraphBuilder::Environment::UpdateStateValuesWithCache( 416 Node** state_values, Node** values, int count, const BitVector* liveness, 417 int liveness_offset) { 418 *state_values = builder_->state_values_cache_.GetNodeForValues( 419 values, static_cast<size_t>(count), liveness, liveness_offset); 420 } 421 422 Node* BytecodeGraphBuilder::Environment::Checkpoint( 423 BailoutId bailout_id, OutputFrameStateCombine combine, 424 bool owner_has_exception, const BytecodeLivenessState* liveness) { 425 if (parameter_count() == register_count()) { 426 // Re-use the state-value cache if the number of local registers happens 427 // to match the parameter count. 428 UpdateStateValuesWithCache(¶meters_state_values_, &values()->at(0), 429 parameter_count(), nullptr, 0); 430 } else { 431 UpdateStateValues(¶meters_state_values_, &values()->at(0), 432 parameter_count()); 433 } 434 435 UpdateStateValuesWithCache(®isters_state_values_, 436 &values()->at(register_base()), register_count(), 437 liveness ? &liveness->bit_vector() : nullptr, 0); 438 439 bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive(); 440 if (parameter_count() == 1 && accumulator_is_live && 441 values()->at(accumulator_base()) == values()->at(0)) { 442 // Re-use the parameter state values if there happens to only be one 443 // parameter and the accumulator is live and holds that parameter's value. 444 accumulator_state_values_ = parameters_state_values_; 445 } else { 446 // Otherwise, use the state values cache to hopefully re-use local register 447 // state values (if there is only one local register), or at the very least 448 // re-use previous accumulator state values. 449 UpdateStateValuesWithCache( 450 &accumulator_state_values_, &values()->at(accumulator_base()), 1, 451 liveness ? &liveness->bit_vector() : nullptr, register_count()); 452 } 453 454 const Operator* op = common()->FrameState( 455 bailout_id, combine, builder()->frame_state_function_info()); 456 Node* result = graph()->NewNode( 457 op, parameters_state_values_, registers_state_values_, 458 accumulator_state_values_, Context(), builder()->GetFunctionClosure(), 459 builder()->graph()->start()); 460 461 return result; 462 } 463 464 BytecodeGraphBuilder::BytecodeGraphBuilder( 465 Zone* local_zone, Handle<SharedFunctionInfo> shared_info, 466 Handle<FeedbackVector> feedback_vector, BailoutId osr_ast_id, 467 JSGraph* jsgraph, float invocation_frequency, 468 SourcePositionTable* source_positions, int inlining_id) 469 : local_zone_(local_zone), 470 jsgraph_(jsgraph), 471 invocation_frequency_(invocation_frequency), 472 bytecode_array_(handle(shared_info->bytecode_array())), 473 exception_handler_table_( 474 handle(HandlerTable::cast(bytecode_array()->handler_table()))), 475 feedback_vector_(feedback_vector), 476 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( 477 FrameStateType::kInterpretedFunction, 478 bytecode_array()->parameter_count(), 479 bytecode_array()->register_count(), shared_info)), 480 bytecode_iterator_(nullptr), 481 bytecode_analysis_(nullptr), 482 environment_(nullptr), 483 osr_ast_id_(osr_ast_id), 484 osr_loop_offset_(-1), 485 merge_environments_(local_zone), 486 exception_handlers_(local_zone), 487 current_exception_handler_(0), 488 input_buffer_size_(0), 489 input_buffer_(nullptr), 490 needs_eager_checkpoint_(true), 491 exit_controls_(local_zone), 492 state_values_cache_(jsgraph), 493 source_positions_(source_positions), 494 start_position_(shared_info->start_position(), inlining_id) {} 495 496 Node* BytecodeGraphBuilder::GetNewTarget() { 497 if (!new_target_.is_set()) { 498 int params = bytecode_array()->parameter_count(); 499 int index = Linkage::GetJSCallNewTargetParamIndex(params); 500 const Operator* op = common()->Parameter(index, "%new.target"); 501 Node* node = NewNode(op, graph()->start()); 502 new_target_.set(node); 503 } 504 return new_target_.get(); 505 } 506 507 508 Node* BytecodeGraphBuilder::GetFunctionContext() { 509 if (!function_context_.is_set()) { 510 int params = bytecode_array()->parameter_count(); 511 int index = Linkage::GetJSCallContextParamIndex(params); 512 const Operator* op = common()->Parameter(index, "%context"); 513 Node* node = NewNode(op, graph()->start()); 514 function_context_.set(node); 515 } 516 return function_context_.get(); 517 } 518 519 520 Node* BytecodeGraphBuilder::GetFunctionClosure() { 521 if (!function_closure_.is_set()) { 522 int index = Linkage::kJSCallClosureParamIndex; 523 const Operator* op = common()->Parameter(index, "%closure"); 524 Node* node = NewNode(op, graph()->start()); 525 function_closure_.set(node); 526 } 527 return function_closure_.get(); 528 } 529 530 531 Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) { 532 const Operator* op = 533 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true); 534 Node* native_context = NewNode(op); 535 Node* result = NewNode(javascript()->LoadContext(0, index, true)); 536 NodeProperties::ReplaceContextInput(result, native_context); 537 return result; 538 } 539 540 541 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { 542 FeedbackSlot slot; 543 if (slot_id >= FeedbackVector::kReservedIndexCount) { 544 slot = feedback_vector()->ToSlot(slot_id); 545 } 546 return VectorSlotPair(feedback_vector(), slot); 547 } 548 549 bool BytecodeGraphBuilder::CreateGraph(bool stack_check) { 550 SourcePositionTable::Scope pos_scope(source_positions_, start_position_); 551 552 // Set up the basic structure of the graph. Outputs for {Start} are the formal 553 // parameters (including the receiver) plus new target, number of arguments, 554 // context and closure. 555 int actual_parameter_count = bytecode_array()->parameter_count() + 4; 556 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count))); 557 558 Environment env(this, bytecode_array()->register_count(), 559 bytecode_array()->parameter_count(), graph()->start(), 560 GetFunctionContext()); 561 set_environment(&env); 562 563 VisitBytecodes(stack_check); 564 565 // Finish the basic structure of the graph. 566 DCHECK_NE(0u, exit_controls_.size()); 567 int const input_count = static_cast<int>(exit_controls_.size()); 568 Node** const inputs = &exit_controls_.front(); 569 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); 570 graph()->SetEnd(end); 571 572 return true; 573 } 574 575 void BytecodeGraphBuilder::PrepareEagerCheckpoint() { 576 if (needs_eager_checkpoint()) { 577 // Create an explicit checkpoint node for before the operation. This only 578 // needs to happen if we aren't effect-dominated by a {Checkpoint} already. 579 mark_as_needing_eager_checkpoint(false); 580 Node* node = NewNode(common()->Checkpoint()); 581 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 582 DCHECK_EQ(IrOpcode::kDead, 583 NodeProperties::GetFrameStateInput(node)->opcode()); 584 BailoutId bailout_id(bytecode_iterator().current_offset()); 585 586 const BytecodeLivenessState* liveness_before = 587 bytecode_analysis()->GetInLivenessFor( 588 bytecode_iterator().current_offset()); 589 590 Node* frame_state_before = environment()->Checkpoint( 591 bailout_id, OutputFrameStateCombine::Ignore(), false, liveness_before); 592 NodeProperties::ReplaceFrameStateInput(node, frame_state_before); 593 #ifdef DEBUG 594 } else { 595 // In case we skipped checkpoint creation above, we must be able to find an 596 // existing checkpoint that effect-dominates the nodes about to be created. 597 // Starting a search from the current effect-dependency has to succeed. 598 Node* effect = environment()->GetEffectDependency(); 599 while (effect->opcode() != IrOpcode::kCheckpoint) { 600 DCHECK(effect->op()->HasProperty(Operator::kNoWrite)); 601 DCHECK_EQ(1, effect->op()->EffectInputCount()); 602 effect = NodeProperties::GetEffectInput(effect); 603 } 604 } 605 #else 606 } 607 #endif // DEBUG 608 } 609 610 void BytecodeGraphBuilder::PrepareFrameState(Node* node, 611 OutputFrameStateCombine combine) { 612 if (OperatorProperties::HasFrameStateInput(node->op())) { 613 // Add the frame state for after the operation. The node in question has 614 // already been created and had a {Dead} frame state input up until now. 615 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 616 DCHECK_EQ(IrOpcode::kDead, 617 NodeProperties::GetFrameStateInput(node)->opcode()); 618 BailoutId bailout_id(bytecode_iterator().current_offset()); 619 bool has_exception = NodeProperties::IsExceptionalCall(node); 620 621 const BytecodeLivenessState* liveness_after = 622 bytecode_analysis()->GetOutLivenessFor( 623 bytecode_iterator().current_offset()); 624 625 Node* frame_state_after = environment()->Checkpoint( 626 bailout_id, combine, has_exception, liveness_after); 627 NodeProperties::ReplaceFrameStateInput(node, frame_state_after); 628 } 629 } 630 631 void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) { 632 BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone(), 633 FLAG_analyze_environment_liveness); 634 bytecode_analysis.Analyze(osr_ast_id_); 635 set_bytecode_analysis(&bytecode_analysis); 636 637 interpreter::BytecodeArrayIterator iterator(bytecode_array()); 638 set_bytecode_iterator(&iterator); 639 SourcePositionTableIterator source_position_iterator( 640 bytecode_array()->source_position_table()); 641 642 if (FLAG_trace_environment_liveness) { 643 OFStream of(stdout); 644 645 bytecode_analysis.PrintLivenessTo(of); 646 } 647 648 BuildOSRNormalEntryPoint(); 649 650 for (; !iterator.done(); iterator.Advance()) { 651 int current_offset = iterator.current_offset(); 652 UpdateCurrentSourcePosition(&source_position_iterator, current_offset); 653 EnterAndExitExceptionHandlers(current_offset); 654 SwitchToMergeEnvironment(current_offset); 655 if (environment() != nullptr) { 656 BuildLoopHeaderEnvironment(current_offset); 657 658 // Skip the first stack check if stack_check is false 659 if (!stack_check && 660 iterator.current_bytecode() == interpreter::Bytecode::kStackCheck) { 661 stack_check = true; 662 continue; 663 } 664 665 switch (iterator.current_bytecode()) { 666 #define BYTECODE_CASE(name, ...) \ 667 case interpreter::Bytecode::k##name: \ 668 Visit##name(); \ 669 break; 670 BYTECODE_LIST(BYTECODE_CASE) 671 #undef BYTECODE_CODE 672 } 673 } 674 } 675 set_bytecode_analysis(nullptr); 676 set_bytecode_iterator(nullptr); 677 DCHECK(exception_handlers_.empty()); 678 } 679 680 void BytecodeGraphBuilder::VisitLdaZero() { 681 Node* node = jsgraph()->ZeroConstant(); 682 environment()->BindAccumulator(node); 683 } 684 685 void BytecodeGraphBuilder::VisitLdaSmi() { 686 Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); 687 environment()->BindAccumulator(node); 688 } 689 690 void BytecodeGraphBuilder::VisitLdaConstant() { 691 Node* node = 692 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); 693 environment()->BindAccumulator(node); 694 } 695 696 void BytecodeGraphBuilder::VisitLdaUndefined() { 697 Node* node = jsgraph()->UndefinedConstant(); 698 environment()->BindAccumulator(node); 699 } 700 701 void BytecodeGraphBuilder::VisitLdaNull() { 702 Node* node = jsgraph()->NullConstant(); 703 environment()->BindAccumulator(node); 704 } 705 706 void BytecodeGraphBuilder::VisitLdaTheHole() { 707 Node* node = jsgraph()->TheHoleConstant(); 708 environment()->BindAccumulator(node); 709 } 710 711 void BytecodeGraphBuilder::VisitLdaTrue() { 712 Node* node = jsgraph()->TrueConstant(); 713 environment()->BindAccumulator(node); 714 } 715 716 void BytecodeGraphBuilder::VisitLdaFalse() { 717 Node* node = jsgraph()->FalseConstant(); 718 environment()->BindAccumulator(node); 719 } 720 721 void BytecodeGraphBuilder::VisitLdar() { 722 Node* value = 723 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 724 environment()->BindAccumulator(value); 725 } 726 727 void BytecodeGraphBuilder::VisitStar() { 728 Node* value = environment()->LookupAccumulator(); 729 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value); 730 } 731 732 void BytecodeGraphBuilder::VisitMov() { 733 Node* value = 734 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 735 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value); 736 } 737 738 Node* BytecodeGraphBuilder::BuildLoadGlobal(Handle<Name> name, 739 uint32_t feedback_slot_index, 740 TypeofMode typeof_mode) { 741 VectorSlotPair feedback = CreateVectorSlotPair(feedback_slot_index); 742 DCHECK(IsLoadGlobalICKind(feedback_vector()->GetKind(feedback.slot()))); 743 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode); 744 return NewNode(op); 745 } 746 747 void BytecodeGraphBuilder::VisitLdaGlobal() { 748 PrepareEagerCheckpoint(); 749 Handle<Name> name = 750 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0)); 751 uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1); 752 Node* node = 753 BuildLoadGlobal(name, feedback_slot_index, TypeofMode::NOT_INSIDE_TYPEOF); 754 environment()->BindAccumulator(node, Environment::kAttachFrameState); 755 } 756 757 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() { 758 PrepareEagerCheckpoint(); 759 Handle<Name> name = 760 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0)); 761 uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1); 762 Node* node = 763 BuildLoadGlobal(name, feedback_slot_index, TypeofMode::INSIDE_TYPEOF); 764 environment()->BindAccumulator(node, Environment::kAttachFrameState); 765 } 766 767 void BytecodeGraphBuilder::BuildStoreGlobal(LanguageMode language_mode) { 768 PrepareEagerCheckpoint(); 769 Handle<Name> name = 770 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0)); 771 VectorSlotPair feedback = 772 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1)); 773 Node* value = environment()->LookupAccumulator(); 774 775 const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback); 776 Node* node = NewNode(op, value); 777 environment()->RecordAfterState(node, Environment::kAttachFrameState); 778 } 779 780 void BytecodeGraphBuilder::VisitStaGlobalSloppy() { 781 BuildStoreGlobal(LanguageMode::SLOPPY); 782 } 783 784 void BytecodeGraphBuilder::VisitStaGlobalStrict() { 785 BuildStoreGlobal(LanguageMode::STRICT); 786 } 787 788 void BytecodeGraphBuilder::VisitStaDataPropertyInLiteral() { 789 PrepareEagerCheckpoint(); 790 791 Node* object = 792 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 793 Node* name = 794 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 795 Node* value = environment()->LookupAccumulator(); 796 int flags = bytecode_iterator().GetFlagOperand(2); 797 VectorSlotPair feedback = 798 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(3)); 799 800 const Operator* op = javascript()->StoreDataPropertyInLiteral(feedback); 801 Node* node = NewNode(op, object, name, value, jsgraph()->Constant(flags)); 802 environment()->RecordAfterState(node, Environment::kAttachFrameState); 803 } 804 805 void BytecodeGraphBuilder::VisitLdaContextSlot() { 806 const Operator* op = javascript()->LoadContext( 807 bytecode_iterator().GetUnsignedImmediateOperand(2), 808 bytecode_iterator().GetIndexOperand(1), false); 809 Node* node = NewNode(op); 810 Node* context = 811 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 812 NodeProperties::ReplaceContextInput(node, context); 813 environment()->BindAccumulator(node); 814 } 815 816 void BytecodeGraphBuilder::VisitLdaImmutableContextSlot() { 817 const Operator* op = javascript()->LoadContext( 818 bytecode_iterator().GetUnsignedImmediateOperand(2), 819 bytecode_iterator().GetIndexOperand(1), true); 820 Node* node = NewNode(op); 821 Node* context = 822 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 823 NodeProperties::ReplaceContextInput(node, context); 824 environment()->BindAccumulator(node); 825 } 826 827 void BytecodeGraphBuilder::VisitLdaCurrentContextSlot() { 828 const Operator* op = javascript()->LoadContext( 829 0, bytecode_iterator().GetIndexOperand(0), false); 830 Node* node = NewNode(op); 831 environment()->BindAccumulator(node); 832 } 833 834 void BytecodeGraphBuilder::VisitLdaImmutableCurrentContextSlot() { 835 const Operator* op = javascript()->LoadContext( 836 0, bytecode_iterator().GetIndexOperand(0), true); 837 Node* node = NewNode(op); 838 environment()->BindAccumulator(node); 839 } 840 841 void BytecodeGraphBuilder::VisitStaContextSlot() { 842 const Operator* op = javascript()->StoreContext( 843 bytecode_iterator().GetUnsignedImmediateOperand(2), 844 bytecode_iterator().GetIndexOperand(1)); 845 Node* value = environment()->LookupAccumulator(); 846 Node* node = NewNode(op, value); 847 Node* context = 848 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 849 NodeProperties::ReplaceContextInput(node, context); 850 } 851 852 void BytecodeGraphBuilder::VisitStaCurrentContextSlot() { 853 const Operator* op = 854 javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(0)); 855 Node* value = environment()->LookupAccumulator(); 856 NewNode(op, value); 857 } 858 859 void BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) { 860 PrepareEagerCheckpoint(); 861 Node* name = 862 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); 863 const Operator* op = 864 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF 865 ? Runtime::kLoadLookupSlot 866 : Runtime::kLoadLookupSlotInsideTypeof); 867 Node* value = NewNode(op, name); 868 environment()->BindAccumulator(value, Environment::kAttachFrameState); 869 } 870 871 void BytecodeGraphBuilder::VisitLdaLookupSlot() { 872 BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF); 873 } 874 875 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() { 876 BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF); 877 } 878 879 BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions( 880 uint32_t depth) { 881 // Output environment where the context has an extension 882 Environment* slow_environment = nullptr; 883 884 // We only need to check up to the last-but-one depth, because the an eval in 885 // the same scope as the variable itself has no way of shadowing it. 886 for (uint32_t d = 0; d < depth; d++) { 887 Node* extension_slot = 888 NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false)); 889 890 Node* check_no_extension = 891 NewNode(simplified()->ReferenceEqual(), extension_slot, 892 jsgraph()->TheHoleConstant()); 893 894 NewBranch(check_no_extension); 895 Environment* true_environment = environment()->Copy(); 896 897 { 898 NewIfFalse(); 899 // If there is an extension, merge into the slow path. 900 if (slow_environment == nullptr) { 901 slow_environment = environment(); 902 NewMerge(); 903 } else { 904 slow_environment->Merge(environment()); 905 } 906 } 907 908 { 909 set_environment(true_environment); 910 NewIfTrue(); 911 // Do nothing on if there is no extension, eventually falling through to 912 // the fast path. 913 } 914 } 915 916 // The depth can be zero, in which case no slow-path checks are built, and the 917 // slow path environment can be null. 918 DCHECK(depth == 0 || slow_environment != nullptr); 919 920 return slow_environment; 921 } 922 923 void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) { 924 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2); 925 926 // Check if any context in the depth has an extension. 927 Environment* slow_environment = CheckContextExtensions(depth); 928 929 // Fast path, do a context load. 930 { 931 uint32_t slot_index = bytecode_iterator().GetIndexOperand(1); 932 933 const Operator* op = javascript()->LoadContext(depth, slot_index, false); 934 environment()->BindAccumulator(NewNode(op)); 935 } 936 937 // Only build the slow path if there were any slow-path checks. 938 if (slow_environment != nullptr) { 939 // Add a merge to the fast environment. 940 NewMerge(); 941 Environment* fast_environment = environment(); 942 943 // Slow path, do a runtime load lookup. 944 set_environment(slow_environment); 945 { 946 Node* name = jsgraph()->Constant( 947 bytecode_iterator().GetConstantForIndexOperand(0)); 948 949 const Operator* op = 950 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF 951 ? Runtime::kLoadLookupSlot 952 : Runtime::kLoadLookupSlotInsideTypeof); 953 Node* value = NewNode(op, name); 954 environment()->BindAccumulator(value, Environment::kAttachFrameState); 955 } 956 957 fast_environment->Merge(environment()); 958 set_environment(fast_environment); 959 mark_as_needing_eager_checkpoint(true); 960 } 961 } 962 963 void BytecodeGraphBuilder::VisitLdaLookupContextSlot() { 964 BuildLdaLookupContextSlot(TypeofMode::NOT_INSIDE_TYPEOF); 965 } 966 967 void BytecodeGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() { 968 BuildLdaLookupContextSlot(TypeofMode::INSIDE_TYPEOF); 969 } 970 971 void BytecodeGraphBuilder::BuildLdaLookupGlobalSlot(TypeofMode typeof_mode) { 972 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2); 973 974 // Check if any context in the depth has an extension. 975 Environment* slow_environment = CheckContextExtensions(depth); 976 977 // Fast path, do a global load. 978 { 979 PrepareEagerCheckpoint(); 980 Handle<Name> name = 981 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0)); 982 uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1); 983 Node* node = BuildLoadGlobal(name, feedback_slot_index, typeof_mode); 984 environment()->BindAccumulator(node, Environment::kAttachFrameState); 985 } 986 987 // Only build the slow path if there were any slow-path checks. 988 if (slow_environment != nullptr) { 989 // Add a merge to the fast environment. 990 NewMerge(); 991 Environment* fast_environment = environment(); 992 993 // Slow path, do a runtime load lookup. 994 set_environment(slow_environment); 995 { 996 Node* name = jsgraph()->Constant( 997 bytecode_iterator().GetConstantForIndexOperand(0)); 998 999 const Operator* op = 1000 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF 1001 ? Runtime::kLoadLookupSlot 1002 : Runtime::kLoadLookupSlotInsideTypeof); 1003 Node* value = NewNode(op, name); 1004 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1005 } 1006 1007 fast_environment->Merge(environment()); 1008 set_environment(fast_environment); 1009 mark_as_needing_eager_checkpoint(true); 1010 } 1011 } 1012 1013 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlot() { 1014 BuildLdaLookupGlobalSlot(TypeofMode::NOT_INSIDE_TYPEOF); 1015 } 1016 1017 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() { 1018 BuildLdaLookupGlobalSlot(TypeofMode::INSIDE_TYPEOF); 1019 } 1020 1021 void BytecodeGraphBuilder::BuildStaLookupSlot(LanguageMode language_mode) { 1022 PrepareEagerCheckpoint(); 1023 Node* value = environment()->LookupAccumulator(); 1024 Node* name = 1025 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); 1026 const Operator* op = javascript()->CallRuntime( 1027 is_strict(language_mode) ? Runtime::kStoreLookupSlot_Strict 1028 : Runtime::kStoreLookupSlot_Sloppy); 1029 Node* store = NewNode(op, name, value); 1030 environment()->BindAccumulator(store, Environment::kAttachFrameState); 1031 } 1032 1033 void BytecodeGraphBuilder::VisitStaLookupSlotSloppy() { 1034 BuildStaLookupSlot(LanguageMode::SLOPPY); 1035 } 1036 1037 void BytecodeGraphBuilder::VisitStaLookupSlotStrict() { 1038 BuildStaLookupSlot(LanguageMode::STRICT); 1039 } 1040 1041 void BytecodeGraphBuilder::VisitLdaNamedProperty() { 1042 PrepareEagerCheckpoint(); 1043 Node* object = 1044 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1045 Handle<Name> name = 1046 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1)); 1047 VectorSlotPair feedback = 1048 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2)); 1049 1050 const Operator* op = javascript()->LoadNamed(name, feedback); 1051 Node* node = NewNode(op, object); 1052 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1053 } 1054 1055 void BytecodeGraphBuilder::VisitLdaKeyedProperty() { 1056 PrepareEagerCheckpoint(); 1057 Node* key = environment()->LookupAccumulator(); 1058 Node* object = 1059 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1060 VectorSlotPair feedback = 1061 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1)); 1062 1063 const Operator* op = javascript()->LoadProperty(feedback); 1064 Node* node = NewNode(op, object, key); 1065 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1066 } 1067 1068 void BytecodeGraphBuilder::BuildNamedStore(LanguageMode language_mode, 1069 StoreMode store_mode) { 1070 PrepareEagerCheckpoint(); 1071 Node* value = environment()->LookupAccumulator(); 1072 Node* object = 1073 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1074 Handle<Name> name = 1075 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1)); 1076 VectorSlotPair feedback = 1077 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2)); 1078 1079 const Operator* op; 1080 if (store_mode == StoreMode::kOwn) { 1081 DCHECK_EQ(FeedbackSlotKind::kStoreOwnNamed, 1082 feedback.vector()->GetKind(feedback.slot())); 1083 op = javascript()->StoreNamedOwn(name, feedback); 1084 } else { 1085 DCHECK(store_mode == StoreMode::kNormal); 1086 DCHECK_EQ(feedback.vector()->GetLanguageMode(feedback.slot()), 1087 language_mode); 1088 op = javascript()->StoreNamed(language_mode, name, feedback); 1089 } 1090 Node* node = NewNode(op, object, value); 1091 environment()->RecordAfterState(node, Environment::kAttachFrameState); 1092 } 1093 1094 void BytecodeGraphBuilder::VisitStaNamedPropertySloppy() { 1095 BuildNamedStore(LanguageMode::SLOPPY, StoreMode::kNormal); 1096 } 1097 1098 void BytecodeGraphBuilder::VisitStaNamedPropertyStrict() { 1099 BuildNamedStore(LanguageMode::STRICT, StoreMode::kNormal); 1100 } 1101 1102 void BytecodeGraphBuilder::VisitStaNamedOwnProperty() { 1103 BuildNamedStore(LanguageMode::STRICT, StoreMode::kOwn); 1104 } 1105 1106 void BytecodeGraphBuilder::BuildKeyedStore(LanguageMode language_mode) { 1107 PrepareEagerCheckpoint(); 1108 Node* value = environment()->LookupAccumulator(); 1109 Node* object = 1110 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1111 Node* key = 1112 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 1113 VectorSlotPair feedback = 1114 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2)); 1115 1116 DCHECK_EQ(feedback.vector()->GetLanguageMode(feedback.slot()), language_mode); 1117 const Operator* op = javascript()->StoreProperty(language_mode, feedback); 1118 Node* node = NewNode(op, object, key, value); 1119 environment()->RecordAfterState(node, Environment::kAttachFrameState); 1120 } 1121 1122 void BytecodeGraphBuilder::VisitStaKeyedPropertySloppy() { 1123 BuildKeyedStore(LanguageMode::SLOPPY); 1124 } 1125 1126 void BytecodeGraphBuilder::VisitStaKeyedPropertyStrict() { 1127 BuildKeyedStore(LanguageMode::STRICT); 1128 } 1129 1130 void BytecodeGraphBuilder::VisitLdaModuleVariable() { 1131 int32_t cell_index = bytecode_iterator().GetImmediateOperand(0); 1132 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1); 1133 Node* module = 1134 NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true)); 1135 Node* value = NewNode(javascript()->LoadModule(cell_index), module); 1136 environment()->BindAccumulator(value); 1137 } 1138 1139 void BytecodeGraphBuilder::VisitStaModuleVariable() { 1140 int32_t cell_index = bytecode_iterator().GetImmediateOperand(0); 1141 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1); 1142 Node* module = 1143 NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true)); 1144 Node* value = environment()->LookupAccumulator(); 1145 NewNode(javascript()->StoreModule(cell_index), module, value); 1146 } 1147 1148 void BytecodeGraphBuilder::VisitPushContext() { 1149 Node* new_context = environment()->LookupAccumulator(); 1150 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), 1151 environment()->Context()); 1152 environment()->SetContext(new_context); 1153 } 1154 1155 void BytecodeGraphBuilder::VisitPopContext() { 1156 Node* context = 1157 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1158 environment()->SetContext(context); 1159 } 1160 1161 void BytecodeGraphBuilder::VisitCreateClosure() { 1162 Handle<SharedFunctionInfo> shared_info = Handle<SharedFunctionInfo>::cast( 1163 bytecode_iterator().GetConstantForIndexOperand(0)); 1164 int const slot_id = bytecode_iterator().GetIndexOperand(1); 1165 VectorSlotPair pair = CreateVectorSlotPair(slot_id); 1166 PretenureFlag tenured = 1167 interpreter::CreateClosureFlags::PretenuredBit::decode( 1168 bytecode_iterator().GetFlagOperand(2)) 1169 ? TENURED 1170 : NOT_TENURED; 1171 const Operator* op = javascript()->CreateClosure(shared_info, pair, tenured); 1172 Node* closure = NewNode(op); 1173 environment()->BindAccumulator(closure); 1174 } 1175 1176 void BytecodeGraphBuilder::VisitCreateBlockContext() { 1177 Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast( 1178 bytecode_iterator().GetConstantForIndexOperand(0)); 1179 1180 const Operator* op = javascript()->CreateBlockContext(scope_info); 1181 Node* context = NewNode(op, environment()->LookupAccumulator()); 1182 environment()->BindAccumulator(context); 1183 } 1184 1185 void BytecodeGraphBuilder::VisitCreateFunctionContext() { 1186 uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(0); 1187 const Operator* op = 1188 javascript()->CreateFunctionContext(slots, FUNCTION_SCOPE); 1189 Node* context = NewNode(op, GetFunctionClosure()); 1190 environment()->BindAccumulator(context); 1191 } 1192 1193 void BytecodeGraphBuilder::VisitCreateEvalContext() { 1194 uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(0); 1195 const Operator* op = javascript()->CreateFunctionContext(slots, EVAL_SCOPE); 1196 Node* context = NewNode(op, GetFunctionClosure()); 1197 environment()->BindAccumulator(context); 1198 } 1199 1200 void BytecodeGraphBuilder::VisitCreateCatchContext() { 1201 interpreter::Register reg = bytecode_iterator().GetRegisterOperand(0); 1202 Node* exception = environment()->LookupRegister(reg); 1203 Handle<String> name = 1204 Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(1)); 1205 Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast( 1206 bytecode_iterator().GetConstantForIndexOperand(2)); 1207 Node* closure = environment()->LookupAccumulator(); 1208 1209 const Operator* op = javascript()->CreateCatchContext(name, scope_info); 1210 Node* context = NewNode(op, exception, closure); 1211 environment()->BindAccumulator(context); 1212 } 1213 1214 void BytecodeGraphBuilder::VisitCreateWithContext() { 1215 Node* object = 1216 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1217 Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast( 1218 bytecode_iterator().GetConstantForIndexOperand(1)); 1219 1220 const Operator* op = javascript()->CreateWithContext(scope_info); 1221 Node* context = NewNode(op, object, environment()->LookupAccumulator()); 1222 environment()->BindAccumulator(context); 1223 } 1224 1225 void BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) { 1226 const Operator* op = javascript()->CreateArguments(type); 1227 Node* object = NewNode(op, GetFunctionClosure()); 1228 environment()->BindAccumulator(object, Environment::kAttachFrameState); 1229 } 1230 1231 void BytecodeGraphBuilder::VisitCreateMappedArguments() { 1232 BuildCreateArguments(CreateArgumentsType::kMappedArguments); 1233 } 1234 1235 void BytecodeGraphBuilder::VisitCreateUnmappedArguments() { 1236 BuildCreateArguments(CreateArgumentsType::kUnmappedArguments); 1237 } 1238 1239 void BytecodeGraphBuilder::VisitCreateRestParameter() { 1240 BuildCreateArguments(CreateArgumentsType::kRestParameter); 1241 } 1242 1243 void BytecodeGraphBuilder::VisitCreateRegExpLiteral() { 1244 Handle<String> constant_pattern = 1245 Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(0)); 1246 int literal_index = bytecode_iterator().GetIndexOperand(1); 1247 int literal_flags = bytecode_iterator().GetFlagOperand(2); 1248 Node* literal = NewNode(javascript()->CreateLiteralRegExp( 1249 constant_pattern, literal_flags, literal_index), 1250 GetFunctionClosure()); 1251 environment()->BindAccumulator(literal, Environment::kAttachFrameState); 1252 } 1253 1254 void BytecodeGraphBuilder::VisitCreateArrayLiteral() { 1255 Handle<ConstantElementsPair> constant_elements = 1256 Handle<ConstantElementsPair>::cast( 1257 bytecode_iterator().GetConstantForIndexOperand(0)); 1258 int literal_index = bytecode_iterator().GetIndexOperand(1); 1259 int bytecode_flags = bytecode_iterator().GetFlagOperand(2); 1260 int literal_flags = 1261 interpreter::CreateArrayLiteralFlags::FlagsBits::decode(bytecode_flags); 1262 // Disable allocation site mementos. Only unoptimized code will collect 1263 // feedback about allocation site. Once the code is optimized we expect the 1264 // data to converge. So, we disable allocation site mementos in optimized 1265 // code. We can revisit this when we have data to the contrary. 1266 literal_flags |= ArrayLiteral::kDisableMementos; 1267 // TODO(mstarzinger): Thread through number of elements. The below number is 1268 // only an estimate and does not match {ArrayLiteral::values::length}. 1269 int number_of_elements = constant_elements->constant_values()->length(); 1270 Node* literal = NewNode( 1271 javascript()->CreateLiteralArray(constant_elements, literal_flags, 1272 literal_index, number_of_elements), 1273 GetFunctionClosure()); 1274 environment()->BindAccumulator(literal, Environment::kAttachFrameState); 1275 } 1276 1277 void BytecodeGraphBuilder::VisitCreateObjectLiteral() { 1278 Handle<BoilerplateDescription> constant_properties = 1279 Handle<BoilerplateDescription>::cast( 1280 bytecode_iterator().GetConstantForIndexOperand(0)); 1281 int literal_index = bytecode_iterator().GetIndexOperand(1); 1282 int bytecode_flags = bytecode_iterator().GetFlagOperand(2); 1283 int literal_flags = 1284 interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags); 1285 // TODO(mstarzinger): Thread through number of properties. The below number is 1286 // only an estimate and does not match {ObjectLiteral::properties_count}. 1287 int number_of_properties = constant_properties->size(); 1288 Node* literal = NewNode( 1289 javascript()->CreateLiteralObject(constant_properties, literal_flags, 1290 literal_index, number_of_properties), 1291 GetFunctionClosure()); 1292 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(3), 1293 literal, Environment::kAttachFrameState); 1294 } 1295 1296 Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, 1297 Node* callee, 1298 interpreter::Register receiver, 1299 size_t arity) { 1300 Node** all = local_zone()->NewArray<Node*>(static_cast<int>(arity)); 1301 all[0] = callee; 1302 all[1] = environment()->LookupRegister(receiver); 1303 int receiver_index = receiver.index(); 1304 for (int i = 2; i < static_cast<int>(arity); ++i) { 1305 all[i] = environment()->LookupRegister( 1306 interpreter::Register(receiver_index + i - 1)); 1307 } 1308 Node* value = MakeNode(call_op, static_cast<int>(arity), all, false); 1309 return value; 1310 } 1311 1312 void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode, 1313 ConvertReceiverMode receiver_hint) { 1314 PrepareEagerCheckpoint(); 1315 1316 Node* callee = 1317 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1318 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 1319 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1320 1321 // Slot index of 0 is used indicate no feedback slot is available. Assert 1322 // the assumption that slot index 0 is never a valid feedback slot. 1323 STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0); 1324 int const slot_id = bytecode_iterator().GetIndexOperand(3); 1325 VectorSlotPair feedback = CreateVectorSlotPair(slot_id); 1326 1327 float const frequency = ComputeCallFrequency(slot_id); 1328 const Operator* call = javascript()->Call(arg_count + 1, frequency, feedback, 1329 receiver_hint, tail_call_mode); 1330 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1); 1331 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1332 } 1333 1334 void BytecodeGraphBuilder::VisitCall() { 1335 BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kAny); 1336 } 1337 1338 void BytecodeGraphBuilder::VisitCallWithSpread() { 1339 PrepareEagerCheckpoint(); 1340 Node* callee = 1341 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1342 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 1343 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1344 const Operator* call = 1345 javascript()->CallWithSpread(static_cast<int>(arg_count + 1)); 1346 1347 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1); 1348 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1349 } 1350 1351 void BytecodeGraphBuilder::VisitCallProperty() { 1352 BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNotNullOrUndefined); 1353 } 1354 1355 void BytecodeGraphBuilder::VisitTailCall() { 1356 TailCallMode tail_call_mode = 1357 bytecode_array_->GetIsolate()->is_tail_call_elimination_enabled() 1358 ? TailCallMode::kAllow 1359 : TailCallMode::kDisallow; 1360 BuildCall(tail_call_mode, ConvertReceiverMode::kAny); 1361 } 1362 1363 void BytecodeGraphBuilder::VisitCallJSRuntime() { 1364 PrepareEagerCheckpoint(); 1365 Node* callee = 1366 BuildLoadNativeContextField(bytecode_iterator().GetIndexOperand(0)); 1367 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 1368 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1369 1370 // Create node to perform the JS runtime call. 1371 const Operator* call = javascript()->Call(arg_count + 1); 1372 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1); 1373 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1374 } 1375 1376 Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments( 1377 const Operator* call_runtime_op, interpreter::Register first_arg, 1378 size_t arity) { 1379 Node** all = local_zone()->NewArray<Node*>(arity); 1380 int first_arg_index = first_arg.index(); 1381 for (int i = 0; i < static_cast<int>(arity); ++i) { 1382 all[i] = environment()->LookupRegister( 1383 interpreter::Register(first_arg_index + i)); 1384 } 1385 Node* value = MakeNode(call_runtime_op, static_cast<int>(arity), all, false); 1386 return value; 1387 } 1388 1389 void BytecodeGraphBuilder::VisitCallRuntime() { 1390 PrepareEagerCheckpoint(); 1391 Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); 1392 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); 1393 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1394 1395 // Create node to perform the runtime call. 1396 const Operator* call = javascript()->CallRuntime(functionId, arg_count); 1397 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count); 1398 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1399 } 1400 1401 void BytecodeGraphBuilder::VisitCallRuntimeForPair() { 1402 PrepareEagerCheckpoint(); 1403 Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); 1404 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); 1405 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1406 interpreter::Register first_return = 1407 bytecode_iterator().GetRegisterOperand(3); 1408 1409 // Create node to perform the runtime call. 1410 const Operator* call = javascript()->CallRuntime(functionId, arg_count); 1411 Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count); 1412 environment()->BindRegistersToProjections(first_return, return_pair, 1413 Environment::kAttachFrameState); 1414 } 1415 1416 Node* BytecodeGraphBuilder::ProcessConstructWithSpreadArguments( 1417 const Operator* op, Node* callee, Node* new_target, 1418 interpreter::Register first_arg, size_t arity) { 1419 Node** all = local_zone()->NewArray<Node*>(arity); 1420 all[0] = callee; 1421 int first_arg_index = first_arg.index(); 1422 for (int i = 1; i < static_cast<int>(arity) - 1; ++i) { 1423 all[i] = environment()->LookupRegister( 1424 interpreter::Register(first_arg_index + i - 1)); 1425 } 1426 all[arity - 1] = new_target; 1427 Node* value = MakeNode(op, static_cast<int>(arity), all, false); 1428 return value; 1429 } 1430 1431 void BytecodeGraphBuilder::VisitConstructWithSpread() { 1432 PrepareEagerCheckpoint(); 1433 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); 1434 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); 1435 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1436 1437 Node* new_target = environment()->LookupAccumulator(); 1438 Node* callee = environment()->LookupRegister(callee_reg); 1439 1440 const Operator* op = 1441 javascript()->ConstructWithSpread(static_cast<int>(arg_count) + 2); 1442 Node* value = ProcessConstructWithSpreadArguments(op, callee, new_target, 1443 first_arg, arg_count + 2); 1444 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1445 } 1446 1447 void BytecodeGraphBuilder::VisitInvokeIntrinsic() { 1448 PrepareEagerCheckpoint(); 1449 Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0); 1450 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); 1451 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1452 1453 // Create node to perform the runtime call. Turbofan will take care of the 1454 // lowering. 1455 const Operator* call = javascript()->CallRuntime(functionId, arg_count); 1456 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count); 1457 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1458 } 1459 1460 Node* BytecodeGraphBuilder::ProcessConstructArguments( 1461 const Operator* call_new_op, Node* callee, Node* new_target, 1462 interpreter::Register first_arg, size_t arity) { 1463 Node** all = local_zone()->NewArray<Node*>(arity); 1464 all[0] = callee; 1465 int first_arg_index = first_arg.index(); 1466 for (int i = 1; i < static_cast<int>(arity) - 1; ++i) { 1467 all[i] = environment()->LookupRegister( 1468 interpreter::Register(first_arg_index + i - 1)); 1469 } 1470 all[arity - 1] = new_target; 1471 Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false); 1472 return value; 1473 } 1474 1475 void BytecodeGraphBuilder::VisitConstruct() { 1476 PrepareEagerCheckpoint(); 1477 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); 1478 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); 1479 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1480 // Slot index of 0 is used indicate no feedback slot is available. Assert 1481 // the assumption that slot index 0 is never a valid feedback slot. 1482 STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0); 1483 int const slot_id = bytecode_iterator().GetIndexOperand(3); 1484 VectorSlotPair feedback = CreateVectorSlotPair(slot_id); 1485 1486 Node* new_target = environment()->LookupAccumulator(); 1487 Node* callee = environment()->LookupRegister(callee_reg); 1488 1489 float const frequency = ComputeCallFrequency(slot_id); 1490 const Operator* call = javascript()->Construct( 1491 static_cast<int>(arg_count) + 2, frequency, feedback); 1492 Node* value = ProcessConstructArguments(call, callee, new_target, first_arg, 1493 arg_count + 2); 1494 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1495 } 1496 1497 void BytecodeGraphBuilder::VisitThrow() { 1498 BuildLoopExitsForFunctionExit(); 1499 Node* value = environment()->LookupAccumulator(); 1500 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); 1501 environment()->BindAccumulator(call, Environment::kAttachFrameState); 1502 Node* control = NewNode(common()->Throw(), call); 1503 MergeControlToLeaveFunction(control); 1504 } 1505 1506 void BytecodeGraphBuilder::VisitReThrow() { 1507 BuildLoopExitsForFunctionExit(); 1508 Node* value = environment()->LookupAccumulator(); 1509 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); 1510 Node* control = NewNode(common()->Throw(), call); 1511 MergeControlToLeaveFunction(control); 1512 } 1513 1514 Node* BytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op, 1515 Node* left, Node* right, 1516 FeedbackSlot slot) { 1517 Node* effect = environment()->GetEffectDependency(); 1518 Node* control = environment()->GetControlDependency(); 1519 JSTypeHintLowering type_hint_lowering(jsgraph(), feedback_vector()); 1520 Reduction early_reduction = type_hint_lowering.ReduceBinaryOperation( 1521 op, left, right, effect, control, slot); 1522 if (early_reduction.Changed()) { 1523 Node* node = early_reduction.replacement(); 1524 if (node->op()->EffectOutputCount() > 0) { 1525 environment()->UpdateEffectDependency(node); 1526 } 1527 return node; 1528 } 1529 return nullptr; 1530 } 1531 1532 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) { 1533 PrepareEagerCheckpoint(); 1534 Node* left = 1535 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1536 Node* right = environment()->LookupAccumulator(); 1537 1538 Node* node = nullptr; 1539 FeedbackSlot slot = feedback_vector()->ToSlot( 1540 bytecode_iterator().GetIndexOperand(kBinaryOperationHintIndex)); 1541 if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) { 1542 node = simplified; 1543 } else { 1544 node = NewNode(op, left, right); 1545 } 1546 1547 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1548 } 1549 1550 // Helper function to create binary operation hint from the recorded type 1551 // feedback. 1552 BinaryOperationHint BytecodeGraphBuilder::GetBinaryOperationHint( 1553 int operand_index) { 1554 FeedbackSlot slot = feedback_vector()->ToSlot( 1555 bytecode_iterator().GetIndexOperand(operand_index)); 1556 DCHECK_EQ(FeedbackSlotKind::kBinaryOp, feedback_vector()->GetKind(slot)); 1557 BinaryOpICNexus nexus(feedback_vector(), slot); 1558 return nexus.GetBinaryOperationFeedback(); 1559 } 1560 1561 // Helper function to create compare operation hint from the recorded type 1562 // feedback. 1563 CompareOperationHint BytecodeGraphBuilder::GetCompareOperationHint() { 1564 int slot_index = bytecode_iterator().GetIndexOperand(1); 1565 if (slot_index == 0) { 1566 return CompareOperationHint::kAny; 1567 } 1568 FeedbackSlot slot = 1569 feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(1)); 1570 DCHECK_EQ(FeedbackSlotKind::kCompareOp, feedback_vector()->GetKind(slot)); 1571 CompareICNexus nexus(feedback_vector(), slot); 1572 return nexus.GetCompareOperationFeedback(); 1573 } 1574 1575 float BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const { 1576 CallICNexus nexus(feedback_vector(), feedback_vector()->ToSlot(slot_id)); 1577 return nexus.ComputeCallFrequency() * invocation_frequency_; 1578 } 1579 1580 void BytecodeGraphBuilder::VisitAdd() { 1581 BuildBinaryOp( 1582 javascript()->Add(GetBinaryOperationHint(kBinaryOperationHintIndex))); 1583 } 1584 1585 void BytecodeGraphBuilder::VisitSub() { 1586 BuildBinaryOp(javascript()->Subtract()); 1587 } 1588 1589 void BytecodeGraphBuilder::VisitMul() { 1590 BuildBinaryOp(javascript()->Multiply()); 1591 } 1592 1593 void BytecodeGraphBuilder::VisitDiv() { BuildBinaryOp(javascript()->Divide()); } 1594 1595 void BytecodeGraphBuilder::VisitMod() { 1596 BuildBinaryOp(javascript()->Modulus()); 1597 } 1598 1599 void BytecodeGraphBuilder::VisitBitwiseOr() { 1600 BuildBinaryOp(javascript()->BitwiseOr()); 1601 } 1602 1603 void BytecodeGraphBuilder::VisitBitwiseXor() { 1604 BuildBinaryOp(javascript()->BitwiseXor()); 1605 } 1606 1607 void BytecodeGraphBuilder::VisitBitwiseAnd() { 1608 BuildBinaryOp(javascript()->BitwiseAnd()); 1609 } 1610 1611 void BytecodeGraphBuilder::VisitShiftLeft() { 1612 BuildBinaryOp(javascript()->ShiftLeft()); 1613 } 1614 1615 void BytecodeGraphBuilder::VisitShiftRight() { 1616 BuildBinaryOp(javascript()->ShiftRight()); 1617 } 1618 1619 void BytecodeGraphBuilder::VisitShiftRightLogical() { 1620 BuildBinaryOp(javascript()->ShiftRightLogical()); 1621 } 1622 1623 void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) { 1624 PrepareEagerCheckpoint(); 1625 Node* left = 1626 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 1627 Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); 1628 1629 Node* node = nullptr; 1630 FeedbackSlot slot = feedback_vector()->ToSlot( 1631 bytecode_iterator().GetIndexOperand(kBinaryOperationSmiHintIndex)); 1632 if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) { 1633 node = simplified; 1634 } else { 1635 node = NewNode(op, left, right); 1636 } 1637 1638 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1639 } 1640 1641 void BytecodeGraphBuilder::VisitAddSmi() { 1642 BuildBinaryOpWithImmediate( 1643 javascript()->Add(GetBinaryOperationHint(kBinaryOperationSmiHintIndex))); 1644 } 1645 1646 void BytecodeGraphBuilder::VisitSubSmi() { 1647 BuildBinaryOpWithImmediate(javascript()->Subtract()); 1648 } 1649 1650 void BytecodeGraphBuilder::VisitBitwiseOrSmi() { 1651 BuildBinaryOpWithImmediate(javascript()->BitwiseOr()); 1652 } 1653 1654 void BytecodeGraphBuilder::VisitBitwiseAndSmi() { 1655 BuildBinaryOpWithImmediate(javascript()->BitwiseAnd()); 1656 } 1657 1658 void BytecodeGraphBuilder::VisitShiftLeftSmi() { 1659 BuildBinaryOpWithImmediate(javascript()->ShiftLeft()); 1660 } 1661 1662 void BytecodeGraphBuilder::VisitShiftRightSmi() { 1663 BuildBinaryOpWithImmediate(javascript()->ShiftRight()); 1664 } 1665 1666 void BytecodeGraphBuilder::VisitInc() { 1667 PrepareEagerCheckpoint(); 1668 // Note: Use subtract -1 here instead of add 1 to ensure we always convert to 1669 // a number, not a string. 1670 Node* left = environment()->LookupAccumulator(); 1671 Node* right = jsgraph()->Constant(-1); 1672 const Operator* op = javascript()->Subtract(); 1673 1674 Node* node = nullptr; 1675 FeedbackSlot slot = feedback_vector()->ToSlot( 1676 bytecode_iterator().GetIndexOperand(kCountOperationHintIndex)); 1677 if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) { 1678 node = simplified; 1679 } else { 1680 node = NewNode(op, left, right); 1681 } 1682 1683 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1684 } 1685 1686 void BytecodeGraphBuilder::VisitDec() { 1687 PrepareEagerCheckpoint(); 1688 Node* left = environment()->LookupAccumulator(); 1689 Node* right = jsgraph()->OneConstant(); 1690 const Operator* op = javascript()->Subtract(); 1691 1692 Node* node = nullptr; 1693 FeedbackSlot slot = feedback_vector()->ToSlot( 1694 bytecode_iterator().GetIndexOperand(kCountOperationHintIndex)); 1695 if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) { 1696 node = simplified; 1697 } else { 1698 node = NewNode(op, left, right); 1699 } 1700 1701 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1702 } 1703 1704 void BytecodeGraphBuilder::VisitLogicalNot() { 1705 Node* value = environment()->LookupAccumulator(); 1706 Node* node = NewNode(simplified()->BooleanNot(), value); 1707 environment()->BindAccumulator(node); 1708 } 1709 1710 void BytecodeGraphBuilder::VisitToBooleanLogicalNot() { 1711 Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), 1712 environment()->LookupAccumulator()); 1713 Node* node = NewNode(simplified()->BooleanNot(), value); 1714 environment()->BindAccumulator(node); 1715 } 1716 1717 void BytecodeGraphBuilder::VisitTypeOf() { 1718 Node* node = 1719 NewNode(javascript()->TypeOf(), environment()->LookupAccumulator()); 1720 environment()->BindAccumulator(node); 1721 } 1722 1723 void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) { 1724 PrepareEagerCheckpoint(); 1725 Node* key = environment()->LookupAccumulator(); 1726 Node* object = 1727 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1728 Node* node = 1729 NewNode(javascript()->DeleteProperty(language_mode), object, key); 1730 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1731 } 1732 1733 void BytecodeGraphBuilder::VisitDeletePropertyStrict() { 1734 BuildDelete(LanguageMode::STRICT); 1735 } 1736 1737 void BytecodeGraphBuilder::VisitDeletePropertySloppy() { 1738 BuildDelete(LanguageMode::SLOPPY); 1739 } 1740 1741 void BytecodeGraphBuilder::VisitGetSuperConstructor() { 1742 Node* node = NewNode(javascript()->GetSuperConstructor(), 1743 environment()->LookupAccumulator()); 1744 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node, 1745 Environment::kAttachFrameState); 1746 } 1747 1748 void BytecodeGraphBuilder::BuildCompareOp(const Operator* js_op) { 1749 PrepareEagerCheckpoint(); 1750 Node* left = 1751 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1752 Node* right = environment()->LookupAccumulator(); 1753 Node* node = NewNode(js_op, left, right); 1754 environment()->BindAccumulator(node, Environment::kAttachFrameState); 1755 } 1756 1757 void BytecodeGraphBuilder::VisitTestEqual() { 1758 BuildCompareOp(javascript()->Equal(GetCompareOperationHint())); 1759 } 1760 1761 void BytecodeGraphBuilder::VisitTestNotEqual() { 1762 BuildCompareOp(javascript()->NotEqual(GetCompareOperationHint())); 1763 } 1764 1765 void BytecodeGraphBuilder::VisitTestEqualStrict() { 1766 BuildCompareOp(javascript()->StrictEqual(GetCompareOperationHint())); 1767 } 1768 1769 void BytecodeGraphBuilder::VisitTestLessThan() { 1770 BuildCompareOp(javascript()->LessThan(GetCompareOperationHint())); 1771 } 1772 1773 void BytecodeGraphBuilder::VisitTestGreaterThan() { 1774 BuildCompareOp(javascript()->GreaterThan(GetCompareOperationHint())); 1775 } 1776 1777 void BytecodeGraphBuilder::VisitTestLessThanOrEqual() { 1778 BuildCompareOp(javascript()->LessThanOrEqual(GetCompareOperationHint())); 1779 } 1780 1781 void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() { 1782 BuildCompareOp(javascript()->GreaterThanOrEqual(GetCompareOperationHint())); 1783 } 1784 1785 void BytecodeGraphBuilder::VisitTestIn() { 1786 BuildCompareOp(javascript()->HasProperty()); 1787 } 1788 1789 void BytecodeGraphBuilder::VisitTestInstanceOf() { 1790 BuildCompareOp(javascript()->InstanceOf()); 1791 } 1792 1793 void BytecodeGraphBuilder::VisitTestUndetectable() { 1794 Node* object = 1795 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1796 Node* node = NewNode(jsgraph()->simplified()->ObjectIsUndetectable(), object); 1797 environment()->BindAccumulator(node); 1798 } 1799 1800 void BytecodeGraphBuilder::VisitTestNull() { 1801 Node* object = 1802 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1803 Node* result = NewNode(simplified()->ReferenceEqual(), object, 1804 jsgraph()->NullConstant()); 1805 environment()->BindAccumulator(result); 1806 } 1807 1808 void BytecodeGraphBuilder::VisitTestUndefined() { 1809 Node* object = 1810 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1811 Node* result = NewNode(simplified()->ReferenceEqual(), object, 1812 jsgraph()->UndefinedConstant()); 1813 environment()->BindAccumulator(result); 1814 } 1815 1816 void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) { 1817 Node* value = NewNode(js_op, environment()->LookupAccumulator()); 1818 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value, 1819 Environment::kAttachFrameState); 1820 } 1821 1822 void BytecodeGraphBuilder::VisitToName() { 1823 BuildCastOperator(javascript()->ToName()); 1824 } 1825 1826 void BytecodeGraphBuilder::VisitToObject() { 1827 BuildCastOperator(javascript()->ToObject()); 1828 } 1829 1830 void BytecodeGraphBuilder::VisitToNumber() { 1831 BuildCastOperator(javascript()->ToNumber()); 1832 } 1833 1834 void BytecodeGraphBuilder::VisitJump() { BuildJump(); } 1835 1836 void BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); } 1837 1838 void BytecodeGraphBuilder::VisitJumpIfTrue() { BuildJumpIfTrue(); } 1839 1840 void BytecodeGraphBuilder::VisitJumpIfTrueConstant() { BuildJumpIfTrue(); } 1841 1842 void BytecodeGraphBuilder::VisitJumpIfFalse() { BuildJumpIfFalse(); } 1843 1844 void BytecodeGraphBuilder::VisitJumpIfFalseConstant() { BuildJumpIfFalse(); } 1845 1846 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() { 1847 BuildJumpIfToBooleanTrue(); 1848 } 1849 1850 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() { 1851 BuildJumpIfToBooleanTrue(); 1852 } 1853 1854 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() { 1855 BuildJumpIfToBooleanFalse(); 1856 } 1857 1858 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() { 1859 BuildJumpIfToBooleanFalse(); 1860 } 1861 1862 void BytecodeGraphBuilder::VisitJumpIfNotHole() { BuildJumpIfNotHole(); } 1863 1864 void BytecodeGraphBuilder::VisitJumpIfNotHoleConstant() { 1865 BuildJumpIfNotHole(); 1866 } 1867 1868 void BytecodeGraphBuilder::VisitJumpIfJSReceiver() { BuildJumpIfJSReceiver(); } 1869 1870 void BytecodeGraphBuilder::VisitJumpIfJSReceiverConstant() { 1871 BuildJumpIfJSReceiver(); 1872 } 1873 1874 void BytecodeGraphBuilder::VisitJumpIfNull() { 1875 BuildJumpIfEqual(jsgraph()->NullConstant()); 1876 } 1877 1878 void BytecodeGraphBuilder::VisitJumpIfNullConstant() { 1879 BuildJumpIfEqual(jsgraph()->NullConstant()); 1880 } 1881 1882 void BytecodeGraphBuilder::VisitJumpIfUndefined() { 1883 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 1884 } 1885 1886 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() { 1887 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 1888 } 1889 1890 void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); } 1891 1892 void BytecodeGraphBuilder::VisitStackCheck() { 1893 PrepareEagerCheckpoint(); 1894 Node* node = NewNode(javascript()->StackCheck()); 1895 environment()->RecordAfterState(node, Environment::kAttachFrameState); 1896 } 1897 1898 void BytecodeGraphBuilder::VisitSetPendingMessage() { 1899 Node* previous_message = NewNode(javascript()->LoadMessage()); 1900 NewNode(javascript()->StoreMessage(), environment()->LookupAccumulator()); 1901 environment()->BindAccumulator(previous_message); 1902 } 1903 1904 void BytecodeGraphBuilder::VisitReturn() { 1905 BuildLoopExitsForFunctionExit(); 1906 Node* pop_node = jsgraph()->ZeroConstant(); 1907 Node* control = 1908 NewNode(common()->Return(), pop_node, environment()->LookupAccumulator()); 1909 MergeControlToLeaveFunction(control); 1910 } 1911 1912 void BytecodeGraphBuilder::VisitDebugger() { 1913 PrepareEagerCheckpoint(); 1914 Node* call = NewNode(javascript()->Debugger()); 1915 environment()->RecordAfterState(call, Environment::kAttachFrameState); 1916 } 1917 1918 // We cannot create a graph from the debugger copy of the bytecode array. 1919 #define DEBUG_BREAK(Name, ...) \ 1920 void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); } 1921 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK); 1922 #undef DEBUG_BREAK 1923 1924 void BytecodeGraphBuilder::BuildForInPrepare() { 1925 PrepareEagerCheckpoint(); 1926 Node* receiver = 1927 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1928 Node* prepare = NewNode(javascript()->ForInPrepare(), receiver); 1929 environment()->BindRegistersToProjections( 1930 bytecode_iterator().GetRegisterOperand(1), prepare, 1931 Environment::kAttachFrameState); 1932 } 1933 1934 void BytecodeGraphBuilder::VisitForInPrepare() { BuildForInPrepare(); } 1935 1936 void BytecodeGraphBuilder::VisitForInContinue() { 1937 PrepareEagerCheckpoint(); 1938 Node* index = 1939 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1940 Node* cache_length = 1941 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 1942 Node* exit_cond = 1943 NewNode(javascript()->LessThan(CompareOperationHint::kSignedSmall), index, 1944 cache_length); 1945 environment()->BindAccumulator(exit_cond, Environment::kAttachFrameState); 1946 } 1947 1948 void BytecodeGraphBuilder::BuildForInNext() { 1949 PrepareEagerCheckpoint(); 1950 Node* receiver = 1951 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1952 Node* index = 1953 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 1954 int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index(); 1955 Node* cache_type = environment()->LookupRegister( 1956 interpreter::Register(catch_reg_pair_index)); 1957 Node* cache_array = environment()->LookupRegister( 1958 interpreter::Register(catch_reg_pair_index + 1)); 1959 1960 Node* value = NewNode(javascript()->ForInNext(), receiver, cache_array, 1961 cache_type, index); 1962 environment()->BindAccumulator(value, Environment::kAttachFrameState); 1963 } 1964 1965 void BytecodeGraphBuilder::VisitForInNext() { BuildForInNext(); } 1966 1967 void BytecodeGraphBuilder::VisitForInStep() { 1968 PrepareEagerCheckpoint(); 1969 Node* index = 1970 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1971 index = NewNode( 1972 simplified()->SpeculativeNumberAdd(NumberOperationHint::kSignedSmall), 1973 index, jsgraph()->OneConstant()); 1974 environment()->BindAccumulator(index, Environment::kAttachFrameState); 1975 } 1976 1977 void BytecodeGraphBuilder::VisitSuspendGenerator() { 1978 Node* state = environment()->LookupAccumulator(); 1979 Node* generator = environment()->LookupRegister( 1980 bytecode_iterator().GetRegisterOperand(0)); 1981 // The offsets used by the bytecode iterator are relative to a different base 1982 // than what is used in the interpreter, hence the addition. 1983 Node* offset = 1984 jsgraph()->Constant(bytecode_iterator().current_offset() + 1985 (BytecodeArray::kHeaderSize - kHeapObjectTag)); 1986 1987 int register_count = environment()->register_count(); 1988 int value_input_count = 3 + register_count; 1989 1990 Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count); 1991 value_inputs[0] = generator; 1992 value_inputs[1] = state; 1993 value_inputs[2] = offset; 1994 for (int i = 0; i < register_count; ++i) { 1995 value_inputs[3 + i] = 1996 environment()->LookupRegister(interpreter::Register(i)); 1997 } 1998 1999 MakeNode(javascript()->GeneratorStore(register_count), value_input_count, 2000 value_inputs, false); 2001 } 2002 2003 void BytecodeGraphBuilder::VisitResumeGenerator() { 2004 PrepareEagerCheckpoint(); 2005 2006 Node* generator = environment()->LookupRegister( 2007 bytecode_iterator().GetRegisterOperand(0)); 2008 2009 // Bijection between registers and array indices must match that used in 2010 // InterpreterAssembler::ExportRegisterFile. 2011 for (int i = 0; i < environment()->register_count(); ++i) { 2012 Node* value = NewNode(javascript()->GeneratorRestoreRegister(i), generator); 2013 environment()->BindRegister(interpreter::Register(i), value); 2014 } 2015 2016 Node* state = 2017 NewNode(javascript()->GeneratorRestoreContinuation(), generator); 2018 2019 environment()->BindAccumulator(state, Environment::kAttachFrameState); 2020 } 2021 2022 void BytecodeGraphBuilder::VisitWide() { 2023 // Consumed by the BytecodeArrayIterator. 2024 UNREACHABLE(); 2025 } 2026 2027 void BytecodeGraphBuilder::VisitExtraWide() { 2028 // Consumed by the BytecodeArrayIterator. 2029 UNREACHABLE(); 2030 } 2031 2032 void BytecodeGraphBuilder::VisitIllegal() { 2033 // Not emitted in valid bytecode. 2034 UNREACHABLE(); 2035 } 2036 2037 void BytecodeGraphBuilder::VisitNop() {} 2038 2039 void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) { 2040 auto it = merge_environments_.find(current_offset); 2041 if (it != merge_environments_.end()) { 2042 mark_as_needing_eager_checkpoint(true); 2043 if (environment() != nullptr) { 2044 it->second->Merge(environment()); 2045 } 2046 set_environment(it->second); 2047 } 2048 } 2049 2050 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { 2051 if (bytecode_analysis()->IsLoopHeader(current_offset)) { 2052 mark_as_needing_eager_checkpoint(true); 2053 const LoopInfo& loop_info = 2054 bytecode_analysis()->GetLoopInfoFor(current_offset); 2055 2056 // Add loop header. 2057 environment()->PrepareForLoop(loop_info.assignments()); 2058 2059 BuildOSRLoopEntryPoint(current_offset); 2060 2061 // Store a copy of the environment so we can connect merged back edge inputs 2062 // to the loop header. 2063 merge_environments_[current_offset] = environment()->Copy(); 2064 } 2065 } 2066 2067 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { 2068 BuildLoopExitsForBranch(target_offset); 2069 Environment*& merge_environment = merge_environments_[target_offset]; 2070 if (merge_environment == nullptr) { 2071 // Append merge nodes to the environment. We may merge here with another 2072 // environment. So add a place holder for merge nodes. We may add redundant 2073 // but will be eliminated in a later pass. 2074 // TODO(mstarzinger): Be smarter about this! 2075 NewMerge(); 2076 merge_environment = environment(); 2077 } else { 2078 merge_environment->Merge(environment()); 2079 } 2080 set_environment(nullptr); 2081 } 2082 2083 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { 2084 exit_controls_.push_back(exit); 2085 set_environment(nullptr); 2086 } 2087 2088 void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { 2089 DCHECK(bytecode_analysis()->IsLoopHeader(current_offset)); 2090 2091 if (!osr_ast_id_.IsNone() && osr_loop_offset_ == current_offset) { 2092 // For OSR add a special {OsrLoopEntry} node into the current loop header. 2093 // It will be turned into a usable entry by the OSR deconstruction. 2094 Environment* osr_env = environment()->Copy(); 2095 osr_env->PrepareForOsrEntry(); 2096 environment()->Merge(osr_env); 2097 } 2098 } 2099 2100 void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() { 2101 if (!osr_ast_id_.IsNone()) { 2102 // For OSR add an {OsrNormalEntry} as the the top-level environment start. 2103 // It will be replaced with {Dead} by the OSR deconstruction. 2104 NewNode(common()->OsrNormalEntry()); 2105 // Translate the offset of the jump instruction to the jump target offset of 2106 // that instruction so that the derived BailoutId points to the loop header. 2107 osr_loop_offset_ = 2108 bytecode_analysis()->GetLoopOffsetFor(osr_ast_id_.ToInt()); 2109 DCHECK(bytecode_analysis()->IsLoopHeader(osr_loop_offset_)); 2110 } 2111 } 2112 2113 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { 2114 int origin_offset = bytecode_iterator().current_offset(); 2115 // Only build loop exits for forward edges. 2116 if (target_offset > origin_offset) { 2117 BuildLoopExitsUntilLoop( 2118 bytecode_analysis()->GetLoopOffsetFor(target_offset)); 2119 } 2120 } 2121 2122 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { 2123 int origin_offset = bytecode_iterator().current_offset(); 2124 int current_loop = bytecode_analysis()->GetLoopOffsetFor(origin_offset); 2125 while (loop_offset < current_loop) { 2126 Node* loop_node = merge_environments_[current_loop]->GetControlDependency(); 2127 const LoopInfo& loop_info = 2128 bytecode_analysis()->GetLoopInfoFor(current_loop); 2129 environment()->PrepareForLoopExit(loop_node, loop_info.assignments()); 2130 current_loop = loop_info.parent_offset(); 2131 } 2132 } 2133 2134 void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit() { 2135 BuildLoopExitsUntilLoop(-1); 2136 } 2137 2138 void BytecodeGraphBuilder::BuildJump() { 2139 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 2140 } 2141 2142 void BytecodeGraphBuilder::BuildJumpIf(Node* condition) { 2143 NewBranch(condition); 2144 Environment* if_false_environment = environment()->Copy(); 2145 NewIfTrue(); 2146 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 2147 set_environment(if_false_environment); 2148 NewIfFalse(); 2149 } 2150 2151 void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) { 2152 NewBranch(condition); 2153 Environment* if_true_environment = environment()->Copy(); 2154 NewIfFalse(); 2155 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 2156 set_environment(if_true_environment); 2157 NewIfTrue(); 2158 } 2159 2160 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { 2161 Node* accumulator = environment()->LookupAccumulator(); 2162 Node* condition = 2163 NewNode(simplified()->ReferenceEqual(), accumulator, comperand); 2164 BuildJumpIf(condition); 2165 } 2166 2167 void BytecodeGraphBuilder::BuildJumpIfFalse() { 2168 NewBranch(environment()->LookupAccumulator()); 2169 Environment* if_true_environment = environment()->Copy(); 2170 environment()->BindAccumulator(jsgraph()->FalseConstant()); 2171 NewIfFalse(); 2172 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 2173 if_true_environment->BindAccumulator(jsgraph()->TrueConstant()); 2174 set_environment(if_true_environment); 2175 NewIfTrue(); 2176 } 2177 2178 void BytecodeGraphBuilder::BuildJumpIfTrue() { 2179 NewBranch(environment()->LookupAccumulator()); 2180 Environment* if_false_environment = environment()->Copy(); 2181 environment()->BindAccumulator(jsgraph()->TrueConstant()); 2182 NewIfTrue(); 2183 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 2184 if_false_environment->BindAccumulator(jsgraph()->FalseConstant()); 2185 set_environment(if_false_environment); 2186 NewIfFalse(); 2187 } 2188 2189 void BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() { 2190 Node* accumulator = environment()->LookupAccumulator(); 2191 Node* condition = 2192 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); 2193 BuildJumpIf(condition); 2194 } 2195 2196 void BytecodeGraphBuilder::BuildJumpIfToBooleanFalse() { 2197 Node* accumulator = environment()->LookupAccumulator(); 2198 Node* condition = 2199 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); 2200 BuildJumpIfNot(condition); 2201 } 2202 2203 void BytecodeGraphBuilder::BuildJumpIfNotHole() { 2204 Node* accumulator = environment()->LookupAccumulator(); 2205 Node* condition = NewNode(simplified()->ReferenceEqual(), accumulator, 2206 jsgraph()->TheHoleConstant()); 2207 BuildJumpIfNot(condition); 2208 } 2209 2210 void BytecodeGraphBuilder::BuildJumpIfJSReceiver() { 2211 Node* accumulator = environment()->LookupAccumulator(); 2212 Node* condition = NewNode(simplified()->ObjectIsReceiver(), accumulator); 2213 BuildJumpIf(condition); 2214 } 2215 2216 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { 2217 if (size > input_buffer_size_) { 2218 size = size + kInputBufferSizeIncrement + input_buffer_size_; 2219 input_buffer_ = local_zone()->NewArray<Node*>(size); 2220 input_buffer_size_ = size; 2221 } 2222 return input_buffer_; 2223 } 2224 2225 void BytecodeGraphBuilder::EnterAndExitExceptionHandlers(int current_offset) { 2226 Handle<HandlerTable> table = exception_handler_table(); 2227 int num_entries = table->NumberOfRangeEntries(); 2228 2229 // Potentially exit exception handlers. 2230 while (!exception_handlers_.empty()) { 2231 int current_end = exception_handlers_.top().end_offset_; 2232 if (current_offset < current_end) break; // Still covered by range. 2233 exception_handlers_.pop(); 2234 } 2235 2236 // Potentially enter exception handlers. 2237 while (current_exception_handler_ < num_entries) { 2238 int next_start = table->GetRangeStart(current_exception_handler_); 2239 if (current_offset < next_start) break; // Not yet covered by range. 2240 int next_end = table->GetRangeEnd(current_exception_handler_); 2241 int next_handler = table->GetRangeHandler(current_exception_handler_); 2242 int context_register = table->GetRangeData(current_exception_handler_); 2243 exception_handlers_.push( 2244 {next_start, next_end, next_handler, context_register}); 2245 current_exception_handler_++; 2246 } 2247 } 2248 2249 Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, 2250 Node** value_inputs, bool incomplete) { 2251 DCHECK_EQ(op->ValueInputCount(), value_input_count); 2252 2253 bool has_context = OperatorProperties::HasContextInput(op); 2254 bool has_frame_state = OperatorProperties::HasFrameStateInput(op); 2255 bool has_control = op->ControlInputCount() == 1; 2256 bool has_effect = op->EffectInputCount() == 1; 2257 2258 DCHECK_LT(op->ControlInputCount(), 2); 2259 DCHECK_LT(op->EffectInputCount(), 2); 2260 2261 Node* result = nullptr; 2262 if (!has_context && !has_frame_state && !has_control && !has_effect) { 2263 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); 2264 } else { 2265 bool inside_handler = !exception_handlers_.empty(); 2266 int input_count_with_deps = value_input_count; 2267 if (has_context) ++input_count_with_deps; 2268 if (has_frame_state) ++input_count_with_deps; 2269 if (has_control) ++input_count_with_deps; 2270 if (has_effect) ++input_count_with_deps; 2271 Node** buffer = EnsureInputBufferSize(input_count_with_deps); 2272 memcpy(buffer, value_inputs, kPointerSize * value_input_count); 2273 Node** current_input = buffer + value_input_count; 2274 if (has_context) { 2275 *current_input++ = environment()->Context(); 2276 } 2277 if (has_frame_state) { 2278 // The frame state will be inserted later. Here we misuse the {Dead} node 2279 // as a sentinel to be later overwritten with the real frame state by the 2280 // calls to {PrepareFrameState} within individual visitor methods. 2281 *current_input++ = jsgraph()->Dead(); 2282 } 2283 if (has_effect) { 2284 *current_input++ = environment()->GetEffectDependency(); 2285 } 2286 if (has_control) { 2287 *current_input++ = environment()->GetControlDependency(); 2288 } 2289 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); 2290 // Update the current control dependency for control-producing nodes. 2291 if (NodeProperties::IsControl(result)) { 2292 environment()->UpdateControlDependency(result); 2293 } 2294 // Update the current effect dependency for effect-producing nodes. 2295 if (result->op()->EffectOutputCount() > 0) { 2296 environment()->UpdateEffectDependency(result); 2297 } 2298 // Add implicit exception continuation for throwing nodes. 2299 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { 2300 int handler_offset = exception_handlers_.top().handler_offset_; 2301 int context_index = exception_handlers_.top().context_register_; 2302 interpreter::Register context_register(context_index); 2303 Environment* success_env = environment()->Copy(); 2304 const Operator* op = common()->IfException(); 2305 Node* effect = environment()->GetEffectDependency(); 2306 Node* on_exception = graph()->NewNode(op, effect, result); 2307 Node* context = environment()->LookupRegister(context_register); 2308 environment()->UpdateControlDependency(on_exception); 2309 environment()->UpdateEffectDependency(on_exception); 2310 environment()->BindAccumulator(on_exception); 2311 environment()->SetContext(context); 2312 MergeIntoSuccessorEnvironment(handler_offset); 2313 set_environment(success_env); 2314 } 2315 // Add implicit success continuation for throwing nodes. 2316 if (!result->op()->HasProperty(Operator::kNoThrow)) { 2317 const Operator* if_success = common()->IfSuccess(); 2318 Node* on_success = graph()->NewNode(if_success, result); 2319 environment()->UpdateControlDependency(on_success); 2320 } 2321 // Ensure checkpoints are created after operations with side-effects. 2322 if (has_effect && !result->op()->HasProperty(Operator::kNoWrite)) { 2323 mark_as_needing_eager_checkpoint(true); 2324 } 2325 } 2326 2327 return result; 2328 } 2329 2330 2331 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { 2332 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); 2333 Node** buffer = EnsureInputBufferSize(count + 1); 2334 MemsetPointer(buffer, input, count); 2335 buffer[count] = control; 2336 return graph()->NewNode(phi_op, count + 1, buffer, true); 2337 } 2338 2339 2340 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input, 2341 Node* control) { 2342 const Operator* phi_op = common()->EffectPhi(count); 2343 Node** buffer = EnsureInputBufferSize(count + 1); 2344 MemsetPointer(buffer, input, count); 2345 buffer[count] = control; 2346 return graph()->NewNode(phi_op, count + 1, buffer, true); 2347 } 2348 2349 2350 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { 2351 int inputs = control->op()->ControlInputCount() + 1; 2352 if (control->opcode() == IrOpcode::kLoop) { 2353 // Control node for loop exists, add input. 2354 const Operator* op = common()->Loop(inputs); 2355 control->AppendInput(graph_zone(), other); 2356 NodeProperties::ChangeOp(control, op); 2357 } else if (control->opcode() == IrOpcode::kMerge) { 2358 // Control node for merge exists, add input. 2359 const Operator* op = common()->Merge(inputs); 2360 control->AppendInput(graph_zone(), other); 2361 NodeProperties::ChangeOp(control, op); 2362 } else { 2363 // Control node is a singleton, introduce a merge. 2364 const Operator* op = common()->Merge(inputs); 2365 Node* merge_inputs[] = {control, other}; 2366 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); 2367 } 2368 return control; 2369 } 2370 2371 2372 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, 2373 Node* control) { 2374 int inputs = control->op()->ControlInputCount(); 2375 if (value->opcode() == IrOpcode::kEffectPhi && 2376 NodeProperties::GetControlInput(value) == control) { 2377 // Phi already exists, add input. 2378 value->InsertInput(graph_zone(), inputs - 1, other); 2379 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs)); 2380 } else if (value != other) { 2381 // Phi does not exist yet, introduce one. 2382 value = NewEffectPhi(inputs, value, control); 2383 value->ReplaceInput(inputs - 1, other); 2384 } 2385 return value; 2386 } 2387 2388 2389 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, 2390 Node* control) { 2391 int inputs = control->op()->ControlInputCount(); 2392 if (value->opcode() == IrOpcode::kPhi && 2393 NodeProperties::GetControlInput(value) == control) { 2394 // Phi already exists, add input. 2395 value->InsertInput(graph_zone(), inputs - 1, other); 2396 NodeProperties::ChangeOp( 2397 value, common()->Phi(MachineRepresentation::kTagged, inputs)); 2398 } else if (value != other) { 2399 // Phi does not exist yet, introduce one. 2400 value = NewPhi(inputs, value, control); 2401 value->ReplaceInput(inputs - 1, other); 2402 } 2403 return value; 2404 } 2405 2406 void BytecodeGraphBuilder::UpdateCurrentSourcePosition( 2407 SourcePositionTableIterator* it, int offset) { 2408 if (it->done()) return; 2409 2410 if (it->code_offset() == offset) { 2411 source_positions_->SetCurrentPosition(SourcePosition( 2412 it->source_position().ScriptOffset(), start_position_.InliningId())); 2413 it->Advance(); 2414 } else { 2415 DCHECK_GT(it->code_offset(), offset); 2416 } 2417 } 2418 2419 } // namespace compiler 2420 } // namespace internal 2421 } // namespace v8 2422