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