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/compiler/bytecode-branch-analysis.h" 8 #include "src/compiler/linkage.h" 9 #include "src/compiler/operator-properties.h" 10 #include "src/interpreter/bytecodes.h" 11 12 namespace v8 { 13 namespace internal { 14 namespace compiler { 15 16 // Helper for generating frame states for before and after a bytecode. 17 class BytecodeGraphBuilder::FrameStateBeforeAndAfter { 18 public: 19 FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder, 20 const interpreter::BytecodeArrayIterator& iterator) 21 : builder_(builder), 22 id_after_(BailoutId::None()), 23 added_to_node_(false), 24 output_poke_offset_(0), 25 output_poke_count_(0) { 26 BailoutId id_before(iterator.current_offset()); 27 frame_state_before_ = builder_->environment()->Checkpoint( 28 id_before, OutputFrameStateCombine::Ignore()); 29 id_after_ = BailoutId(id_before.ToInt() + iterator.current_bytecode_size()); 30 } 31 32 ~FrameStateBeforeAndAfter() { 33 DCHECK(added_to_node_); 34 DCHECK(builder_->environment()->StateValuesAreUpToDate(output_poke_offset_, 35 output_poke_count_)); 36 } 37 38 private: 39 friend class Environment; 40 41 void AddToNode(Node* node, OutputFrameStateCombine combine) { 42 DCHECK(!added_to_node_); 43 int count = OperatorProperties::GetFrameStateInputCount(node->op()); 44 DCHECK_LE(count, 2); 45 if (count >= 1) { 46 // Add the frame state for after the operation. 47 DCHECK_EQ(IrOpcode::kDead, 48 NodeProperties::GetFrameStateInput(node, 0)->opcode()); 49 Node* frame_state_after = 50 builder_->environment()->Checkpoint(id_after_, combine); 51 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after); 52 } 53 54 if (count >= 2) { 55 // Add the frame state for before the operation. 56 DCHECK_EQ(IrOpcode::kDead, 57 NodeProperties::GetFrameStateInput(node, 1)->opcode()); 58 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); 59 } 60 61 if (!combine.IsOutputIgnored()) { 62 output_poke_offset_ = static_cast<int>(combine.GetOffsetToPokeAt()); 63 output_poke_count_ = node->op()->ValueOutputCount(); 64 } 65 added_to_node_ = true; 66 } 67 68 BytecodeGraphBuilder* builder_; 69 Node* frame_state_before_; 70 BailoutId id_after_; 71 72 bool added_to_node_; 73 int output_poke_offset_; 74 int output_poke_count_; 75 }; 76 77 78 // Issues: 79 // - Scopes - intimately tied to AST. Need to eval what is needed. 80 // - Need to resolve closure parameter treatment. 81 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder, 82 int register_count, 83 int parameter_count, 84 Node* control_dependency, 85 Node* context) 86 : builder_(builder), 87 register_count_(register_count), 88 parameter_count_(parameter_count), 89 context_(context), 90 control_dependency_(control_dependency), 91 effect_dependency_(control_dependency), 92 values_(builder->local_zone()), 93 parameters_state_values_(nullptr), 94 registers_state_values_(nullptr), 95 accumulator_state_values_(nullptr) { 96 // The layout of values_ is: 97 // 98 // [receiver] [parameters] [registers] [accumulator] 99 // 100 // parameter[0] is the receiver (this), parameters 1..N are the 101 // parameters supplied to the method (arg0..argN-1). The accumulator 102 // is stored separately. 103 104 // Parameters including the receiver 105 for (int i = 0; i < parameter_count; i++) { 106 const char* debug_name = (i == 0) ? "%this" : nullptr; 107 const Operator* op = common()->Parameter(i, debug_name); 108 Node* parameter = builder->graph()->NewNode(op, graph()->start()); 109 values()->push_back(parameter); 110 } 111 112 // Registers 113 register_base_ = static_cast<int>(values()->size()); 114 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); 115 values()->insert(values()->end(), register_count, undefined_constant); 116 117 // Accumulator 118 accumulator_base_ = static_cast<int>(values()->size()); 119 values()->push_back(undefined_constant); 120 } 121 122 123 BytecodeGraphBuilder::Environment::Environment( 124 const BytecodeGraphBuilder::Environment* other) 125 : builder_(other->builder_), 126 register_count_(other->register_count_), 127 parameter_count_(other->parameter_count_), 128 context_(other->context_), 129 control_dependency_(other->control_dependency_), 130 effect_dependency_(other->effect_dependency_), 131 values_(other->zone()), 132 parameters_state_values_(nullptr), 133 registers_state_values_(nullptr), 134 accumulator_state_values_(nullptr), 135 register_base_(other->register_base_), 136 accumulator_base_(other->accumulator_base_) { 137 values_ = other->values_; 138 } 139 140 141 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( 142 interpreter::Register the_register) const { 143 if (the_register.is_parameter()) { 144 return the_register.ToParameterIndex(parameter_count()); 145 } else { 146 return the_register.index() + register_base(); 147 } 148 } 149 150 151 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { 152 return values()->at(accumulator_base_); 153 } 154 155 156 Node* BytecodeGraphBuilder::Environment::LookupRegister( 157 interpreter::Register the_register) const { 158 if (the_register.is_function_context()) { 159 return builder()->GetFunctionContext(); 160 } else if (the_register.is_function_closure()) { 161 return builder()->GetFunctionClosure(); 162 } else if (the_register.is_new_target()) { 163 return builder()->GetNewTarget(); 164 } else { 165 int values_index = RegisterToValuesIndex(the_register); 166 return values()->at(values_index); 167 } 168 } 169 170 171 void BytecodeGraphBuilder::Environment::ExchangeRegisters( 172 interpreter::Register reg0, interpreter::Register reg1) { 173 int reg0_index = RegisterToValuesIndex(reg0); 174 int reg1_index = RegisterToValuesIndex(reg1); 175 Node* saved_reg0_value = values()->at(reg0_index); 176 values()->at(reg0_index) = values()->at(reg1_index); 177 values()->at(reg1_index) = saved_reg0_value; 178 } 179 180 181 void BytecodeGraphBuilder::Environment::BindAccumulator( 182 Node* node, FrameStateBeforeAndAfter* states) { 183 if (states) { 184 states->AddToNode(node, OutputFrameStateCombine::PokeAt(0)); 185 } 186 values()->at(accumulator_base_) = node; 187 } 188 189 190 void BytecodeGraphBuilder::Environment::BindRegister( 191 interpreter::Register the_register, Node* node, 192 FrameStateBeforeAndAfter* states) { 193 int values_index = RegisterToValuesIndex(the_register); 194 if (states) { 195 states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ - 196 values_index)); 197 } 198 values()->at(values_index) = node; 199 } 200 201 202 void BytecodeGraphBuilder::Environment::BindRegistersToProjections( 203 interpreter::Register first_reg, Node* node, 204 FrameStateBeforeAndAfter* states) { 205 int values_index = RegisterToValuesIndex(first_reg); 206 if (states) { 207 states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ - 208 values_index)); 209 } 210 for (int i = 0; i < node->op()->ValueOutputCount(); i++) { 211 values()->at(values_index + i) = 212 builder()->NewNode(common()->Projection(i), node); 213 } 214 } 215 216 217 void BytecodeGraphBuilder::Environment::RecordAfterState( 218 Node* node, FrameStateBeforeAndAfter* states) { 219 states->AddToNode(node, OutputFrameStateCombine::Ignore()); 220 } 221 222 223 bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const { 224 return GetControlDependency()->opcode() == IrOpcode::kDead; 225 } 226 227 228 void BytecodeGraphBuilder::Environment::MarkAsUnreachable() { 229 UpdateControlDependency(builder()->jsgraph()->Dead()); 230 } 231 232 233 BytecodeGraphBuilder::Environment* 234 BytecodeGraphBuilder::Environment::CopyForLoop() { 235 PrepareForLoop(); 236 return new (zone()) Environment(this); 237 } 238 239 240 BytecodeGraphBuilder::Environment* 241 BytecodeGraphBuilder::Environment::CopyForConditional() const { 242 return new (zone()) Environment(this); 243 } 244 245 246 void BytecodeGraphBuilder::Environment::Merge( 247 BytecodeGraphBuilder::Environment* other) { 248 // Nothing to do if the other environment is dead. 249 if (other->IsMarkedAsUnreachable()) { 250 return; 251 } 252 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 274 void BytecodeGraphBuilder::Environment::PrepareForLoop() { 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 // Assume everything in the loop is updated. 283 context_ = builder()->NewPhi(1, context_, control); 284 int size = static_cast<int>(values()->size()); 285 for (int i = 0; i < size; i++) { 286 values()->at(i) = builder()->NewPhi(1, values()->at(i), control); 287 } 288 289 // Connect to the loop end. 290 Node* terminate = builder()->graph()->NewNode( 291 builder()->common()->Terminate(), effect, control); 292 builder()->exit_controls_.push_back(terminate); 293 } 294 295 296 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( 297 Node** state_values, int offset, int count) { 298 if (!builder()->info()->is_deoptimization_enabled()) { 299 return false; 300 } 301 if (*state_values == nullptr) { 302 return true; 303 } 304 DCHECK_EQ((*state_values)->InputCount(), count); 305 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); 306 Node** env_values = (count == 0) ? nullptr : &values()->at(offset); 307 for (int i = 0; i < count; i++) { 308 if ((*state_values)->InputAt(i) != env_values[i]) { 309 return true; 310 } 311 } 312 return false; 313 } 314 315 316 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, 317 int offset, 318 int count) { 319 if (StateValuesRequireUpdate(state_values, offset, count)) { 320 const Operator* op = common()->StateValues(count); 321 (*state_values) = graph()->NewNode(op, count, &values()->at(offset)); 322 } 323 } 324 325 326 Node* BytecodeGraphBuilder::Environment::Checkpoint( 327 BailoutId bailout_id, OutputFrameStateCombine combine) { 328 if (!builder()->info()->is_deoptimization_enabled()) { 329 return builder()->jsgraph()->EmptyFrameState(); 330 } 331 332 // TODO(rmcilroy): Consider using StateValuesCache for some state values. 333 UpdateStateValues(¶meters_state_values_, 0, parameter_count()); 334 UpdateStateValues(®isters_state_values_, register_base(), 335 register_count()); 336 UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1); 337 338 const Operator* op = common()->FrameState( 339 bailout_id, combine, builder()->frame_state_function_info()); 340 Node* result = graph()->NewNode( 341 op, parameters_state_values_, registers_state_values_, 342 accumulator_state_values_, Context(), builder()->GetFunctionClosure(), 343 builder()->graph()->start()); 344 345 return result; 346 } 347 348 349 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( 350 Node** state_values, int offset, int count, int output_poke_start, 351 int output_poke_end) { 352 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); 353 for (int i = 0; i < count; i++, offset++) { 354 if (offset < output_poke_start || offset >= output_poke_end) { 355 if ((*state_values)->InputAt(i) != values()->at(offset)) { 356 return false; 357 } 358 } 359 } 360 return true; 361 } 362 363 364 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( 365 int output_poke_offset, int output_poke_count) { 366 // Poke offset is relative to the top of the stack (i.e., the accumulator). 367 int output_poke_start = accumulator_base() - output_poke_offset; 368 int output_poke_end = output_poke_start + output_poke_count; 369 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(), 370 output_poke_start, output_poke_end) && 371 StateValuesAreUpToDate(®isters_state_values_, register_base(), 372 register_count(), output_poke_start, 373 output_poke_end) && 374 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(), 375 1, output_poke_start, output_poke_end); 376 } 377 378 379 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, 380 CompilationInfo* compilation_info, 381 JSGraph* jsgraph) 382 : local_zone_(local_zone), 383 info_(compilation_info), 384 jsgraph_(jsgraph), 385 bytecode_array_(handle(info()->shared_info()->bytecode_array())), 386 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( 387 FrameStateType::kInterpretedFunction, 388 bytecode_array()->parameter_count(), 389 bytecode_array()->register_count(), info()->shared_info(), 390 CALL_MAINTAINS_NATIVE_CONTEXT)), 391 merge_environments_(local_zone), 392 loop_header_environments_(local_zone), 393 input_buffer_size_(0), 394 input_buffer_(nullptr), 395 exit_controls_(local_zone) {} 396 397 398 Node* BytecodeGraphBuilder::GetNewTarget() { 399 if (!new_target_.is_set()) { 400 int params = bytecode_array()->parameter_count(); 401 int index = Linkage::GetJSCallNewTargetParamIndex(params); 402 const Operator* op = common()->Parameter(index, "%new.target"); 403 Node* node = NewNode(op, graph()->start()); 404 new_target_.set(node); 405 } 406 return new_target_.get(); 407 } 408 409 410 Node* BytecodeGraphBuilder::GetFunctionContext() { 411 if (!function_context_.is_set()) { 412 int params = bytecode_array()->parameter_count(); 413 int index = Linkage::GetJSCallContextParamIndex(params); 414 const Operator* op = common()->Parameter(index, "%context"); 415 Node* node = NewNode(op, graph()->start()); 416 function_context_.set(node); 417 } 418 return function_context_.get(); 419 } 420 421 422 Node* BytecodeGraphBuilder::GetFunctionClosure() { 423 if (!function_closure_.is_set()) { 424 int index = Linkage::kJSCallClosureParamIndex; 425 const Operator* op = common()->Parameter(index, "%closure"); 426 Node* node = NewNode(op, graph()->start()); 427 function_closure_.set(node); 428 } 429 return function_closure_.get(); 430 } 431 432 433 Node* BytecodeGraphBuilder::BuildLoadObjectField(Node* object, int offset) { 434 return NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()), object, 435 jsgraph()->IntPtrConstant(offset - kHeapObjectTag)); 436 } 437 438 439 Node* BytecodeGraphBuilder::BuildLoadImmutableObjectField(Node* object, 440 int offset) { 441 return graph()->NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()), 442 object, 443 jsgraph()->IntPtrConstant(offset - kHeapObjectTag), 444 graph()->start(), graph()->start()); 445 } 446 447 448 Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) { 449 const Operator* op = 450 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true); 451 Node* native_context = NewNode(op, environment()->Context()); 452 return NewNode(javascript()->LoadContext(0, index, true), native_context); 453 } 454 455 456 Node* BytecodeGraphBuilder::BuildLoadFeedbackVector() { 457 if (!feedback_vector_.is_set()) { 458 Node* closure = GetFunctionClosure(); 459 Node* shared = BuildLoadImmutableObjectField( 460 closure, JSFunction::kSharedFunctionInfoOffset); 461 Node* vector = BuildLoadImmutableObjectField( 462 shared, SharedFunctionInfo::kFeedbackVectorOffset); 463 feedback_vector_.set(vector); 464 } 465 return feedback_vector_.get(); 466 } 467 468 469 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { 470 Handle<TypeFeedbackVector> feedback_vector = info()->feedback_vector(); 471 FeedbackVectorSlot slot; 472 if (slot_id >= TypeFeedbackVector::kReservedIndexCount) { 473 slot = feedback_vector->ToSlot(slot_id); 474 } 475 return VectorSlotPair(feedback_vector, slot); 476 } 477 478 479 bool BytecodeGraphBuilder::CreateGraph(bool stack_check) { 480 // Set up the basic structure of the graph. Outputs for {Start} are 481 // the formal parameters (including the receiver) plus context and 482 // closure. 483 484 // Set up the basic structure of the graph. Outputs for {Start} are the formal 485 // parameters (including the receiver) plus new target, number of arguments, 486 // context and closure. 487 int actual_parameter_count = bytecode_array()->parameter_count() + 4; 488 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count))); 489 490 Environment env(this, bytecode_array()->register_count(), 491 bytecode_array()->parameter_count(), graph()->start(), 492 GetFunctionContext()); 493 set_environment(&env); 494 495 CreateGraphBody(stack_check); 496 497 // Finish the basic structure of the graph. 498 DCHECK_NE(0u, exit_controls_.size()); 499 int const input_count = static_cast<int>(exit_controls_.size()); 500 Node** const inputs = &exit_controls_.front(); 501 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); 502 graph()->SetEnd(end); 503 504 return true; 505 } 506 507 508 void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) { 509 // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments 510 // object setup, this function variable if used, tracing hooks. 511 512 if (stack_check) { 513 Node* node = NewNode(javascript()->StackCheck()); 514 PrepareEntryFrameState(node); 515 } 516 517 VisitBytecodes(); 518 } 519 520 521 void BytecodeGraphBuilder::VisitBytecodes() { 522 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); 523 analysis.Analyze(); 524 set_branch_analysis(&analysis); 525 interpreter::BytecodeArrayIterator iterator(bytecode_array()); 526 set_bytecode_iterator(&iterator); 527 while (!iterator.done()) { 528 int current_offset = iterator.current_offset(); 529 if (analysis.is_reachable(current_offset)) { 530 MergeEnvironmentsOfForwardBranches(current_offset); 531 BuildLoopHeaderForBackwardBranches(current_offset); 532 533 switch (iterator.current_bytecode()) { 534 #define BYTECODE_CASE(name, ...) \ 535 case interpreter::Bytecode::k##name: \ 536 Visit##name(iterator); \ 537 break; 538 BYTECODE_LIST(BYTECODE_CASE) 539 #undef BYTECODE_CODE 540 } 541 } 542 iterator.Advance(); 543 } 544 set_branch_analysis(nullptr); 545 set_bytecode_iterator(nullptr); 546 } 547 548 549 void BytecodeGraphBuilder::VisitLdaZero( 550 const interpreter::BytecodeArrayIterator& iterator) { 551 Node* node = jsgraph()->ZeroConstant(); 552 environment()->BindAccumulator(node); 553 } 554 555 556 void BytecodeGraphBuilder::VisitLdaSmi8( 557 const interpreter::BytecodeArrayIterator& iterator) { 558 Node* node = jsgraph()->Constant(iterator.GetImmediateOperand(0)); 559 environment()->BindAccumulator(node); 560 } 561 562 563 void BytecodeGraphBuilder::VisitLdaConstantWide( 564 const interpreter::BytecodeArrayIterator& iterator) { 565 Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0)); 566 environment()->BindAccumulator(node); 567 } 568 569 570 void BytecodeGraphBuilder::VisitLdaConstant( 571 const interpreter::BytecodeArrayIterator& iterator) { 572 Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0)); 573 environment()->BindAccumulator(node); 574 } 575 576 577 void BytecodeGraphBuilder::VisitLdaUndefined( 578 const interpreter::BytecodeArrayIterator& iterator) { 579 Node* node = jsgraph()->UndefinedConstant(); 580 environment()->BindAccumulator(node); 581 } 582 583 584 void BytecodeGraphBuilder::VisitLdaNull( 585 const interpreter::BytecodeArrayIterator& iterator) { 586 Node* node = jsgraph()->NullConstant(); 587 environment()->BindAccumulator(node); 588 } 589 590 591 void BytecodeGraphBuilder::VisitLdaTheHole( 592 const interpreter::BytecodeArrayIterator& iterator) { 593 Node* node = jsgraph()->TheHoleConstant(); 594 environment()->BindAccumulator(node); 595 } 596 597 598 void BytecodeGraphBuilder::VisitLdaTrue( 599 const interpreter::BytecodeArrayIterator& iterator) { 600 Node* node = jsgraph()->TrueConstant(); 601 environment()->BindAccumulator(node); 602 } 603 604 605 void BytecodeGraphBuilder::VisitLdaFalse( 606 const interpreter::BytecodeArrayIterator& iterator) { 607 Node* node = jsgraph()->FalseConstant(); 608 environment()->BindAccumulator(node); 609 } 610 611 612 void BytecodeGraphBuilder::VisitLdar( 613 const interpreter::BytecodeArrayIterator& iterator) { 614 Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 615 environment()->BindAccumulator(value); 616 } 617 618 619 void BytecodeGraphBuilder::VisitStar( 620 const interpreter::BytecodeArrayIterator& iterator) { 621 Node* value = environment()->LookupAccumulator(); 622 environment()->BindRegister(iterator.GetRegisterOperand(0), value); 623 } 624 625 626 void BytecodeGraphBuilder::VisitMov( 627 const interpreter::BytecodeArrayIterator& iterator) { 628 Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 629 environment()->BindRegister(iterator.GetRegisterOperand(1), value); 630 } 631 632 633 void BytecodeGraphBuilder::VisitExchange( 634 const interpreter::BytecodeArrayIterator& iterator) { 635 environment()->ExchangeRegisters(iterator.GetRegisterOperand(0), 636 iterator.GetRegisterOperand(1)); 637 } 638 639 640 void BytecodeGraphBuilder::VisitExchangeWide( 641 const interpreter::BytecodeArrayIterator& iterator) { 642 environment()->ExchangeRegisters(iterator.GetRegisterOperand(0), 643 iterator.GetRegisterOperand(1)); 644 } 645 646 647 void BytecodeGraphBuilder::BuildLoadGlobal( 648 const interpreter::BytecodeArrayIterator& iterator, 649 TypeofMode typeof_mode) { 650 FrameStateBeforeAndAfter states(this, iterator); 651 Handle<Name> name = 652 Handle<Name>::cast(iterator.GetConstantForIndexOperand(0)); 653 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1)); 654 655 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode); 656 Node* node = NewNode(op, BuildLoadFeedbackVector()); 657 environment()->BindAccumulator(node, &states); 658 } 659 660 661 void BytecodeGraphBuilder::VisitLdaGlobalSloppy( 662 const interpreter::BytecodeArrayIterator& iterator) { 663 DCHECK(is_sloppy(language_mode())); 664 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF); 665 } 666 667 668 void BytecodeGraphBuilder::VisitLdaGlobalStrict( 669 const interpreter::BytecodeArrayIterator& iterator) { 670 DCHECK(is_strict(language_mode())); 671 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF); 672 } 673 674 675 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppy( 676 const interpreter::BytecodeArrayIterator& iterator) { 677 DCHECK(is_sloppy(language_mode())); 678 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF); 679 } 680 681 682 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrict( 683 const interpreter::BytecodeArrayIterator& iterator) { 684 DCHECK(is_strict(language_mode())); 685 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF); 686 } 687 688 689 void BytecodeGraphBuilder::VisitLdaGlobalSloppyWide( 690 const interpreter::BytecodeArrayIterator& iterator) { 691 DCHECK(is_sloppy(language_mode())); 692 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF); 693 } 694 695 696 void BytecodeGraphBuilder::VisitLdaGlobalStrictWide( 697 const interpreter::BytecodeArrayIterator& iterator) { 698 DCHECK(is_strict(language_mode())); 699 BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF); 700 } 701 702 703 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppyWide( 704 const interpreter::BytecodeArrayIterator& iterator) { 705 DCHECK(is_sloppy(language_mode())); 706 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF); 707 } 708 709 710 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrictWide( 711 const interpreter::BytecodeArrayIterator& iterator) { 712 DCHECK(is_strict(language_mode())); 713 BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF); 714 } 715 716 717 void BytecodeGraphBuilder::BuildStoreGlobal( 718 const interpreter::BytecodeArrayIterator& iterator) { 719 FrameStateBeforeAndAfter states(this, iterator); 720 Handle<Name> name = 721 Handle<Name>::cast(iterator.GetConstantForIndexOperand(0)); 722 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1)); 723 Node* value = environment()->LookupAccumulator(); 724 725 const Operator* op = 726 javascript()->StoreGlobal(language_mode(), name, feedback); 727 Node* node = NewNode(op, value, BuildLoadFeedbackVector()); 728 environment()->RecordAfterState(node, &states); 729 } 730 731 732 void BytecodeGraphBuilder::VisitStaGlobalSloppy( 733 const interpreter::BytecodeArrayIterator& iterator) { 734 DCHECK(is_sloppy(language_mode())); 735 BuildStoreGlobal(iterator); 736 } 737 738 739 void BytecodeGraphBuilder::VisitStaGlobalStrict( 740 const interpreter::BytecodeArrayIterator& iterator) { 741 DCHECK(is_strict(language_mode())); 742 BuildStoreGlobal(iterator); 743 } 744 745 void BytecodeGraphBuilder::VisitStaGlobalSloppyWide( 746 const interpreter::BytecodeArrayIterator& iterator) { 747 DCHECK(is_sloppy(language_mode())); 748 BuildStoreGlobal(iterator); 749 } 750 751 752 void BytecodeGraphBuilder::VisitStaGlobalStrictWide( 753 const interpreter::BytecodeArrayIterator& iterator) { 754 DCHECK(is_strict(language_mode())); 755 BuildStoreGlobal(iterator); 756 } 757 758 759 void BytecodeGraphBuilder::VisitLdaContextSlot( 760 const interpreter::BytecodeArrayIterator& iterator) { 761 // TODO(mythria): LoadContextSlots are unrolled by the required depth when 762 // generating bytecode. Hence the value of depth is always 0. Update this 763 // code, when the implementation changes. 764 // TODO(mythria): immutable flag is also set to false. This information is not 765 // available in bytecode array. update this code when the implementation 766 // changes. 767 const Operator* op = 768 javascript()->LoadContext(0, iterator.GetIndexOperand(1), false); 769 Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 770 Node* node = NewNode(op, context); 771 environment()->BindAccumulator(node); 772 } 773 774 775 void BytecodeGraphBuilder::VisitLdaContextSlotWide( 776 const interpreter::BytecodeArrayIterator& iterator) { 777 VisitLdaContextSlot(iterator); 778 } 779 780 781 void BytecodeGraphBuilder::VisitStaContextSlot( 782 const interpreter::BytecodeArrayIterator& iterator) { 783 // TODO(mythria): LoadContextSlots are unrolled by the required depth when 784 // generating bytecode. Hence the value of depth is always 0. Update this 785 // code, when the implementation changes. 786 const Operator* op = 787 javascript()->StoreContext(0, iterator.GetIndexOperand(1)); 788 Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 789 Node* value = environment()->LookupAccumulator(); 790 NewNode(op, context, value); 791 } 792 793 794 void BytecodeGraphBuilder::VisitStaContextSlotWide( 795 const interpreter::BytecodeArrayIterator& iterator) { 796 VisitStaContextSlot(iterator); 797 } 798 799 800 void BytecodeGraphBuilder::BuildLdaLookupSlot( 801 TypeofMode typeof_mode, 802 const interpreter::BytecodeArrayIterator& iterator) { 803 FrameStateBeforeAndAfter states(this, iterator); 804 Handle<String> name = 805 Handle<String>::cast(iterator.GetConstantForIndexOperand(0)); 806 const Operator* op = javascript()->LoadDynamic(name, typeof_mode); 807 Node* value = 808 NewNode(op, BuildLoadFeedbackVector(), environment()->Context()); 809 environment()->BindAccumulator(value, &states); 810 } 811 812 813 void BytecodeGraphBuilder::VisitLdaLookupSlot( 814 const interpreter::BytecodeArrayIterator& iterator) { 815 BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF, iterator); 816 } 817 818 819 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof( 820 const interpreter::BytecodeArrayIterator& iterator) { 821 BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF, iterator); 822 } 823 824 825 void BytecodeGraphBuilder::BuildStaLookupSlot( 826 LanguageMode language_mode, 827 const interpreter::BytecodeArrayIterator& iterator) { 828 FrameStateBeforeAndAfter states(this, iterator); 829 Node* value = environment()->LookupAccumulator(); 830 Node* name = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0)); 831 Node* language = jsgraph()->Constant(language_mode); 832 const Operator* op = javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4); 833 Node* store = NewNode(op, value, environment()->Context(), name, language); 834 environment()->BindAccumulator(store, &states); 835 } 836 837 838 void BytecodeGraphBuilder::VisitLdaLookupSlotWide( 839 const interpreter::BytecodeArrayIterator& iterator) { 840 VisitLdaLookupSlot(iterator); 841 } 842 843 844 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeofWide( 845 const interpreter::BytecodeArrayIterator& iterator) { 846 VisitLdaLookupSlotInsideTypeof(iterator); 847 } 848 849 850 void BytecodeGraphBuilder::VisitStaLookupSlotSloppy( 851 const interpreter::BytecodeArrayIterator& iterator) { 852 BuildStaLookupSlot(LanguageMode::SLOPPY, iterator); 853 } 854 855 856 void BytecodeGraphBuilder::VisitStaLookupSlotStrict( 857 const interpreter::BytecodeArrayIterator& iterator) { 858 BuildStaLookupSlot(LanguageMode::STRICT, iterator); 859 } 860 861 862 void BytecodeGraphBuilder::VisitStaLookupSlotSloppyWide( 863 const interpreter::BytecodeArrayIterator& iterator) { 864 VisitStaLookupSlotSloppy(iterator); 865 } 866 867 868 void BytecodeGraphBuilder::VisitStaLookupSlotStrictWide( 869 const interpreter::BytecodeArrayIterator& iterator) { 870 VisitStaLookupSlotStrict(iterator); 871 } 872 873 874 void BytecodeGraphBuilder::BuildNamedLoad( 875 const interpreter::BytecodeArrayIterator& iterator) { 876 FrameStateBeforeAndAfter states(this, iterator); 877 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 878 Handle<Name> name = 879 Handle<Name>::cast(iterator.GetConstantForIndexOperand(1)); 880 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2)); 881 882 const Operator* op = javascript()->LoadNamed(language_mode(), name, feedback); 883 Node* node = NewNode(op, object, BuildLoadFeedbackVector()); 884 environment()->BindAccumulator(node, &states); 885 } 886 887 888 void BytecodeGraphBuilder::VisitLoadICSloppy( 889 const interpreter::BytecodeArrayIterator& iterator) { 890 DCHECK(is_sloppy(language_mode())); 891 BuildNamedLoad(iterator); 892 } 893 894 895 void BytecodeGraphBuilder::VisitLoadICStrict( 896 const interpreter::BytecodeArrayIterator& iterator) { 897 DCHECK(is_strict(language_mode())); 898 BuildNamedLoad(iterator); 899 } 900 901 902 void BytecodeGraphBuilder::VisitLoadICSloppyWide( 903 const interpreter::BytecodeArrayIterator& iterator) { 904 DCHECK(is_sloppy(language_mode())); 905 BuildNamedLoad(iterator); 906 } 907 908 909 void BytecodeGraphBuilder::VisitLoadICStrictWide( 910 const interpreter::BytecodeArrayIterator& iterator) { 911 DCHECK(is_strict(language_mode())); 912 BuildNamedLoad(iterator); 913 } 914 915 916 void BytecodeGraphBuilder::BuildKeyedLoad( 917 const interpreter::BytecodeArrayIterator& iterator) { 918 FrameStateBeforeAndAfter states(this, iterator); 919 Node* key = environment()->LookupAccumulator(); 920 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 921 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1)); 922 923 const Operator* op = javascript()->LoadProperty(language_mode(), feedback); 924 Node* node = NewNode(op, object, key, BuildLoadFeedbackVector()); 925 environment()->BindAccumulator(node, &states); 926 } 927 928 929 void BytecodeGraphBuilder::VisitKeyedLoadICSloppy( 930 const interpreter::BytecodeArrayIterator& iterator) { 931 DCHECK(is_sloppy(language_mode())); 932 BuildKeyedLoad(iterator); 933 } 934 935 936 void BytecodeGraphBuilder::VisitKeyedLoadICStrict( 937 const interpreter::BytecodeArrayIterator& iterator) { 938 DCHECK(is_strict(language_mode())); 939 BuildKeyedLoad(iterator); 940 } 941 942 943 void BytecodeGraphBuilder::VisitKeyedLoadICSloppyWide( 944 const interpreter::BytecodeArrayIterator& iterator) { 945 DCHECK(is_sloppy(language_mode())); 946 BuildKeyedLoad(iterator); 947 } 948 949 950 void BytecodeGraphBuilder::VisitKeyedLoadICStrictWide( 951 const interpreter::BytecodeArrayIterator& iterator) { 952 DCHECK(is_strict(language_mode())); 953 BuildKeyedLoad(iterator); 954 } 955 956 957 void BytecodeGraphBuilder::BuildNamedStore( 958 const interpreter::BytecodeArrayIterator& iterator) { 959 FrameStateBeforeAndAfter states(this, iterator); 960 Node* value = environment()->LookupAccumulator(); 961 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 962 Handle<Name> name = 963 Handle<Name>::cast(iterator.GetConstantForIndexOperand(1)); 964 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2)); 965 966 const Operator* op = 967 javascript()->StoreNamed(language_mode(), name, feedback); 968 Node* node = NewNode(op, object, value, BuildLoadFeedbackVector()); 969 environment()->RecordAfterState(node, &states); 970 } 971 972 973 void BytecodeGraphBuilder::VisitStoreICSloppy( 974 const interpreter::BytecodeArrayIterator& iterator) { 975 DCHECK(is_sloppy(language_mode())); 976 BuildNamedStore(iterator); 977 } 978 979 980 void BytecodeGraphBuilder::VisitStoreICStrict( 981 const interpreter::BytecodeArrayIterator& iterator) { 982 DCHECK(is_strict(language_mode())); 983 BuildNamedStore(iterator); 984 } 985 986 987 void BytecodeGraphBuilder::VisitStoreICSloppyWide( 988 const interpreter::BytecodeArrayIterator& iterator) { 989 DCHECK(is_sloppy(language_mode())); 990 BuildNamedStore(iterator); 991 } 992 993 994 void BytecodeGraphBuilder::VisitStoreICStrictWide( 995 const interpreter::BytecodeArrayIterator& iterator) { 996 DCHECK(is_strict(language_mode())); 997 BuildNamedStore(iterator); 998 } 999 1000 1001 void BytecodeGraphBuilder::BuildKeyedStore( 1002 const interpreter::BytecodeArrayIterator& iterator) { 1003 FrameStateBeforeAndAfter states(this, iterator); 1004 Node* value = environment()->LookupAccumulator(); 1005 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 1006 Node* key = environment()->LookupRegister(iterator.GetRegisterOperand(1)); 1007 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2)); 1008 1009 const Operator* op = javascript()->StoreProperty(language_mode(), feedback); 1010 Node* node = NewNode(op, object, key, value, BuildLoadFeedbackVector()); 1011 environment()->RecordAfterState(node, &states); 1012 } 1013 1014 1015 void BytecodeGraphBuilder::VisitKeyedStoreICSloppy( 1016 const interpreter::BytecodeArrayIterator& iterator) { 1017 DCHECK(is_sloppy(language_mode())); 1018 BuildKeyedStore(iterator); 1019 } 1020 1021 1022 void BytecodeGraphBuilder::VisitKeyedStoreICStrict( 1023 const interpreter::BytecodeArrayIterator& iterator) { 1024 DCHECK(is_strict(language_mode())); 1025 BuildKeyedStore(iterator); 1026 } 1027 1028 1029 void BytecodeGraphBuilder::VisitKeyedStoreICSloppyWide( 1030 const interpreter::BytecodeArrayIterator& iterator) { 1031 DCHECK(is_sloppy(language_mode())); 1032 BuildKeyedStore(iterator); 1033 } 1034 1035 1036 void BytecodeGraphBuilder::VisitKeyedStoreICStrictWide( 1037 const interpreter::BytecodeArrayIterator& iterator) { 1038 DCHECK(is_strict(language_mode())); 1039 BuildKeyedStore(iterator); 1040 } 1041 1042 1043 void BytecodeGraphBuilder::VisitPushContext( 1044 const interpreter::BytecodeArrayIterator& iterator) { 1045 Node* context = environment()->LookupAccumulator(); 1046 environment()->BindRegister(iterator.GetRegisterOperand(0), context); 1047 environment()->SetContext(context); 1048 } 1049 1050 1051 void BytecodeGraphBuilder::VisitPopContext( 1052 const interpreter::BytecodeArrayIterator& iterator) { 1053 Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 1054 environment()->SetContext(context); 1055 } 1056 1057 1058 void BytecodeGraphBuilder::VisitCreateClosure( 1059 const interpreter::BytecodeArrayIterator& iterator) { 1060 Handle<SharedFunctionInfo> shared_info = 1061 Handle<SharedFunctionInfo>::cast(iterator.GetConstantForIndexOperand(0)); 1062 PretenureFlag tenured = 1063 iterator.GetImmediateOperand(1) ? TENURED : NOT_TENURED; 1064 const Operator* op = javascript()->CreateClosure(shared_info, tenured); 1065 Node* closure = NewNode(op); 1066 environment()->BindAccumulator(closure); 1067 } 1068 1069 1070 void BytecodeGraphBuilder::VisitCreateClosureWide( 1071 const interpreter::BytecodeArrayIterator& iterator) { 1072 VisitCreateClosure(iterator); 1073 } 1074 1075 1076 void BytecodeGraphBuilder::BuildCreateArguments( 1077 CreateArgumentsParameters::Type type, 1078 const interpreter::BytecodeArrayIterator& iterator) { 1079 FrameStateBeforeAndAfter states(this, iterator); 1080 const Operator* op = javascript()->CreateArguments(type, 0); 1081 Node* object = NewNode(op, GetFunctionClosure()); 1082 environment()->BindAccumulator(object, &states); 1083 } 1084 1085 1086 void BytecodeGraphBuilder::VisitCreateMappedArguments( 1087 const interpreter::BytecodeArrayIterator& iterator) { 1088 BuildCreateArguments(CreateArgumentsParameters::kMappedArguments, iterator); 1089 } 1090 1091 1092 void BytecodeGraphBuilder::VisitCreateUnmappedArguments( 1093 const interpreter::BytecodeArrayIterator& iterator) { 1094 BuildCreateArguments(CreateArgumentsParameters::kUnmappedArguments, iterator); 1095 } 1096 1097 1098 void BytecodeGraphBuilder::BuildCreateLiteral( 1099 const Operator* op, const interpreter::BytecodeArrayIterator& iterator) { 1100 FrameStateBeforeAndAfter states(this, iterator); 1101 Node* literal = NewNode(op, GetFunctionClosure()); 1102 environment()->BindAccumulator(literal, &states); 1103 } 1104 1105 1106 void BytecodeGraphBuilder::BuildCreateRegExpLiteral( 1107 const interpreter::BytecodeArrayIterator& iterator) { 1108 Handle<String> constant_pattern = 1109 Handle<String>::cast(iterator.GetConstantForIndexOperand(0)); 1110 int literal_index = iterator.GetIndexOperand(1); 1111 int literal_flags = iterator.GetImmediateOperand(2); 1112 const Operator* op = javascript()->CreateLiteralRegExp( 1113 constant_pattern, literal_flags, literal_index); 1114 BuildCreateLiteral(op, iterator); 1115 } 1116 1117 1118 void BytecodeGraphBuilder::VisitCreateRegExpLiteral( 1119 const interpreter::BytecodeArrayIterator& iterator) { 1120 BuildCreateRegExpLiteral(iterator); 1121 } 1122 1123 1124 void BytecodeGraphBuilder::VisitCreateRegExpLiteralWide( 1125 const interpreter::BytecodeArrayIterator& iterator) { 1126 BuildCreateRegExpLiteral(iterator); 1127 } 1128 1129 1130 void BytecodeGraphBuilder::BuildCreateArrayLiteral( 1131 const interpreter::BytecodeArrayIterator& iterator) { 1132 Handle<FixedArray> constant_elements = 1133 Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0)); 1134 int literal_index = iterator.GetIndexOperand(1); 1135 int literal_flags = iterator.GetImmediateOperand(2); 1136 const Operator* op = javascript()->CreateLiteralArray( 1137 constant_elements, literal_flags, literal_index); 1138 BuildCreateLiteral(op, iterator); 1139 } 1140 1141 1142 void BytecodeGraphBuilder::VisitCreateArrayLiteral( 1143 const interpreter::BytecodeArrayIterator& iterator) { 1144 BuildCreateArrayLiteral(iterator); 1145 } 1146 1147 1148 void BytecodeGraphBuilder::VisitCreateArrayLiteralWide( 1149 const interpreter::BytecodeArrayIterator& iterator) { 1150 BuildCreateArrayLiteral(iterator); 1151 } 1152 1153 1154 void BytecodeGraphBuilder::BuildCreateObjectLiteral( 1155 const interpreter::BytecodeArrayIterator& iterator) { 1156 Handle<FixedArray> constant_properties = 1157 Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0)); 1158 int literal_index = iterator.GetIndexOperand(1); 1159 int literal_flags = iterator.GetImmediateOperand(2); 1160 const Operator* op = javascript()->CreateLiteralObject( 1161 constant_properties, literal_flags, literal_index); 1162 BuildCreateLiteral(op, iterator); 1163 } 1164 1165 1166 void BytecodeGraphBuilder::VisitCreateObjectLiteral( 1167 const interpreter::BytecodeArrayIterator& iterator) { 1168 BuildCreateObjectLiteral(iterator); 1169 } 1170 1171 1172 void BytecodeGraphBuilder::VisitCreateObjectLiteralWide( 1173 const interpreter::BytecodeArrayIterator& iterator) { 1174 BuildCreateObjectLiteral(iterator); 1175 } 1176 1177 1178 Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, 1179 Node* callee, 1180 interpreter::Register receiver, 1181 size_t arity) { 1182 Node** all = info()->zone()->NewArray<Node*>(static_cast<int>(arity)); 1183 all[0] = callee; 1184 all[1] = environment()->LookupRegister(receiver); 1185 int receiver_index = receiver.index(); 1186 for (int i = 2; i < static_cast<int>(arity); ++i) { 1187 all[i] = environment()->LookupRegister( 1188 interpreter::Register(receiver_index + i - 1)); 1189 } 1190 Node* value = MakeNode(call_op, static_cast<int>(arity), all, false); 1191 return value; 1192 } 1193 1194 1195 void BytecodeGraphBuilder::BuildCall( 1196 const interpreter::BytecodeArrayIterator& iterator) { 1197 FrameStateBeforeAndAfter states(this, iterator); 1198 // TODO(rmcilroy): Set receiver_hint correctly based on whether the receiver 1199 // register has been loaded with null / undefined explicitly or we are sure it 1200 // is not null / undefined. 1201 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny; 1202 Node* callee = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 1203 interpreter::Register receiver = iterator.GetRegisterOperand(1); 1204 size_t arg_count = iterator.GetCountOperand(2); 1205 VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(3)); 1206 1207 const Operator* call = javascript()->CallFunction( 1208 arg_count + 2, language_mode(), feedback, receiver_hint); 1209 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2); 1210 environment()->BindAccumulator(value, &states); 1211 } 1212 1213 1214 void BytecodeGraphBuilder::VisitCall( 1215 const interpreter::BytecodeArrayIterator& iterator) { 1216 BuildCall(iterator); 1217 } 1218 1219 1220 void BytecodeGraphBuilder::VisitCallWide( 1221 const interpreter::BytecodeArrayIterator& iterator) { 1222 BuildCall(iterator); 1223 } 1224 1225 1226 void BytecodeGraphBuilder::VisitCallJSRuntime( 1227 const interpreter::BytecodeArrayIterator& iterator) { 1228 FrameStateBeforeAndAfter states(this, iterator); 1229 Node* callee = BuildLoadNativeContextField(iterator.GetIndexOperand(0)); 1230 interpreter::Register receiver = iterator.GetRegisterOperand(1); 1231 size_t arg_count = iterator.GetCountOperand(2); 1232 1233 // Create node to perform the JS runtime call. 1234 const Operator* call = 1235 javascript()->CallFunction(arg_count + 2, language_mode()); 1236 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2); 1237 environment()->BindAccumulator(value, &states); 1238 } 1239 1240 1241 Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments( 1242 const Operator* call_runtime_op, interpreter::Register first_arg, 1243 size_t arity) { 1244 Node** all = info()->zone()->NewArray<Node*>(arity); 1245 int first_arg_index = first_arg.index(); 1246 for (int i = 0; i < static_cast<int>(arity); ++i) { 1247 all[i] = environment()->LookupRegister( 1248 interpreter::Register(first_arg_index + i)); 1249 } 1250 Node* value = MakeNode(call_runtime_op, static_cast<int>(arity), all, false); 1251 return value; 1252 } 1253 1254 1255 void BytecodeGraphBuilder::VisitCallRuntime( 1256 const interpreter::BytecodeArrayIterator& iterator) { 1257 FrameStateBeforeAndAfter states(this, iterator); 1258 Runtime::FunctionId functionId = 1259 static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0)); 1260 interpreter::Register first_arg = iterator.GetRegisterOperand(1); 1261 size_t arg_count = iterator.GetCountOperand(2); 1262 1263 // Create node to perform the runtime call. 1264 const Operator* call = javascript()->CallRuntime(functionId, arg_count); 1265 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count); 1266 environment()->BindAccumulator(value, &states); 1267 } 1268 1269 1270 void BytecodeGraphBuilder::VisitCallRuntimeForPair( 1271 const interpreter::BytecodeArrayIterator& iterator) { 1272 FrameStateBeforeAndAfter states(this, iterator); 1273 Runtime::FunctionId functionId = 1274 static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0)); 1275 interpreter::Register first_arg = iterator.GetRegisterOperand(1); 1276 size_t arg_count = iterator.GetCountOperand(2); 1277 interpreter::Register first_return = iterator.GetRegisterOperand(3); 1278 1279 // Create node to perform the runtime call. 1280 const Operator* call = javascript()->CallRuntime(functionId, arg_count); 1281 Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count); 1282 environment()->BindRegistersToProjections(first_return, return_pair, &states); 1283 } 1284 1285 1286 Node* BytecodeGraphBuilder::ProcessCallNewArguments( 1287 const Operator* call_new_op, interpreter::Register callee, 1288 interpreter::Register first_arg, size_t arity) { 1289 Node** all = info()->zone()->NewArray<Node*>(arity); 1290 all[0] = environment()->LookupRegister(callee); 1291 int first_arg_index = first_arg.index(); 1292 for (int i = 1; i < static_cast<int>(arity) - 1; ++i) { 1293 all[i] = environment()->LookupRegister( 1294 interpreter::Register(first_arg_index + i - 1)); 1295 } 1296 // Original constructor is the same as the callee. 1297 all[arity - 1] = environment()->LookupRegister(callee); 1298 Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false); 1299 return value; 1300 } 1301 1302 1303 void BytecodeGraphBuilder::VisitNew( 1304 const interpreter::BytecodeArrayIterator& iterator) { 1305 FrameStateBeforeAndAfter states(this, iterator); 1306 interpreter::Register callee = iterator.GetRegisterOperand(0); 1307 interpreter::Register first_arg = iterator.GetRegisterOperand(1); 1308 size_t arg_count = iterator.GetCountOperand(2); 1309 1310 // TODO(turbofan): Pass the feedback here. 1311 const Operator* call = javascript()->CallConstruct( 1312 static_cast<int>(arg_count) + 2, VectorSlotPair()); 1313 Node* value = ProcessCallNewArguments(call, callee, first_arg, arg_count + 2); 1314 environment()->BindAccumulator(value, &states); 1315 } 1316 1317 1318 void BytecodeGraphBuilder::VisitThrow( 1319 const interpreter::BytecodeArrayIterator& iterator) { 1320 FrameStateBeforeAndAfter states(this, iterator); 1321 Node* value = environment()->LookupAccumulator(); 1322 // TODO(mythria): Change to Runtime::kThrow when we have deoptimization 1323 // information support in the interpreter. 1324 NewNode(javascript()->CallRuntime(Runtime::kReThrow, 1), value); 1325 Node* control = NewNode(common()->Throw(), value); 1326 environment()->RecordAfterState(control, &states); 1327 UpdateControlDependencyToLeaveFunction(control); 1328 } 1329 1330 1331 void BytecodeGraphBuilder::BuildBinaryOp( 1332 const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) { 1333 FrameStateBeforeAndAfter states(this, iterator); 1334 Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 1335 Node* right = environment()->LookupAccumulator(); 1336 Node* node = NewNode(js_op, left, right); 1337 environment()->BindAccumulator(node, &states); 1338 } 1339 1340 1341 void BytecodeGraphBuilder::VisitAdd( 1342 const interpreter::BytecodeArrayIterator& iterator) { 1343 BinaryOperationHints hints = BinaryOperationHints::Any(); 1344 BuildBinaryOp(javascript()->Add(language_mode(), hints), iterator); 1345 } 1346 1347 1348 void BytecodeGraphBuilder::VisitSub( 1349 const interpreter::BytecodeArrayIterator& iterator) { 1350 BinaryOperationHints hints = BinaryOperationHints::Any(); 1351 BuildBinaryOp(javascript()->Subtract(language_mode(), hints), iterator); 1352 } 1353 1354 1355 void BytecodeGraphBuilder::VisitMul( 1356 const interpreter::BytecodeArrayIterator& iterator) { 1357 BinaryOperationHints hints = BinaryOperationHints::Any(); 1358 BuildBinaryOp(javascript()->Multiply(language_mode(), hints), iterator); 1359 } 1360 1361 1362 void BytecodeGraphBuilder::VisitDiv( 1363 const interpreter::BytecodeArrayIterator& iterator) { 1364 BinaryOperationHints hints = BinaryOperationHints::Any(); 1365 BuildBinaryOp(javascript()->Divide(language_mode(), hints), iterator); 1366 } 1367 1368 1369 void BytecodeGraphBuilder::VisitMod( 1370 const interpreter::BytecodeArrayIterator& iterator) { 1371 BinaryOperationHints hints = BinaryOperationHints::Any(); 1372 BuildBinaryOp(javascript()->Modulus(language_mode(), hints), iterator); 1373 } 1374 1375 1376 void BytecodeGraphBuilder::VisitBitwiseOr( 1377 const interpreter::BytecodeArrayIterator& iterator) { 1378 BinaryOperationHints hints = BinaryOperationHints::Any(); 1379 BuildBinaryOp(javascript()->BitwiseOr(language_mode(), hints), iterator); 1380 } 1381 1382 1383 void BytecodeGraphBuilder::VisitBitwiseXor( 1384 const interpreter::BytecodeArrayIterator& iterator) { 1385 BinaryOperationHints hints = BinaryOperationHints::Any(); 1386 BuildBinaryOp(javascript()->BitwiseXor(language_mode(), hints), iterator); 1387 } 1388 1389 1390 void BytecodeGraphBuilder::VisitBitwiseAnd( 1391 const interpreter::BytecodeArrayIterator& iterator) { 1392 BinaryOperationHints hints = BinaryOperationHints::Any(); 1393 BuildBinaryOp(javascript()->BitwiseAnd(language_mode(), hints), iterator); 1394 } 1395 1396 1397 void BytecodeGraphBuilder::VisitShiftLeft( 1398 const interpreter::BytecodeArrayIterator& iterator) { 1399 BinaryOperationHints hints = BinaryOperationHints::Any(); 1400 BuildBinaryOp(javascript()->ShiftLeft(language_mode(), hints), iterator); 1401 } 1402 1403 1404 void BytecodeGraphBuilder::VisitShiftRight( 1405 const interpreter::BytecodeArrayIterator& iterator) { 1406 BinaryOperationHints hints = BinaryOperationHints::Any(); 1407 BuildBinaryOp(javascript()->ShiftRight(language_mode(), hints), iterator); 1408 } 1409 1410 1411 void BytecodeGraphBuilder::VisitShiftRightLogical( 1412 const interpreter::BytecodeArrayIterator& iterator) { 1413 BinaryOperationHints hints = BinaryOperationHints::Any(); 1414 BuildBinaryOp(javascript()->ShiftRightLogical(language_mode(), hints), 1415 iterator); 1416 } 1417 1418 1419 void BytecodeGraphBuilder::VisitInc( 1420 const interpreter::BytecodeArrayIterator& iterator) { 1421 FrameStateBeforeAndAfter states(this, iterator); 1422 const Operator* js_op = 1423 javascript()->Add(language_mode(), BinaryOperationHints::Any()); 1424 Node* node = NewNode(js_op, environment()->LookupAccumulator(), 1425 jsgraph()->OneConstant()); 1426 environment()->BindAccumulator(node, &states); 1427 } 1428 1429 1430 void BytecodeGraphBuilder::VisitDec( 1431 const interpreter::BytecodeArrayIterator& iterator) { 1432 FrameStateBeforeAndAfter states(this, iterator); 1433 const Operator* js_op = 1434 javascript()->Subtract(language_mode(), BinaryOperationHints::Any()); 1435 Node* node = NewNode(js_op, environment()->LookupAccumulator(), 1436 jsgraph()->OneConstant()); 1437 environment()->BindAccumulator(node, &states); 1438 } 1439 1440 1441 void BytecodeGraphBuilder::VisitLogicalNot( 1442 const interpreter::BytecodeArrayIterator& iterator) { 1443 Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), 1444 environment()->LookupAccumulator()); 1445 Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value, 1446 jsgraph()->FalseConstant(), jsgraph()->TrueConstant()); 1447 environment()->BindAccumulator(node); 1448 } 1449 1450 1451 void BytecodeGraphBuilder::VisitTypeOf( 1452 const interpreter::BytecodeArrayIterator& iterator) { 1453 Node* node = 1454 NewNode(javascript()->TypeOf(), environment()->LookupAccumulator()); 1455 environment()->BindAccumulator(node); 1456 } 1457 1458 1459 void BytecodeGraphBuilder::BuildDelete( 1460 const interpreter::BytecodeArrayIterator& iterator) { 1461 FrameStateBeforeAndAfter states(this, iterator); 1462 Node* key = environment()->LookupAccumulator(); 1463 Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 1464 Node* node = 1465 NewNode(javascript()->DeleteProperty(language_mode()), object, key); 1466 environment()->BindAccumulator(node, &states); 1467 } 1468 1469 1470 void BytecodeGraphBuilder::VisitDeletePropertyStrict( 1471 const interpreter::BytecodeArrayIterator& iterator) { 1472 DCHECK(is_strict(language_mode())); 1473 BuildDelete(iterator); 1474 } 1475 1476 1477 void BytecodeGraphBuilder::VisitDeletePropertySloppy( 1478 const interpreter::BytecodeArrayIterator& iterator) { 1479 DCHECK(is_sloppy(language_mode())); 1480 BuildDelete(iterator); 1481 } 1482 1483 1484 void BytecodeGraphBuilder::VisitDeleteLookupSlot( 1485 const interpreter::BytecodeArrayIterator& iterator) { 1486 FrameStateBeforeAndAfter states(this, iterator); 1487 Node* name = environment()->LookupAccumulator(); 1488 const Operator* op = javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2); 1489 Node* result = NewNode(op, environment()->Context(), name); 1490 environment()->BindAccumulator(result, &states); 1491 } 1492 1493 1494 void BytecodeGraphBuilder::BuildCompareOp( 1495 const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) { 1496 FrameStateBeforeAndAfter states(this, iterator); 1497 Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 1498 Node* right = environment()->LookupAccumulator(); 1499 Node* node = NewNode(js_op, left, right); 1500 environment()->BindAccumulator(node, &states); 1501 } 1502 1503 1504 void BytecodeGraphBuilder::VisitTestEqual( 1505 const interpreter::BytecodeArrayIterator& iterator) { 1506 BuildCompareOp(javascript()->Equal(), iterator); 1507 } 1508 1509 1510 void BytecodeGraphBuilder::VisitTestNotEqual( 1511 const interpreter::BytecodeArrayIterator& iterator) { 1512 BuildCompareOp(javascript()->NotEqual(), iterator); 1513 } 1514 1515 1516 void BytecodeGraphBuilder::VisitTestEqualStrict( 1517 const interpreter::BytecodeArrayIterator& iterator) { 1518 BuildCompareOp(javascript()->StrictEqual(), iterator); 1519 } 1520 1521 1522 void BytecodeGraphBuilder::VisitTestNotEqualStrict( 1523 const interpreter::BytecodeArrayIterator& iterator) { 1524 BuildCompareOp(javascript()->StrictNotEqual(), iterator); 1525 } 1526 1527 1528 void BytecodeGraphBuilder::VisitTestLessThan( 1529 const interpreter::BytecodeArrayIterator& iterator) { 1530 BuildCompareOp(javascript()->LessThan(language_mode()), iterator); 1531 } 1532 1533 1534 void BytecodeGraphBuilder::VisitTestGreaterThan( 1535 const interpreter::BytecodeArrayIterator& iterator) { 1536 BuildCompareOp(javascript()->GreaterThan(language_mode()), iterator); 1537 } 1538 1539 1540 void BytecodeGraphBuilder::VisitTestLessThanOrEqual( 1541 const interpreter::BytecodeArrayIterator& iterator) { 1542 BuildCompareOp(javascript()->LessThanOrEqual(language_mode()), iterator); 1543 } 1544 1545 1546 void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual( 1547 const interpreter::BytecodeArrayIterator& iterator) { 1548 BuildCompareOp(javascript()->GreaterThanOrEqual(language_mode()), iterator); 1549 } 1550 1551 1552 void BytecodeGraphBuilder::VisitTestIn( 1553 const interpreter::BytecodeArrayIterator& iterator) { 1554 BuildCompareOp(javascript()->HasProperty(), iterator); 1555 } 1556 1557 1558 void BytecodeGraphBuilder::VisitTestInstanceOf( 1559 const interpreter::BytecodeArrayIterator& iterator) { 1560 BuildCompareOp(javascript()->InstanceOf(), iterator); 1561 } 1562 1563 1564 void BytecodeGraphBuilder::BuildCastOperator( 1565 const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) { 1566 FrameStateBeforeAndAfter states(this, iterator); 1567 Node* node = NewNode(js_op, environment()->LookupAccumulator()); 1568 environment()->BindAccumulator(node, &states); 1569 } 1570 1571 1572 void BytecodeGraphBuilder::VisitToName( 1573 const interpreter::BytecodeArrayIterator& iterator) { 1574 BuildCastOperator(javascript()->ToName(), iterator); 1575 } 1576 1577 1578 void BytecodeGraphBuilder::VisitToObject( 1579 const interpreter::BytecodeArrayIterator& iterator) { 1580 BuildCastOperator(javascript()->ToObject(), iterator); 1581 } 1582 1583 1584 void BytecodeGraphBuilder::VisitToNumber( 1585 const interpreter::BytecodeArrayIterator& iterator) { 1586 BuildCastOperator(javascript()->ToNumber(), iterator); 1587 } 1588 1589 1590 void BytecodeGraphBuilder::VisitJump( 1591 const interpreter::BytecodeArrayIterator& iterator) { 1592 BuildJump(); 1593 } 1594 1595 1596 void BytecodeGraphBuilder::VisitJumpConstant( 1597 const interpreter::BytecodeArrayIterator& iterator) { 1598 BuildJump(); 1599 } 1600 1601 1602 void BytecodeGraphBuilder::VisitJumpConstantWide( 1603 const interpreter::BytecodeArrayIterator& iterator) { 1604 BuildJump(); 1605 } 1606 1607 1608 void BytecodeGraphBuilder::VisitJumpIfTrue( 1609 const interpreter::BytecodeArrayIterator& iterator) { 1610 BuildJumpIfEqual(jsgraph()->TrueConstant()); 1611 } 1612 1613 1614 void BytecodeGraphBuilder::VisitJumpIfTrueConstant( 1615 const interpreter::BytecodeArrayIterator& iterator) { 1616 BuildJumpIfEqual(jsgraph()->TrueConstant()); 1617 } 1618 1619 1620 void BytecodeGraphBuilder::VisitJumpIfTrueConstantWide( 1621 const interpreter::BytecodeArrayIterator& iterator) { 1622 BuildJumpIfEqual(jsgraph()->TrueConstant()); 1623 } 1624 1625 1626 void BytecodeGraphBuilder::VisitJumpIfFalse( 1627 const interpreter::BytecodeArrayIterator& iterator) { 1628 BuildJumpIfEqual(jsgraph()->FalseConstant()); 1629 } 1630 1631 1632 void BytecodeGraphBuilder::VisitJumpIfFalseConstant( 1633 const interpreter::BytecodeArrayIterator& iterator) { 1634 BuildJumpIfEqual(jsgraph()->FalseConstant()); 1635 } 1636 1637 1638 void BytecodeGraphBuilder::VisitJumpIfFalseConstantWide( 1639 const interpreter::BytecodeArrayIterator& iterator) { 1640 BuildJumpIfEqual(jsgraph()->FalseConstant()); 1641 } 1642 1643 1644 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue( 1645 const interpreter::BytecodeArrayIterator& iterator) { 1646 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant()); 1647 } 1648 1649 1650 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant( 1651 const interpreter::BytecodeArrayIterator& iterator) { 1652 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant()); 1653 } 1654 1655 1656 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstantWide( 1657 const interpreter::BytecodeArrayIterator& iterator) { 1658 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant()); 1659 } 1660 1661 1662 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse( 1663 const interpreter::BytecodeArrayIterator& iterator) { 1664 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant()); 1665 } 1666 1667 1668 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant( 1669 const interpreter::BytecodeArrayIterator& iterator) { 1670 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant()); 1671 } 1672 1673 1674 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstantWide( 1675 const interpreter::BytecodeArrayIterator& iterator) { 1676 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant()); 1677 } 1678 1679 1680 void BytecodeGraphBuilder::VisitJumpIfNull( 1681 const interpreter::BytecodeArrayIterator& iterator) { 1682 BuildJumpIfEqual(jsgraph()->NullConstant()); 1683 } 1684 1685 1686 void BytecodeGraphBuilder::VisitJumpIfNullConstant( 1687 const interpreter::BytecodeArrayIterator& iterator) { 1688 BuildJumpIfEqual(jsgraph()->NullConstant()); 1689 } 1690 1691 1692 void BytecodeGraphBuilder::VisitJumpIfNullConstantWide( 1693 const interpreter::BytecodeArrayIterator& iterator) { 1694 BuildJumpIfEqual(jsgraph()->NullConstant()); 1695 } 1696 1697 1698 void BytecodeGraphBuilder::VisitJumpIfUndefined( 1699 const interpreter::BytecodeArrayIterator& iterator) { 1700 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 1701 } 1702 1703 1704 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant( 1705 const interpreter::BytecodeArrayIterator& iterator) { 1706 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 1707 } 1708 1709 1710 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstantWide( 1711 const interpreter::BytecodeArrayIterator& iterator) { 1712 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 1713 } 1714 1715 1716 void BytecodeGraphBuilder::VisitReturn( 1717 const interpreter::BytecodeArrayIterator& iterator) { 1718 Node* control = 1719 NewNode(common()->Return(), environment()->LookupAccumulator()); 1720 UpdateControlDependencyToLeaveFunction(control); 1721 set_environment(nullptr); 1722 } 1723 1724 1725 void BytecodeGraphBuilder::VisitForInPrepare( 1726 const interpreter::BytecodeArrayIterator& iterator) { 1727 Node* prepare = nullptr; 1728 { 1729 FrameStateBeforeAndAfter states(this, iterator); 1730 Node* receiver = environment()->LookupAccumulator(); 1731 prepare = NewNode(javascript()->ForInPrepare(), receiver); 1732 environment()->RecordAfterState(prepare, &states); 1733 } 1734 // Project cache_type, cache_array, cache_length into register 1735 // operands 1, 2, 3. 1736 for (int i = 0; i < 3; i++) { 1737 environment()->BindRegister(iterator.GetRegisterOperand(i), 1738 NewNode(common()->Projection(i), prepare)); 1739 } 1740 } 1741 1742 1743 void BytecodeGraphBuilder::VisitForInDone( 1744 const interpreter::BytecodeArrayIterator& iterator) { 1745 FrameStateBeforeAndAfter states(this, iterator); 1746 Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 1747 Node* cache_length = 1748 environment()->LookupRegister(iterator.GetRegisterOperand(1)); 1749 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length); 1750 environment()->BindAccumulator(exit_cond, &states); 1751 } 1752 1753 1754 void BytecodeGraphBuilder::VisitForInNext( 1755 const interpreter::BytecodeArrayIterator& iterator) { 1756 FrameStateBeforeAndAfter states(this, iterator); 1757 Node* receiver = 1758 environment()->LookupRegister(iterator.GetRegisterOperand(0)); 1759 Node* cache_type = 1760 environment()->LookupRegister(iterator.GetRegisterOperand(1)); 1761 Node* cache_array = 1762 environment()->LookupRegister(iterator.GetRegisterOperand(2)); 1763 Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(3)); 1764 Node* value = NewNode(javascript()->ForInNext(), receiver, cache_array, 1765 cache_type, index); 1766 environment()->BindAccumulator(value, &states); 1767 } 1768 1769 1770 void BytecodeGraphBuilder::VisitForInStep( 1771 const interpreter::BytecodeArrayIterator& iterator) { 1772 FrameStateBeforeAndAfter states(this, iterator); 1773 Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(0)); 1774 index = NewNode(javascript()->ForInStep(), index); 1775 environment()->BindAccumulator(index, &states); 1776 } 1777 1778 1779 void BytecodeGraphBuilder::MergeEnvironmentsOfBackwardBranches( 1780 int source_offset, int target_offset) { 1781 DCHECK_GE(source_offset, target_offset); 1782 const ZoneVector<int>* branch_sites = 1783 branch_analysis()->BackwardBranchesTargetting(target_offset); 1784 if (branch_sites->back() == source_offset) { 1785 // The set of back branches is complete, merge them. 1786 DCHECK_GE(branch_sites->at(0), target_offset); 1787 Environment* merged = merge_environments_[branch_sites->at(0)]; 1788 for (size_t i = 1; i < branch_sites->size(); i++) { 1789 DCHECK_GE(branch_sites->at(i), target_offset); 1790 merged->Merge(merge_environments_[branch_sites->at(i)]); 1791 } 1792 // And now merge with loop header environment created when loop 1793 // header was visited. 1794 loop_header_environments_[target_offset]->Merge(merged); 1795 } 1796 } 1797 1798 1799 void BytecodeGraphBuilder::MergeEnvironmentsOfForwardBranches( 1800 int source_offset) { 1801 if (branch_analysis()->forward_branches_target(source_offset)) { 1802 // Merge environments of branches that reach this bytecode. 1803 auto branch_sites = 1804 branch_analysis()->ForwardBranchesTargetting(source_offset); 1805 DCHECK_LT(branch_sites->at(0), source_offset); 1806 Environment* merged = merge_environments_[branch_sites->at(0)]; 1807 for (size_t i = 1; i < branch_sites->size(); i++) { 1808 DCHECK_LT(branch_sites->at(i), source_offset); 1809 merged->Merge(merge_environments_[branch_sites->at(i)]); 1810 } 1811 if (environment()) { 1812 merged->Merge(environment()); 1813 } 1814 set_environment(merged); 1815 } 1816 } 1817 1818 1819 void BytecodeGraphBuilder::BuildLoopHeaderForBackwardBranches( 1820 int source_offset) { 1821 if (branch_analysis()->backward_branches_target(source_offset)) { 1822 // Add loop header and store a copy so we can connect merged back 1823 // edge inputs to the loop header. 1824 loop_header_environments_[source_offset] = environment()->CopyForLoop(); 1825 } 1826 } 1827 1828 1829 void BytecodeGraphBuilder::BuildJump(int source_offset, int target_offset) { 1830 DCHECK_NULL(merge_environments_[source_offset]); 1831 merge_environments_[source_offset] = environment(); 1832 if (source_offset >= target_offset) { 1833 MergeEnvironmentsOfBackwardBranches(source_offset, target_offset); 1834 } 1835 set_environment(nullptr); 1836 } 1837 1838 1839 void BytecodeGraphBuilder::BuildJump() { 1840 int source_offset = bytecode_iterator()->current_offset(); 1841 int target_offset = bytecode_iterator()->GetJumpTargetOffset(); 1842 BuildJump(source_offset, target_offset); 1843 } 1844 1845 1846 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { 1847 int source_offset = bytecode_iterator()->current_offset(); 1848 NewBranch(condition); 1849 Environment* if_false_environment = environment()->CopyForConditional(); 1850 NewIfTrue(); 1851 BuildJump(source_offset, bytecode_iterator()->GetJumpTargetOffset()); 1852 set_environment(if_false_environment); 1853 NewIfFalse(); 1854 } 1855 1856 1857 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { 1858 Node* accumulator = environment()->LookupAccumulator(); 1859 Node* condition = 1860 NewNode(javascript()->StrictEqual(), accumulator, comperand); 1861 BuildConditionalJump(condition); 1862 } 1863 1864 1865 void BytecodeGraphBuilder::BuildJumpIfToBooleanEqual(Node* comperand) { 1866 Node* accumulator = environment()->LookupAccumulator(); 1867 Node* to_boolean = 1868 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); 1869 Node* condition = NewNode(javascript()->StrictEqual(), to_boolean, comperand); 1870 BuildConditionalJump(condition); 1871 } 1872 1873 1874 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { 1875 if (size > input_buffer_size_) { 1876 size = size + kInputBufferSizeIncrement + input_buffer_size_; 1877 input_buffer_ = local_zone()->NewArray<Node*>(size); 1878 input_buffer_size_ = size; 1879 } 1880 return input_buffer_; 1881 } 1882 1883 1884 void BytecodeGraphBuilder::PrepareEntryFrameState(Node* node) { 1885 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 1886 DCHECK_EQ(IrOpcode::kDead, 1887 NodeProperties::GetFrameStateInput(node, 0)->opcode()); 1888 NodeProperties::ReplaceFrameStateInput( 1889 node, 0, environment()->Checkpoint(BailoutId(0), 1890 OutputFrameStateCombine::Ignore())); 1891 } 1892 1893 1894 Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, 1895 Node** value_inputs, bool incomplete) { 1896 DCHECK_EQ(op->ValueInputCount(), value_input_count); 1897 1898 bool has_context = OperatorProperties::HasContextInput(op); 1899 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op); 1900 bool has_control = op->ControlInputCount() == 1; 1901 bool has_effect = op->EffectInputCount() == 1; 1902 1903 DCHECK_LT(op->ControlInputCount(), 2); 1904 DCHECK_LT(op->EffectInputCount(), 2); 1905 1906 Node* result = nullptr; 1907 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) { 1908 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); 1909 } else { 1910 int input_count_with_deps = value_input_count; 1911 if (has_context) ++input_count_with_deps; 1912 input_count_with_deps += frame_state_count; 1913 if (has_control) ++input_count_with_deps; 1914 if (has_effect) ++input_count_with_deps; 1915 Node** buffer = EnsureInputBufferSize(input_count_with_deps); 1916 memcpy(buffer, value_inputs, kPointerSize * value_input_count); 1917 Node** current_input = buffer + value_input_count; 1918 if (has_context) { 1919 *current_input++ = environment()->Context(); 1920 } 1921 for (int i = 0; i < frame_state_count; i++) { 1922 // The frame state will be inserted later. Here we misuse 1923 // the {Dead} node as a sentinel to be later overwritten 1924 // with the real frame state. 1925 *current_input++ = jsgraph()->Dead(); 1926 } 1927 if (has_effect) { 1928 *current_input++ = environment()->GetEffectDependency(); 1929 } 1930 if (has_control) { 1931 *current_input++ = environment()->GetControlDependency(); 1932 } 1933 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); 1934 if (!environment()->IsMarkedAsUnreachable()) { 1935 // Update the current control dependency for control-producing nodes. 1936 if (NodeProperties::IsControl(result)) { 1937 environment()->UpdateControlDependency(result); 1938 } 1939 // Update the current effect dependency for effect-producing nodes. 1940 if (result->op()->EffectOutputCount() > 0) { 1941 environment()->UpdateEffectDependency(result); 1942 } 1943 // Add implicit success continuation for throwing nodes. 1944 if (!result->op()->HasProperty(Operator::kNoThrow)) { 1945 const Operator* if_success = common()->IfSuccess(); 1946 Node* on_success = graph()->NewNode(if_success, result); 1947 environment_->UpdateControlDependency(on_success); 1948 } 1949 } 1950 } 1951 1952 return result; 1953 } 1954 1955 1956 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { 1957 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); 1958 Node** buffer = EnsureInputBufferSize(count + 1); 1959 MemsetPointer(buffer, input, count); 1960 buffer[count] = control; 1961 return graph()->NewNode(phi_op, count + 1, buffer, true); 1962 } 1963 1964 1965 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input, 1966 Node* control) { 1967 const Operator* phi_op = common()->EffectPhi(count); 1968 Node** buffer = EnsureInputBufferSize(count + 1); 1969 MemsetPointer(buffer, input, count); 1970 buffer[count] = control; 1971 return graph()->NewNode(phi_op, count + 1, buffer, true); 1972 } 1973 1974 1975 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { 1976 int inputs = control->op()->ControlInputCount() + 1; 1977 if (control->opcode() == IrOpcode::kLoop) { 1978 // Control node for loop exists, add input. 1979 const Operator* op = common()->Loop(inputs); 1980 control->AppendInput(graph_zone(), other); 1981 NodeProperties::ChangeOp(control, op); 1982 } else if (control->opcode() == IrOpcode::kMerge) { 1983 // Control node for merge exists, add input. 1984 const Operator* op = common()->Merge(inputs); 1985 control->AppendInput(graph_zone(), other); 1986 NodeProperties::ChangeOp(control, op); 1987 } else { 1988 // Control node is a singleton, introduce a merge. 1989 const Operator* op = common()->Merge(inputs); 1990 Node* merge_inputs[] = {control, other}; 1991 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); 1992 } 1993 return control; 1994 } 1995 1996 1997 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, 1998 Node* control) { 1999 int inputs = control->op()->ControlInputCount(); 2000 if (value->opcode() == IrOpcode::kEffectPhi && 2001 NodeProperties::GetControlInput(value) == control) { 2002 // Phi already exists, add input. 2003 value->InsertInput(graph_zone(), inputs - 1, other); 2004 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs)); 2005 } else if (value != other) { 2006 // Phi does not exist yet, introduce one. 2007 value = NewEffectPhi(inputs, value, control); 2008 value->ReplaceInput(inputs - 1, other); 2009 } 2010 return value; 2011 } 2012 2013 2014 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, 2015 Node* control) { 2016 int inputs = control->op()->ControlInputCount(); 2017 if (value->opcode() == IrOpcode::kPhi && 2018 NodeProperties::GetControlInput(value) == control) { 2019 // Phi already exists, add input. 2020 value->InsertInput(graph_zone(), inputs - 1, other); 2021 NodeProperties::ChangeOp( 2022 value, common()->Phi(MachineRepresentation::kTagged, inputs)); 2023 } else if (value != other) { 2024 // Phi does not exist yet, introduce one. 2025 value = NewPhi(inputs, value, control); 2026 value->ReplaceInput(inputs - 1, other); 2027 } 2028 return value; 2029 } 2030 2031 2032 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { 2033 if (environment()->IsMarkedAsUnreachable()) return; 2034 environment()->MarkAsUnreachable(); 2035 exit_controls_.push_back(exit); 2036 } 2037 2038 } // namespace compiler 2039 } // namespace internal 2040 } // namespace v8 2041