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 // The abstract execution environment simulates the content of the interpreter 17 // register file. The environment performs SSA-renaming of all tracked nodes at 18 // split and merge points in the control flow. 19 class BytecodeGraphBuilder::Environment : public ZoneObject { 20 public: 21 Environment(BytecodeGraphBuilder* builder, int register_count, 22 int parameter_count, Node* control_dependency, Node* context); 23 24 int parameter_count() const { return parameter_count_; } 25 int register_count() const { return register_count_; } 26 27 Node* LookupAccumulator() const; 28 Node* LookupRegister(interpreter::Register the_register) const; 29 30 void BindAccumulator(Node* node, FrameStateBeforeAndAfter* states = nullptr); 31 void BindRegister(interpreter::Register the_register, Node* node, 32 FrameStateBeforeAndAfter* states = nullptr); 33 void BindRegistersToProjections(interpreter::Register first_reg, Node* node, 34 FrameStateBeforeAndAfter* states = nullptr); 35 void RecordAfterState(Node* node, FrameStateBeforeAndAfter* states); 36 37 // Effect dependency tracked by this environment. 38 Node* GetEffectDependency() { return effect_dependency_; } 39 void UpdateEffectDependency(Node* dependency) { 40 effect_dependency_ = dependency; 41 } 42 43 // Preserve a checkpoint of the environment for the IR graph. Any 44 // further mutation of the environment will not affect checkpoints. 45 Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine); 46 47 // Returns true if the state values are up to date with the current 48 // environment. 49 bool StateValuesAreUpToDate(int output_poke_offset, int output_poke_count); 50 51 // Control dependency tracked by this environment. 52 Node* GetControlDependency() const { return control_dependency_; } 53 void UpdateControlDependency(Node* dependency) { 54 control_dependency_ = dependency; 55 } 56 57 Node* Context() const { return context_; } 58 void SetContext(Node* new_context) { context_ = new_context; } 59 60 Environment* CopyForConditional() const; 61 Environment* CopyForLoop(); 62 void Merge(Environment* other); 63 64 private: 65 explicit Environment(const Environment* copy); 66 void PrepareForLoop(); 67 bool StateValuesAreUpToDate(Node** state_values, int offset, int count, 68 int output_poke_start, int output_poke_end); 69 bool StateValuesRequireUpdate(Node** state_values, int offset, int count); 70 void UpdateStateValues(Node** state_values, int offset, int count); 71 72 int RegisterToValuesIndex(interpreter::Register the_register) const; 73 74 Zone* zone() const { return builder_->local_zone(); } 75 Graph* graph() const { return builder_->graph(); } 76 CommonOperatorBuilder* common() const { return builder_->common(); } 77 BytecodeGraphBuilder* builder() const { return builder_; } 78 const NodeVector* values() const { return &values_; } 79 NodeVector* values() { return &values_; } 80 int register_base() const { return register_base_; } 81 int accumulator_base() const { return accumulator_base_; } 82 83 BytecodeGraphBuilder* builder_; 84 int register_count_; 85 int parameter_count_; 86 Node* context_; 87 Node* control_dependency_; 88 Node* effect_dependency_; 89 NodeVector values_; 90 Node* parameters_state_values_; 91 Node* registers_state_values_; 92 Node* accumulator_state_values_; 93 int register_base_; 94 int accumulator_base_; 95 }; 96 97 // Helper for generating frame states for before and after a bytecode. 98 class BytecodeGraphBuilder::FrameStateBeforeAndAfter { 99 public: 100 explicit FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder) 101 : builder_(builder), 102 id_after_(BailoutId::None()), 103 added_to_node_(false), 104 frame_states_unused_(false), 105 output_poke_offset_(0), 106 output_poke_count_(0) { 107 BailoutId id_before(builder->bytecode_iterator().current_offset()); 108 frame_state_before_ = builder_->environment()->Checkpoint( 109 id_before, OutputFrameStateCombine::Ignore()); 110 id_after_ = BailoutId(id_before.ToInt() + 111 builder->bytecode_iterator().current_bytecode_size()); 112 // Create an explicit checkpoint node for before the operation. 113 Node* node = builder_->NewNode(builder_->common()->Checkpoint()); 114 DCHECK_EQ(IrOpcode::kDead, 115 NodeProperties::GetFrameStateInput(node, 0)->opcode()); 116 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_before_); 117 } 118 119 ~FrameStateBeforeAndAfter() { 120 DCHECK(added_to_node_); 121 DCHECK(frame_states_unused_ || 122 builder_->environment()->StateValuesAreUpToDate(output_poke_offset_, 123 output_poke_count_)); 124 } 125 126 private: 127 friend class Environment; 128 129 void AddToNode(Node* node, OutputFrameStateCombine combine) { 130 DCHECK(!added_to_node_); 131 int count = OperatorProperties::GetFrameStateInputCount(node->op()); 132 DCHECK_LE(count, 2); 133 if (count >= 1) { 134 // Add the frame state for after the operation. 135 DCHECK_EQ(IrOpcode::kDead, 136 NodeProperties::GetFrameStateInput(node, 0)->opcode()); 137 Node* frame_state_after = 138 builder_->environment()->Checkpoint(id_after_, combine); 139 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after); 140 } 141 142 if (count >= 2) { 143 // Add the frame state for before the operation. 144 // TODO(mstarzinger): Get rid of frame state input before! 145 DCHECK_EQ(IrOpcode::kDead, 146 NodeProperties::GetFrameStateInput(node, 1)->opcode()); 147 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); 148 } 149 150 if (!combine.IsOutputIgnored()) { 151 output_poke_offset_ = static_cast<int>(combine.GetOffsetToPokeAt()); 152 output_poke_count_ = node->op()->ValueOutputCount(); 153 } 154 frame_states_unused_ = count == 0; 155 added_to_node_ = true; 156 } 157 158 BytecodeGraphBuilder* builder_; 159 Node* frame_state_before_; 160 BailoutId id_after_; 161 162 bool added_to_node_; 163 bool frame_states_unused_; 164 int output_poke_offset_; 165 int output_poke_count_; 166 }; 167 168 169 // Issues: 170 // - Scopes - intimately tied to AST. Need to eval what is needed. 171 // - Need to resolve closure parameter treatment. 172 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder, 173 int register_count, 174 int parameter_count, 175 Node* control_dependency, 176 Node* context) 177 : builder_(builder), 178 register_count_(register_count), 179 parameter_count_(parameter_count), 180 context_(context), 181 control_dependency_(control_dependency), 182 effect_dependency_(control_dependency), 183 values_(builder->local_zone()), 184 parameters_state_values_(nullptr), 185 registers_state_values_(nullptr), 186 accumulator_state_values_(nullptr) { 187 // The layout of values_ is: 188 // 189 // [receiver] [parameters] [registers] [accumulator] 190 // 191 // parameter[0] is the receiver (this), parameters 1..N are the 192 // parameters supplied to the method (arg0..argN-1). The accumulator 193 // is stored separately. 194 195 // Parameters including the receiver 196 for (int i = 0; i < parameter_count; i++) { 197 const char* debug_name = (i == 0) ? "%this" : nullptr; 198 const Operator* op = common()->Parameter(i, debug_name); 199 Node* parameter = builder->graph()->NewNode(op, graph()->start()); 200 values()->push_back(parameter); 201 } 202 203 // Registers 204 register_base_ = static_cast<int>(values()->size()); 205 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); 206 values()->insert(values()->end(), register_count, undefined_constant); 207 208 // Accumulator 209 accumulator_base_ = static_cast<int>(values()->size()); 210 values()->push_back(undefined_constant); 211 } 212 213 214 BytecodeGraphBuilder::Environment::Environment( 215 const BytecodeGraphBuilder::Environment* other) 216 : builder_(other->builder_), 217 register_count_(other->register_count_), 218 parameter_count_(other->parameter_count_), 219 context_(other->context_), 220 control_dependency_(other->control_dependency_), 221 effect_dependency_(other->effect_dependency_), 222 values_(other->zone()), 223 parameters_state_values_(nullptr), 224 registers_state_values_(nullptr), 225 accumulator_state_values_(nullptr), 226 register_base_(other->register_base_), 227 accumulator_base_(other->accumulator_base_) { 228 values_ = other->values_; 229 } 230 231 232 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( 233 interpreter::Register the_register) const { 234 if (the_register.is_parameter()) { 235 return the_register.ToParameterIndex(parameter_count()); 236 } else { 237 return the_register.index() + register_base(); 238 } 239 } 240 241 242 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { 243 return values()->at(accumulator_base_); 244 } 245 246 247 Node* BytecodeGraphBuilder::Environment::LookupRegister( 248 interpreter::Register the_register) const { 249 if (the_register.is_current_context()) { 250 return Context(); 251 } else if (the_register.is_function_closure()) { 252 return builder()->GetFunctionClosure(); 253 } else if (the_register.is_new_target()) { 254 return builder()->GetNewTarget(); 255 } else { 256 int values_index = RegisterToValuesIndex(the_register); 257 return values()->at(values_index); 258 } 259 } 260 261 262 void BytecodeGraphBuilder::Environment::BindAccumulator( 263 Node* node, FrameStateBeforeAndAfter* states) { 264 if (states) { 265 states->AddToNode(node, OutputFrameStateCombine::PokeAt(0)); 266 } 267 values()->at(accumulator_base_) = node; 268 } 269 270 271 void BytecodeGraphBuilder::Environment::BindRegister( 272 interpreter::Register the_register, Node* node, 273 FrameStateBeforeAndAfter* states) { 274 int values_index = RegisterToValuesIndex(the_register); 275 if (states) { 276 states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ - 277 values_index)); 278 } 279 values()->at(values_index) = node; 280 } 281 282 283 void BytecodeGraphBuilder::Environment::BindRegistersToProjections( 284 interpreter::Register first_reg, Node* node, 285 FrameStateBeforeAndAfter* states) { 286 int values_index = RegisterToValuesIndex(first_reg); 287 if (states) { 288 states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ - 289 values_index)); 290 } 291 for (int i = 0; i < node->op()->ValueOutputCount(); i++) { 292 values()->at(values_index + i) = 293 builder()->NewNode(common()->Projection(i), node); 294 } 295 } 296 297 298 void BytecodeGraphBuilder::Environment::RecordAfterState( 299 Node* node, FrameStateBeforeAndAfter* states) { 300 states->AddToNode(node, OutputFrameStateCombine::Ignore()); 301 } 302 303 304 BytecodeGraphBuilder::Environment* 305 BytecodeGraphBuilder::Environment::CopyForLoop() { 306 PrepareForLoop(); 307 return new (zone()) Environment(this); 308 } 309 310 311 BytecodeGraphBuilder::Environment* 312 BytecodeGraphBuilder::Environment::CopyForConditional() const { 313 return new (zone()) Environment(this); 314 } 315 316 317 void BytecodeGraphBuilder::Environment::Merge( 318 BytecodeGraphBuilder::Environment* other) { 319 // Create a merge of the control dependencies of both environments and update 320 // the current environment's control dependency accordingly. 321 Node* control = builder()->MergeControl(GetControlDependency(), 322 other->GetControlDependency()); 323 UpdateControlDependency(control); 324 325 // Create a merge of the effect dependencies of both environments and update 326 // the current environment's effect dependency accordingly. 327 Node* effect = builder()->MergeEffect(GetEffectDependency(), 328 other->GetEffectDependency(), control); 329 UpdateEffectDependency(effect); 330 331 // Introduce Phi nodes for values that have differing input at merge points, 332 // potentially extending an existing Phi node if possible. 333 context_ = builder()->MergeValue(context_, other->context_, control); 334 for (size_t i = 0; i < values_.size(); i++) { 335 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control); 336 } 337 } 338 339 340 void BytecodeGraphBuilder::Environment::PrepareForLoop() { 341 // Create a control node for the loop header. 342 Node* control = builder()->NewLoop(); 343 344 // Create a Phi for external effects. 345 Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control); 346 UpdateEffectDependency(effect); 347 348 // Assume everything in the loop is updated. 349 context_ = builder()->NewPhi(1, context_, control); 350 int size = static_cast<int>(values()->size()); 351 for (int i = 0; i < size; i++) { 352 values()->at(i) = builder()->NewPhi(1, values()->at(i), control); 353 } 354 355 // Connect to the loop end. 356 Node* terminate = builder()->graph()->NewNode( 357 builder()->common()->Terminate(), effect, control); 358 builder()->exit_controls_.push_back(terminate); 359 } 360 361 362 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( 363 Node** state_values, int offset, int count) { 364 if (*state_values == nullptr) { 365 return true; 366 } 367 DCHECK_EQ((*state_values)->InputCount(), count); 368 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); 369 Node** env_values = (count == 0) ? nullptr : &values()->at(offset); 370 for (int i = 0; i < count; i++) { 371 if ((*state_values)->InputAt(i) != env_values[i]) { 372 return true; 373 } 374 } 375 return false; 376 } 377 378 379 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, 380 int offset, 381 int count) { 382 if (StateValuesRequireUpdate(state_values, offset, count)) { 383 const Operator* op = common()->StateValues(count); 384 (*state_values) = graph()->NewNode(op, count, &values()->at(offset)); 385 } 386 } 387 388 389 Node* BytecodeGraphBuilder::Environment::Checkpoint( 390 BailoutId bailout_id, OutputFrameStateCombine combine) { 391 // TODO(rmcilroy): Consider using StateValuesCache for some state values. 392 UpdateStateValues(¶meters_state_values_, 0, parameter_count()); 393 UpdateStateValues(®isters_state_values_, register_base(), 394 register_count()); 395 UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1); 396 397 const Operator* op = common()->FrameState( 398 bailout_id, combine, builder()->frame_state_function_info()); 399 Node* result = graph()->NewNode( 400 op, parameters_state_values_, registers_state_values_, 401 accumulator_state_values_, Context(), builder()->GetFunctionClosure(), 402 builder()->graph()->start()); 403 404 return result; 405 } 406 407 408 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( 409 Node** state_values, int offset, int count, int output_poke_start, 410 int output_poke_end) { 411 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); 412 for (int i = 0; i < count; i++, offset++) { 413 if (offset < output_poke_start || offset >= output_poke_end) { 414 if ((*state_values)->InputAt(i) != values()->at(offset)) { 415 return false; 416 } 417 } 418 } 419 return true; 420 } 421 422 423 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( 424 int output_poke_offset, int output_poke_count) { 425 // Poke offset is relative to the top of the stack (i.e., the accumulator). 426 int output_poke_start = accumulator_base() - output_poke_offset; 427 int output_poke_end = output_poke_start + output_poke_count; 428 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(), 429 output_poke_start, output_poke_end) && 430 StateValuesAreUpToDate(®isters_state_values_, register_base(), 431 register_count(), output_poke_start, 432 output_poke_end) && 433 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(), 434 1, output_poke_start, output_poke_end); 435 } 436 437 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, 438 CompilationInfo* info, 439 JSGraph* jsgraph) 440 : local_zone_(local_zone), 441 jsgraph_(jsgraph), 442 bytecode_array_(handle(info->shared_info()->bytecode_array())), 443 exception_handler_table_( 444 handle(HandlerTable::cast(bytecode_array()->handler_table()))), 445 feedback_vector_(handle(info->closure()->feedback_vector())), 446 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( 447 FrameStateType::kInterpretedFunction, 448 bytecode_array()->parameter_count(), 449 bytecode_array()->register_count(), info->shared_info())), 450 merge_environments_(local_zone), 451 exception_handlers_(local_zone), 452 current_exception_handler_(0), 453 input_buffer_size_(0), 454 input_buffer_(nullptr), 455 exit_controls_(local_zone) {} 456 457 Node* BytecodeGraphBuilder::GetNewTarget() { 458 if (!new_target_.is_set()) { 459 int params = bytecode_array()->parameter_count(); 460 int index = Linkage::GetJSCallNewTargetParamIndex(params); 461 const Operator* op = common()->Parameter(index, "%new.target"); 462 Node* node = NewNode(op, graph()->start()); 463 new_target_.set(node); 464 } 465 return new_target_.get(); 466 } 467 468 469 Node* BytecodeGraphBuilder::GetFunctionContext() { 470 if (!function_context_.is_set()) { 471 int params = bytecode_array()->parameter_count(); 472 int index = Linkage::GetJSCallContextParamIndex(params); 473 const Operator* op = common()->Parameter(index, "%context"); 474 Node* node = NewNode(op, graph()->start()); 475 function_context_.set(node); 476 } 477 return function_context_.get(); 478 } 479 480 481 Node* BytecodeGraphBuilder::GetFunctionClosure() { 482 if (!function_closure_.is_set()) { 483 int index = Linkage::kJSCallClosureParamIndex; 484 const Operator* op = common()->Parameter(index, "%closure"); 485 Node* node = NewNode(op, graph()->start()); 486 function_closure_.set(node); 487 } 488 return function_closure_.get(); 489 } 490 491 492 Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) { 493 const Operator* op = 494 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true); 495 Node* native_context = NewNode(op, environment()->Context()); 496 return NewNode(javascript()->LoadContext(0, index, true), native_context); 497 } 498 499 500 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { 501 FeedbackVectorSlot slot; 502 if (slot_id >= TypeFeedbackVector::kReservedIndexCount) { 503 slot = feedback_vector()->ToSlot(slot_id); 504 } 505 return VectorSlotPair(feedback_vector(), slot); 506 } 507 508 bool BytecodeGraphBuilder::CreateGraph() { 509 // Set up the basic structure of the graph. Outputs for {Start} are 510 // the formal parameters (including the receiver) plus context and 511 // closure. 512 513 // Set up the basic structure of the graph. Outputs for {Start} are the formal 514 // parameters (including the receiver) plus new target, number of arguments, 515 // context and closure. 516 int actual_parameter_count = bytecode_array()->parameter_count() + 4; 517 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count))); 518 519 Environment env(this, bytecode_array()->register_count(), 520 bytecode_array()->parameter_count(), graph()->start(), 521 GetFunctionContext()); 522 set_environment(&env); 523 524 VisitBytecodes(); 525 526 // Finish the basic structure of the graph. 527 DCHECK_NE(0u, exit_controls_.size()); 528 int const input_count = static_cast<int>(exit_controls_.size()); 529 Node** const inputs = &exit_controls_.front(); 530 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); 531 graph()->SetEnd(end); 532 533 return true; 534 } 535 536 void BytecodeGraphBuilder::VisitBytecodes() { 537 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); 538 analysis.Analyze(); 539 set_branch_analysis(&analysis); 540 interpreter::BytecodeArrayIterator iterator(bytecode_array()); 541 set_bytecode_iterator(&iterator); 542 while (!iterator.done()) { 543 int current_offset = iterator.current_offset(); 544 EnterAndExitExceptionHandlers(current_offset); 545 SwitchToMergeEnvironment(current_offset); 546 if (environment() != nullptr) { 547 BuildLoopHeaderEnvironment(current_offset); 548 549 switch (iterator.current_bytecode()) { 550 #define BYTECODE_CASE(name, ...) \ 551 case interpreter::Bytecode::k##name: \ 552 Visit##name(); \ 553 break; 554 BYTECODE_LIST(BYTECODE_CASE) 555 #undef BYTECODE_CODE 556 } 557 } 558 iterator.Advance(); 559 } 560 set_branch_analysis(nullptr); 561 set_bytecode_iterator(nullptr); 562 DCHECK(exception_handlers_.empty()); 563 } 564 565 void BytecodeGraphBuilder::VisitLdaZero() { 566 Node* node = jsgraph()->ZeroConstant(); 567 environment()->BindAccumulator(node); 568 } 569 570 void BytecodeGraphBuilder::VisitLdaSmi() { 571 Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); 572 environment()->BindAccumulator(node); 573 } 574 575 void BytecodeGraphBuilder::VisitLdaConstant() { 576 Node* node = 577 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); 578 environment()->BindAccumulator(node); 579 } 580 581 void BytecodeGraphBuilder::VisitLdaUndefined() { 582 Node* node = jsgraph()->UndefinedConstant(); 583 environment()->BindAccumulator(node); 584 } 585 586 void BytecodeGraphBuilder::VisitLdrUndefined() { 587 Node* node = jsgraph()->UndefinedConstant(); 588 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node); 589 } 590 591 void BytecodeGraphBuilder::VisitLdaNull() { 592 Node* node = jsgraph()->NullConstant(); 593 environment()->BindAccumulator(node); 594 } 595 596 void BytecodeGraphBuilder::VisitLdaTheHole() { 597 Node* node = jsgraph()->TheHoleConstant(); 598 environment()->BindAccumulator(node); 599 } 600 601 void BytecodeGraphBuilder::VisitLdaTrue() { 602 Node* node = jsgraph()->TrueConstant(); 603 environment()->BindAccumulator(node); 604 } 605 606 void BytecodeGraphBuilder::VisitLdaFalse() { 607 Node* node = jsgraph()->FalseConstant(); 608 environment()->BindAccumulator(node); 609 } 610 611 void BytecodeGraphBuilder::VisitLdar() { 612 Node* value = 613 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 614 environment()->BindAccumulator(value); 615 } 616 617 void BytecodeGraphBuilder::VisitStar() { 618 Node* value = environment()->LookupAccumulator(); 619 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value); 620 } 621 622 void BytecodeGraphBuilder::VisitMov() { 623 Node* value = 624 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 625 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value); 626 } 627 628 Node* BytecodeGraphBuilder::BuildLoadGlobal(TypeofMode typeof_mode) { 629 VectorSlotPair feedback = 630 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(0)); 631 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, 632 feedback_vector()->GetKind(feedback.slot())); 633 Handle<Name> name(feedback_vector()->GetName(feedback.slot())); 634 const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode); 635 return NewNode(op, GetFunctionClosure()); 636 } 637 638 void BytecodeGraphBuilder::VisitLdaGlobal() { 639 FrameStateBeforeAndAfter states(this); 640 Node* node = BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF); 641 environment()->BindAccumulator(node, &states); 642 } 643 644 void BytecodeGraphBuilder::VisitLdrGlobal() { 645 FrameStateBeforeAndAfter states(this); 646 Node* node = BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF); 647 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), node, 648 &states); 649 } 650 651 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() { 652 FrameStateBeforeAndAfter states(this); 653 Node* node = BuildLoadGlobal(TypeofMode::INSIDE_TYPEOF); 654 environment()->BindAccumulator(node, &states); 655 } 656 657 void BytecodeGraphBuilder::BuildStoreGlobal(LanguageMode language_mode) { 658 FrameStateBeforeAndAfter states(this); 659 Handle<Name> name = 660 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0)); 661 VectorSlotPair feedback = 662 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1)); 663 Node* value = environment()->LookupAccumulator(); 664 665 const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback); 666 Node* node = NewNode(op, value, GetFunctionClosure()); 667 environment()->RecordAfterState(node, &states); 668 } 669 670 void BytecodeGraphBuilder::VisitStaGlobalSloppy() { 671 BuildStoreGlobal(LanguageMode::SLOPPY); 672 } 673 674 void BytecodeGraphBuilder::VisitStaGlobalStrict() { 675 BuildStoreGlobal(LanguageMode::STRICT); 676 } 677 678 Node* BytecodeGraphBuilder::BuildLoadContextSlot() { 679 // TODO(mythria): LoadContextSlots are unrolled by the required depth when 680 // generating bytecode. Hence the value of depth is always 0. Update this 681 // code, when the implementation changes. 682 // TODO(mythria): immutable flag is also set to false. This information is not 683 // available in bytecode array. update this code when the implementation 684 // changes. 685 const Operator* op = javascript()->LoadContext( 686 0, bytecode_iterator().GetIndexOperand(1), false); 687 Node* context = 688 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 689 return NewNode(op, context); 690 } 691 692 void BytecodeGraphBuilder::VisitLdaContextSlot() { 693 Node* node = BuildLoadContextSlot(); 694 environment()->BindAccumulator(node); 695 } 696 697 void BytecodeGraphBuilder::VisitLdrContextSlot() { 698 Node* node = BuildLoadContextSlot(); 699 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(2), node); 700 } 701 702 void BytecodeGraphBuilder::VisitStaContextSlot() { 703 // TODO(mythria): LoadContextSlots are unrolled by the required depth when 704 // generating bytecode. Hence the value of depth is always 0. Update this 705 // code, when the implementation changes. 706 const Operator* op = 707 javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(1)); 708 Node* context = 709 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 710 Node* value = environment()->LookupAccumulator(); 711 NewNode(op, context, value); 712 } 713 714 void BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) { 715 FrameStateBeforeAndAfter states(this); 716 Node* name = 717 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); 718 const Operator* op = 719 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF 720 ? Runtime::kLoadLookupSlot 721 : Runtime::kLoadLookupSlotInsideTypeof); 722 Node* value = NewNode(op, name); 723 environment()->BindAccumulator(value, &states); 724 } 725 726 void BytecodeGraphBuilder::VisitLdaLookupSlot() { 727 BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF); 728 } 729 730 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() { 731 BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF); 732 } 733 734 void BytecodeGraphBuilder::BuildStaLookupSlot(LanguageMode language_mode) { 735 FrameStateBeforeAndAfter states(this); 736 Node* value = environment()->LookupAccumulator(); 737 Node* name = 738 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); 739 const Operator* op = javascript()->CallRuntime( 740 is_strict(language_mode) ? Runtime::kStoreLookupSlot_Strict 741 : Runtime::kStoreLookupSlot_Sloppy); 742 Node* store = NewNode(op, name, value); 743 environment()->BindAccumulator(store, &states); 744 } 745 746 void BytecodeGraphBuilder::VisitStaLookupSlotSloppy() { 747 BuildStaLookupSlot(LanguageMode::SLOPPY); 748 } 749 750 void BytecodeGraphBuilder::VisitStaLookupSlotStrict() { 751 BuildStaLookupSlot(LanguageMode::STRICT); 752 } 753 754 Node* BytecodeGraphBuilder::BuildNamedLoad() { 755 Node* object = 756 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 757 Handle<Name> name = 758 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1)); 759 VectorSlotPair feedback = 760 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2)); 761 762 const Operator* op = javascript()->LoadNamed(name, feedback); 763 return NewNode(op, object, GetFunctionClosure()); 764 } 765 766 void BytecodeGraphBuilder::VisitLdaNamedProperty() { 767 FrameStateBeforeAndAfter states(this); 768 Node* node = BuildNamedLoad(); 769 environment()->BindAccumulator(node, &states); 770 } 771 772 void BytecodeGraphBuilder::VisitLdrNamedProperty() { 773 FrameStateBeforeAndAfter states(this); 774 Node* node = BuildNamedLoad(); 775 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(3), node, 776 &states); 777 } 778 779 Node* BytecodeGraphBuilder::BuildKeyedLoad() { 780 Node* key = environment()->LookupAccumulator(); 781 Node* object = 782 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 783 VectorSlotPair feedback = 784 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1)); 785 786 const Operator* op = javascript()->LoadProperty(feedback); 787 return NewNode(op, object, key, GetFunctionClosure()); 788 } 789 790 void BytecodeGraphBuilder::VisitLdaKeyedProperty() { 791 FrameStateBeforeAndAfter states(this); 792 Node* node = BuildKeyedLoad(); 793 environment()->BindAccumulator(node, &states); 794 } 795 796 void BytecodeGraphBuilder::VisitLdrKeyedProperty() { 797 FrameStateBeforeAndAfter states(this); 798 Node* node = BuildKeyedLoad(); 799 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(2), node, 800 &states); 801 } 802 803 void BytecodeGraphBuilder::BuildNamedStore(LanguageMode language_mode) { 804 FrameStateBeforeAndAfter states(this); 805 Node* value = environment()->LookupAccumulator(); 806 Node* object = 807 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 808 Handle<Name> name = 809 Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1)); 810 VectorSlotPair feedback = 811 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2)); 812 813 const Operator* op = javascript()->StoreNamed(language_mode, name, feedback); 814 Node* node = NewNode(op, object, value, GetFunctionClosure()); 815 environment()->RecordAfterState(node, &states); 816 } 817 818 void BytecodeGraphBuilder::VisitStaNamedPropertySloppy() { 819 BuildNamedStore(LanguageMode::SLOPPY); 820 } 821 822 void BytecodeGraphBuilder::VisitStaNamedPropertyStrict() { 823 BuildNamedStore(LanguageMode::STRICT); 824 } 825 826 void BytecodeGraphBuilder::BuildKeyedStore(LanguageMode language_mode) { 827 FrameStateBeforeAndAfter states(this); 828 Node* value = environment()->LookupAccumulator(); 829 Node* object = 830 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 831 Node* key = 832 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 833 VectorSlotPair feedback = 834 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2)); 835 836 const Operator* op = javascript()->StoreProperty(language_mode, feedback); 837 Node* node = NewNode(op, object, key, value, GetFunctionClosure()); 838 environment()->RecordAfterState(node, &states); 839 } 840 841 void BytecodeGraphBuilder::VisitStaKeyedPropertySloppy() { 842 BuildKeyedStore(LanguageMode::SLOPPY); 843 } 844 845 void BytecodeGraphBuilder::VisitStaKeyedPropertyStrict() { 846 BuildKeyedStore(LanguageMode::STRICT); 847 } 848 849 void BytecodeGraphBuilder::VisitPushContext() { 850 Node* new_context = environment()->LookupAccumulator(); 851 environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), 852 environment()->Context()); 853 environment()->SetContext(new_context); 854 } 855 856 void BytecodeGraphBuilder::VisitPopContext() { 857 Node* context = 858 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 859 environment()->SetContext(context); 860 } 861 862 void BytecodeGraphBuilder::VisitCreateClosure() { 863 Handle<SharedFunctionInfo> shared_info = Handle<SharedFunctionInfo>::cast( 864 bytecode_iterator().GetConstantForIndexOperand(0)); 865 PretenureFlag tenured = 866 bytecode_iterator().GetFlagOperand(1) ? TENURED : NOT_TENURED; 867 const Operator* op = javascript()->CreateClosure(shared_info, tenured); 868 Node* closure = NewNode(op); 869 environment()->BindAccumulator(closure); 870 } 871 872 void BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) { 873 FrameStateBeforeAndAfter states(this); 874 const Operator* op = javascript()->CreateArguments(type); 875 Node* object = NewNode(op, GetFunctionClosure()); 876 environment()->BindAccumulator(object, &states); 877 } 878 879 void BytecodeGraphBuilder::VisitCreateMappedArguments() { 880 BuildCreateArguments(CreateArgumentsType::kMappedArguments); 881 } 882 883 void BytecodeGraphBuilder::VisitCreateUnmappedArguments() { 884 BuildCreateArguments(CreateArgumentsType::kUnmappedArguments); 885 } 886 887 void BytecodeGraphBuilder::VisitCreateRestParameter() { 888 BuildCreateArguments(CreateArgumentsType::kRestParameter); 889 } 890 891 void BytecodeGraphBuilder::BuildCreateLiteral(const Operator* op) { 892 FrameStateBeforeAndAfter states(this); 893 Node* literal = NewNode(op, GetFunctionClosure()); 894 environment()->BindAccumulator(literal, &states); 895 } 896 897 void BytecodeGraphBuilder::VisitCreateRegExpLiteral() { 898 Handle<String> constant_pattern = 899 Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(0)); 900 int literal_index = bytecode_iterator().GetIndexOperand(1); 901 int literal_flags = bytecode_iterator().GetFlagOperand(2); 902 const Operator* op = javascript()->CreateLiteralRegExp( 903 constant_pattern, literal_flags, literal_index); 904 BuildCreateLiteral(op); 905 } 906 907 void BytecodeGraphBuilder::VisitCreateArrayLiteral() { 908 Handle<FixedArray> constant_elements = Handle<FixedArray>::cast( 909 bytecode_iterator().GetConstantForIndexOperand(0)); 910 int literal_index = bytecode_iterator().GetIndexOperand(1); 911 int literal_flags = bytecode_iterator().GetFlagOperand(2); 912 int number_of_elements = constant_elements->length(); 913 const Operator* op = javascript()->CreateLiteralArray( 914 constant_elements, literal_flags, literal_index, number_of_elements); 915 BuildCreateLiteral(op); 916 } 917 918 void BytecodeGraphBuilder::VisitCreateObjectLiteral() { 919 Handle<FixedArray> constant_properties = Handle<FixedArray>::cast( 920 bytecode_iterator().GetConstantForIndexOperand(0)); 921 int literal_index = bytecode_iterator().GetIndexOperand(1); 922 int bytecode_flags = bytecode_iterator().GetFlagOperand(2); 923 int literal_flags = 924 interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags); 925 // TODO(mstarzinger): Thread through number of properties. 926 int number_of_properties = constant_properties->length() / 2; 927 const Operator* op = javascript()->CreateLiteralObject( 928 constant_properties, literal_flags, literal_index, number_of_properties); 929 BuildCreateLiteral(op); 930 } 931 932 Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, 933 Node* callee, 934 interpreter::Register receiver, 935 size_t arity) { 936 Node** all = local_zone()->NewArray<Node*>(static_cast<int>(arity)); 937 all[0] = callee; 938 all[1] = environment()->LookupRegister(receiver); 939 int receiver_index = receiver.index(); 940 for (int i = 2; i < static_cast<int>(arity); ++i) { 941 all[i] = environment()->LookupRegister( 942 interpreter::Register(receiver_index + i - 1)); 943 } 944 Node* value = MakeNode(call_op, static_cast<int>(arity), all, false); 945 return value; 946 } 947 948 void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode) { 949 FrameStateBeforeAndAfter states(this); 950 // TODO(rmcilroy): Set receiver_hint correctly based on whether the receiver 951 // register has been loaded with null / undefined explicitly or we are sure it 952 // is not null / undefined. 953 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny; 954 Node* callee = 955 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 956 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 957 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 958 VectorSlotPair feedback = 959 CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(3)); 960 961 const Operator* call = javascript()->CallFunction( 962 arg_count + 1, feedback, receiver_hint, tail_call_mode); 963 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1); 964 environment()->BindAccumulator(value, &states); 965 } 966 967 void BytecodeGraphBuilder::VisitCall() { BuildCall(TailCallMode::kDisallow); } 968 969 void BytecodeGraphBuilder::VisitTailCall() { 970 TailCallMode tail_call_mode = 971 bytecode_array_->GetIsolate()->is_tail_call_elimination_enabled() 972 ? TailCallMode::kAllow 973 : TailCallMode::kDisallow; 974 BuildCall(tail_call_mode); 975 } 976 977 void BytecodeGraphBuilder::VisitCallJSRuntime() { 978 FrameStateBeforeAndAfter states(this); 979 Node* callee = 980 BuildLoadNativeContextField(bytecode_iterator().GetIndexOperand(0)); 981 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 982 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 983 984 // Create node to perform the JS runtime call. 985 const Operator* call = javascript()->CallFunction(arg_count + 1); 986 Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1); 987 environment()->BindAccumulator(value, &states); 988 } 989 990 Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments( 991 const Operator* call_runtime_op, interpreter::Register first_arg, 992 size_t arity) { 993 Node** all = local_zone()->NewArray<Node*>(arity); 994 int first_arg_index = first_arg.index(); 995 for (int i = 0; i < static_cast<int>(arity); ++i) { 996 all[i] = environment()->LookupRegister( 997 interpreter::Register(first_arg_index + i)); 998 } 999 Node* value = MakeNode(call_runtime_op, static_cast<int>(arity), all, false); 1000 return value; 1001 } 1002 1003 void BytecodeGraphBuilder::VisitCallRuntime() { 1004 FrameStateBeforeAndAfter states(this); 1005 Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); 1006 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); 1007 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1008 1009 // Create node to perform the runtime call. 1010 const Operator* call = javascript()->CallRuntime(functionId, arg_count); 1011 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count); 1012 environment()->BindAccumulator(value, &states); 1013 } 1014 1015 void BytecodeGraphBuilder::VisitCallRuntimeForPair() { 1016 FrameStateBeforeAndAfter states(this); 1017 Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); 1018 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); 1019 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1020 interpreter::Register first_return = 1021 bytecode_iterator().GetRegisterOperand(3); 1022 1023 // Create node to perform the runtime call. 1024 const Operator* call = javascript()->CallRuntime(functionId, arg_count); 1025 Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count); 1026 environment()->BindRegistersToProjections(first_return, return_pair, &states); 1027 } 1028 1029 void BytecodeGraphBuilder::VisitInvokeIntrinsic() { 1030 FrameStateBeforeAndAfter states(this); 1031 Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0); 1032 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); 1033 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1034 1035 // Create node to perform the runtime call. Turbofan will take care of the 1036 // lowering. 1037 const Operator* call = javascript()->CallRuntime(functionId, arg_count); 1038 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count); 1039 environment()->BindAccumulator(value, &states); 1040 } 1041 1042 Node* BytecodeGraphBuilder::ProcessCallNewArguments( 1043 const Operator* call_new_op, Node* callee, Node* new_target, 1044 interpreter::Register first_arg, size_t arity) { 1045 Node** all = local_zone()->NewArray<Node*>(arity); 1046 all[0] = new_target; 1047 int first_arg_index = first_arg.index(); 1048 for (int i = 1; i < static_cast<int>(arity) - 1; ++i) { 1049 all[i] = environment()->LookupRegister( 1050 interpreter::Register(first_arg_index + i - 1)); 1051 } 1052 all[arity - 1] = callee; 1053 Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false); 1054 return value; 1055 } 1056 1057 void BytecodeGraphBuilder::VisitNew() { 1058 FrameStateBeforeAndAfter states(this); 1059 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); 1060 interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); 1061 size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); 1062 1063 Node* new_target = environment()->LookupAccumulator(); 1064 Node* callee = environment()->LookupRegister(callee_reg); 1065 // TODO(turbofan): Pass the feedback here. 1066 const Operator* call = javascript()->CallConstruct( 1067 static_cast<int>(arg_count) + 2, VectorSlotPair()); 1068 Node* value = ProcessCallNewArguments(call, callee, new_target, first_arg, 1069 arg_count + 2); 1070 environment()->BindAccumulator(value, &states); 1071 } 1072 1073 void BytecodeGraphBuilder::BuildThrow() { 1074 FrameStateBeforeAndAfter states(this); 1075 Node* value = environment()->LookupAccumulator(); 1076 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); 1077 environment()->BindAccumulator(call, &states); 1078 } 1079 1080 void BytecodeGraphBuilder::VisitThrow() { 1081 BuildThrow(); 1082 Node* call = environment()->LookupAccumulator(); 1083 Node* control = NewNode(common()->Throw(), call); 1084 MergeControlToLeaveFunction(control); 1085 } 1086 1087 void BytecodeGraphBuilder::VisitReThrow() { 1088 Node* value = environment()->LookupAccumulator(); 1089 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); 1090 Node* control = NewNode(common()->Throw(), call); 1091 MergeControlToLeaveFunction(control); 1092 } 1093 1094 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) { 1095 FrameStateBeforeAndAfter states(this); 1096 Node* left = 1097 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1098 Node* right = environment()->LookupAccumulator(); 1099 Node* node = NewNode(js_op, left, right); 1100 environment()->BindAccumulator(node, &states); 1101 } 1102 1103 void BytecodeGraphBuilder::VisitAdd() { 1104 BinaryOperationHints hints = BinaryOperationHints::Any(); 1105 BuildBinaryOp(javascript()->Add(hints)); 1106 } 1107 1108 void BytecodeGraphBuilder::VisitSub() { 1109 BinaryOperationHints hints = BinaryOperationHints::Any(); 1110 BuildBinaryOp(javascript()->Subtract(hints)); 1111 } 1112 1113 void BytecodeGraphBuilder::VisitMul() { 1114 BinaryOperationHints hints = BinaryOperationHints::Any(); 1115 BuildBinaryOp(javascript()->Multiply(hints)); 1116 } 1117 1118 void BytecodeGraphBuilder::VisitDiv() { 1119 BinaryOperationHints hints = BinaryOperationHints::Any(); 1120 BuildBinaryOp(javascript()->Divide(hints)); 1121 } 1122 1123 void BytecodeGraphBuilder::VisitMod() { 1124 BinaryOperationHints hints = BinaryOperationHints::Any(); 1125 BuildBinaryOp(javascript()->Modulus(hints)); 1126 } 1127 1128 void BytecodeGraphBuilder::VisitBitwiseOr() { 1129 BinaryOperationHints hints = BinaryOperationHints::Any(); 1130 BuildBinaryOp(javascript()->BitwiseOr(hints)); 1131 } 1132 1133 void BytecodeGraphBuilder::VisitBitwiseXor() { 1134 BinaryOperationHints hints = BinaryOperationHints::Any(); 1135 BuildBinaryOp(javascript()->BitwiseXor(hints)); 1136 } 1137 1138 void BytecodeGraphBuilder::VisitBitwiseAnd() { 1139 BinaryOperationHints hints = BinaryOperationHints::Any(); 1140 BuildBinaryOp(javascript()->BitwiseAnd(hints)); 1141 } 1142 1143 void BytecodeGraphBuilder::VisitShiftLeft() { 1144 BinaryOperationHints hints = BinaryOperationHints::Any(); 1145 BuildBinaryOp(javascript()->ShiftLeft(hints)); 1146 } 1147 1148 void BytecodeGraphBuilder::VisitShiftRight() { 1149 BinaryOperationHints hints = BinaryOperationHints::Any(); 1150 BuildBinaryOp(javascript()->ShiftRight(hints)); 1151 } 1152 1153 void BytecodeGraphBuilder::VisitShiftRightLogical() { 1154 BinaryOperationHints hints = BinaryOperationHints::Any(); 1155 BuildBinaryOp(javascript()->ShiftRightLogical(hints)); 1156 } 1157 1158 void BytecodeGraphBuilder::VisitInc() { 1159 FrameStateBeforeAndAfter states(this); 1160 // Note: Use subtract -1 here instead of add 1 to ensure we always convert to 1161 // a number, not a string. 1162 const Operator* js_op = javascript()->Subtract(BinaryOperationHints::Any()); 1163 Node* node = NewNode(js_op, environment()->LookupAccumulator(), 1164 jsgraph()->Constant(-1.0)); 1165 environment()->BindAccumulator(node, &states); 1166 } 1167 1168 void BytecodeGraphBuilder::VisitDec() { 1169 FrameStateBeforeAndAfter states(this); 1170 const Operator* js_op = javascript()->Subtract(BinaryOperationHints::Any()); 1171 Node* node = NewNode(js_op, environment()->LookupAccumulator(), 1172 jsgraph()->OneConstant()); 1173 environment()->BindAccumulator(node, &states); 1174 } 1175 1176 void BytecodeGraphBuilder::VisitLogicalNot() { 1177 Node* value = environment()->LookupAccumulator(); 1178 Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value, 1179 jsgraph()->FalseConstant(), jsgraph()->TrueConstant()); 1180 environment()->BindAccumulator(node); 1181 } 1182 1183 void BytecodeGraphBuilder::VisitToBooleanLogicalNot() { 1184 Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), 1185 environment()->LookupAccumulator()); 1186 Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value, 1187 jsgraph()->FalseConstant(), jsgraph()->TrueConstant()); 1188 environment()->BindAccumulator(node); 1189 } 1190 1191 void BytecodeGraphBuilder::VisitTypeOf() { 1192 Node* node = 1193 NewNode(javascript()->TypeOf(), environment()->LookupAccumulator()); 1194 environment()->BindAccumulator(node); 1195 } 1196 1197 void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) { 1198 FrameStateBeforeAndAfter states(this); 1199 Node* key = environment()->LookupAccumulator(); 1200 Node* object = 1201 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1202 Node* node = 1203 NewNode(javascript()->DeleteProperty(language_mode), object, key); 1204 environment()->BindAccumulator(node, &states); 1205 } 1206 1207 void BytecodeGraphBuilder::VisitDeletePropertyStrict() { 1208 BuildDelete(LanguageMode::STRICT); 1209 } 1210 1211 void BytecodeGraphBuilder::VisitDeletePropertySloppy() { 1212 BuildDelete(LanguageMode::SLOPPY); 1213 } 1214 1215 void BytecodeGraphBuilder::BuildCompareOp(const Operator* js_op) { 1216 FrameStateBeforeAndAfter states(this); 1217 Node* left = 1218 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1219 Node* right = environment()->LookupAccumulator(); 1220 Node* node = NewNode(js_op, left, right); 1221 environment()->BindAccumulator(node, &states); 1222 } 1223 1224 void BytecodeGraphBuilder::VisitTestEqual() { 1225 CompareOperationHints hints = CompareOperationHints::Any(); 1226 BuildCompareOp(javascript()->Equal(hints)); 1227 } 1228 1229 void BytecodeGraphBuilder::VisitTestNotEqual() { 1230 CompareOperationHints hints = CompareOperationHints::Any(); 1231 BuildCompareOp(javascript()->NotEqual(hints)); 1232 } 1233 1234 void BytecodeGraphBuilder::VisitTestEqualStrict() { 1235 CompareOperationHints hints = CompareOperationHints::Any(); 1236 BuildCompareOp(javascript()->StrictEqual(hints)); 1237 } 1238 1239 void BytecodeGraphBuilder::VisitTestLessThan() { 1240 CompareOperationHints hints = CompareOperationHints::Any(); 1241 BuildCompareOp(javascript()->LessThan(hints)); 1242 } 1243 1244 void BytecodeGraphBuilder::VisitTestGreaterThan() { 1245 CompareOperationHints hints = CompareOperationHints::Any(); 1246 BuildCompareOp(javascript()->GreaterThan(hints)); 1247 } 1248 1249 void BytecodeGraphBuilder::VisitTestLessThanOrEqual() { 1250 CompareOperationHints hints = CompareOperationHints::Any(); 1251 BuildCompareOp(javascript()->LessThanOrEqual(hints)); 1252 } 1253 1254 void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() { 1255 CompareOperationHints hints = CompareOperationHints::Any(); 1256 BuildCompareOp(javascript()->GreaterThanOrEqual(hints)); 1257 } 1258 1259 void BytecodeGraphBuilder::VisitTestIn() { 1260 BuildCompareOp(javascript()->HasProperty()); 1261 } 1262 1263 void BytecodeGraphBuilder::VisitTestInstanceOf() { 1264 BuildCompareOp(javascript()->InstanceOf()); 1265 } 1266 1267 void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) { 1268 FrameStateBeforeAndAfter states(this); 1269 Node* node = NewNode(js_op, environment()->LookupAccumulator()); 1270 environment()->BindAccumulator(node, &states); 1271 } 1272 1273 void BytecodeGraphBuilder::VisitToName() { 1274 BuildCastOperator(javascript()->ToName()); 1275 } 1276 1277 void BytecodeGraphBuilder::VisitToObject() { 1278 BuildCastOperator(javascript()->ToObject()); 1279 } 1280 1281 void BytecodeGraphBuilder::VisitToNumber() { 1282 BuildCastOperator(javascript()->ToNumber()); 1283 } 1284 1285 void BytecodeGraphBuilder::VisitJump() { BuildJump(); } 1286 1287 void BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); } 1288 1289 1290 void BytecodeGraphBuilder::VisitJumpIfTrue() { 1291 BuildJumpIfEqual(jsgraph()->TrueConstant()); 1292 } 1293 1294 void BytecodeGraphBuilder::VisitJumpIfTrueConstant() { 1295 BuildJumpIfEqual(jsgraph()->TrueConstant()); 1296 } 1297 1298 void BytecodeGraphBuilder::VisitJumpIfFalse() { 1299 BuildJumpIfEqual(jsgraph()->FalseConstant()); 1300 } 1301 1302 void BytecodeGraphBuilder::VisitJumpIfFalseConstant() { 1303 BuildJumpIfEqual(jsgraph()->FalseConstant()); 1304 } 1305 1306 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() { 1307 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant()); 1308 } 1309 1310 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() { 1311 BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant()); 1312 } 1313 1314 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() { 1315 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant()); 1316 } 1317 1318 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() { 1319 BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant()); 1320 } 1321 1322 void BytecodeGraphBuilder::VisitJumpIfNotHole() { BuildJumpIfNotHole(); } 1323 1324 void BytecodeGraphBuilder::VisitJumpIfNotHoleConstant() { 1325 BuildJumpIfNotHole(); 1326 } 1327 1328 void BytecodeGraphBuilder::VisitJumpIfNull() { 1329 BuildJumpIfEqual(jsgraph()->NullConstant()); 1330 } 1331 1332 void BytecodeGraphBuilder::VisitJumpIfNullConstant() { 1333 BuildJumpIfEqual(jsgraph()->NullConstant()); 1334 } 1335 1336 void BytecodeGraphBuilder::VisitJumpIfUndefined() { 1337 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 1338 } 1339 1340 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() { 1341 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 1342 } 1343 1344 void BytecodeGraphBuilder::VisitStackCheck() { 1345 FrameStateBeforeAndAfter states(this); 1346 Node* node = NewNode(javascript()->StackCheck()); 1347 environment()->RecordAfterState(node, &states); 1348 } 1349 1350 void BytecodeGraphBuilder::VisitReturn() { 1351 Node* control = 1352 NewNode(common()->Return(), environment()->LookupAccumulator()); 1353 MergeControlToLeaveFunction(control); 1354 } 1355 1356 void BytecodeGraphBuilder::VisitDebugger() { 1357 FrameStateBeforeAndAfter states(this); 1358 Node* call = 1359 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); 1360 environment()->BindAccumulator(call, &states); 1361 } 1362 1363 // We cannot create a graph from the debugger copy of the bytecode array. 1364 #define DEBUG_BREAK(Name, ...) \ 1365 void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); } 1366 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK); 1367 #undef DEBUG_BREAK 1368 1369 void BytecodeGraphBuilder::BuildForInPrepare() { 1370 FrameStateBeforeAndAfter states(this); 1371 Node* receiver = environment()->LookupAccumulator(); 1372 Node* prepare = NewNode(javascript()->ForInPrepare(), receiver); 1373 environment()->BindRegistersToProjections( 1374 bytecode_iterator().GetRegisterOperand(0), prepare, &states); 1375 } 1376 1377 void BytecodeGraphBuilder::VisitForInPrepare() { BuildForInPrepare(); } 1378 1379 void BytecodeGraphBuilder::VisitForInDone() { 1380 FrameStateBeforeAndAfter states(this); 1381 Node* index = 1382 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1383 Node* cache_length = 1384 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 1385 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length); 1386 environment()->BindAccumulator(exit_cond, &states); 1387 } 1388 1389 void BytecodeGraphBuilder::BuildForInNext() { 1390 FrameStateBeforeAndAfter states(this); 1391 Node* receiver = 1392 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1393 Node* index = 1394 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 1395 int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index(); 1396 Node* cache_type = environment()->LookupRegister( 1397 interpreter::Register(catch_reg_pair_index)); 1398 Node* cache_array = environment()->LookupRegister( 1399 interpreter::Register(catch_reg_pair_index + 1)); 1400 1401 Node* value = NewNode(javascript()->ForInNext(), receiver, cache_array, 1402 cache_type, index); 1403 environment()->BindAccumulator(value, &states); 1404 } 1405 1406 void BytecodeGraphBuilder::VisitForInNext() { BuildForInNext(); } 1407 1408 void BytecodeGraphBuilder::VisitForInStep() { 1409 FrameStateBeforeAndAfter states(this); 1410 Node* index = 1411 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1412 index = NewNode(javascript()->ForInStep(), index); 1413 environment()->BindAccumulator(index, &states); 1414 } 1415 1416 void BytecodeGraphBuilder::VisitSuspendGenerator() { 1417 Node* state = environment()->LookupAccumulator(); 1418 Node* generator = environment()->LookupRegister( 1419 bytecode_iterator().GetRegisterOperand(0)); 1420 // The offsets used by the bytecode iterator are relative to a different base 1421 // than what is used in the interpreter, hence the addition. 1422 Node* offset = 1423 jsgraph()->Constant(bytecode_iterator().current_offset() + 1424 (BytecodeArray::kHeaderSize - kHeapObjectTag)); 1425 1426 int register_count = environment()->register_count(); 1427 int value_input_count = 3 + register_count; 1428 1429 Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count); 1430 value_inputs[0] = generator; 1431 value_inputs[1] = state; 1432 value_inputs[2] = offset; 1433 for (int i = 0; i < register_count; ++i) { 1434 value_inputs[3 + i] = 1435 environment()->LookupRegister(interpreter::Register(i)); 1436 } 1437 1438 MakeNode(javascript()->GeneratorStore(register_count), value_input_count, 1439 value_inputs, false); 1440 } 1441 1442 void BytecodeGraphBuilder::VisitResumeGenerator() { 1443 FrameStateBeforeAndAfter states(this); 1444 1445 Node* generator = environment()->LookupRegister( 1446 bytecode_iterator().GetRegisterOperand(0)); 1447 1448 // Bijection between registers and array indices must match that used in 1449 // InterpreterAssembler::ExportRegisterFile. 1450 for (int i = 0; i < environment()->register_count(); ++i) { 1451 Node* value = NewNode(javascript()->GeneratorRestoreRegister(i), generator); 1452 environment()->BindRegister(interpreter::Register(i), value); 1453 } 1454 1455 Node* state = 1456 NewNode(javascript()->GeneratorRestoreContinuation(), generator); 1457 1458 environment()->BindAccumulator(state, &states); 1459 } 1460 1461 void BytecodeGraphBuilder::VisitWide() { 1462 // Consumed by the BytecodeArrayIterator. 1463 UNREACHABLE(); 1464 } 1465 1466 void BytecodeGraphBuilder::VisitExtraWide() { 1467 // Consumed by the BytecodeArrayIterator. 1468 UNREACHABLE(); 1469 } 1470 1471 void BytecodeGraphBuilder::VisitIllegal() { 1472 // Not emitted in valid bytecode. 1473 UNREACHABLE(); 1474 } 1475 1476 void BytecodeGraphBuilder::VisitNop() {} 1477 1478 void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) { 1479 if (merge_environments_[current_offset] != nullptr) { 1480 if (environment() != nullptr) { 1481 merge_environments_[current_offset]->Merge(environment()); 1482 } 1483 set_environment(merge_environments_[current_offset]); 1484 } 1485 } 1486 1487 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { 1488 if (branch_analysis()->backward_branches_target(current_offset)) { 1489 // Add loop header and store a copy so we can connect merged back 1490 // edge inputs to the loop header. 1491 merge_environments_[current_offset] = environment()->CopyForLoop(); 1492 } 1493 } 1494 1495 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { 1496 if (merge_environments_[target_offset] == nullptr) { 1497 // Append merge nodes to the environment. We may merge here with another 1498 // environment. So add a place holder for merge nodes. We may add redundant 1499 // but will be eliminated in a later pass. 1500 // TODO(mstarzinger): Be smarter about this! 1501 NewMerge(); 1502 merge_environments_[target_offset] = environment(); 1503 } else { 1504 merge_environments_[target_offset]->Merge(environment()); 1505 } 1506 set_environment(nullptr); 1507 } 1508 1509 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { 1510 exit_controls_.push_back(exit); 1511 set_environment(nullptr); 1512 } 1513 1514 void BytecodeGraphBuilder::BuildJump() { 1515 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 1516 } 1517 1518 1519 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { 1520 NewBranch(condition); 1521 Environment* if_false_environment = environment()->CopyForConditional(); 1522 NewIfTrue(); 1523 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 1524 set_environment(if_false_environment); 1525 NewIfFalse(); 1526 } 1527 1528 1529 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { 1530 Node* accumulator = environment()->LookupAccumulator(); 1531 Node* condition = 1532 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), 1533 accumulator, comperand); 1534 BuildConditionalJump(condition); 1535 } 1536 1537 1538 void BytecodeGraphBuilder::BuildJumpIfToBooleanEqual(Node* comperand) { 1539 Node* accumulator = environment()->LookupAccumulator(); 1540 Node* to_boolean = 1541 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); 1542 Node* condition = 1543 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), 1544 to_boolean, comperand); 1545 BuildConditionalJump(condition); 1546 } 1547 1548 void BytecodeGraphBuilder::BuildJumpIfNotHole() { 1549 Node* accumulator = environment()->LookupAccumulator(); 1550 Node* condition = 1551 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), 1552 accumulator, jsgraph()->TheHoleConstant()); 1553 Node* node = 1554 NewNode(common()->Select(MachineRepresentation::kTagged), condition, 1555 jsgraph()->FalseConstant(), jsgraph()->TrueConstant()); 1556 BuildConditionalJump(node); 1557 } 1558 1559 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { 1560 if (size > input_buffer_size_) { 1561 size = size + kInputBufferSizeIncrement + input_buffer_size_; 1562 input_buffer_ = local_zone()->NewArray<Node*>(size); 1563 input_buffer_size_ = size; 1564 } 1565 return input_buffer_; 1566 } 1567 1568 void BytecodeGraphBuilder::EnterAndExitExceptionHandlers(int current_offset) { 1569 Handle<HandlerTable> table = exception_handler_table(); 1570 int num_entries = table->NumberOfRangeEntries(); 1571 1572 // Potentially exit exception handlers. 1573 while (!exception_handlers_.empty()) { 1574 int current_end = exception_handlers_.top().end_offset_; 1575 if (current_offset < current_end) break; // Still covered by range. 1576 exception_handlers_.pop(); 1577 } 1578 1579 // Potentially enter exception handlers. 1580 while (current_exception_handler_ < num_entries) { 1581 int next_start = table->GetRangeStart(current_exception_handler_); 1582 if (current_offset < next_start) break; // Not yet covered by range. 1583 int next_end = table->GetRangeEnd(current_exception_handler_); 1584 int next_handler = table->GetRangeHandler(current_exception_handler_); 1585 int context_register = table->GetRangeData(current_exception_handler_); 1586 CatchPrediction pred = 1587 table->GetRangePrediction(current_exception_handler_); 1588 exception_handlers_.push( 1589 {next_start, next_end, next_handler, context_register, pred}); 1590 current_exception_handler_++; 1591 } 1592 } 1593 1594 Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, 1595 Node** value_inputs, bool incomplete) { 1596 DCHECK_EQ(op->ValueInputCount(), value_input_count); 1597 1598 bool has_context = OperatorProperties::HasContextInput(op); 1599 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op); 1600 bool has_control = op->ControlInputCount() == 1; 1601 bool has_effect = op->EffectInputCount() == 1; 1602 1603 DCHECK_LT(op->ControlInputCount(), 2); 1604 DCHECK_LT(op->EffectInputCount(), 2); 1605 1606 Node* result = nullptr; 1607 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) { 1608 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); 1609 } else { 1610 bool inside_handler = !exception_handlers_.empty(); 1611 int input_count_with_deps = value_input_count; 1612 if (has_context) ++input_count_with_deps; 1613 input_count_with_deps += frame_state_count; 1614 if (has_control) ++input_count_with_deps; 1615 if (has_effect) ++input_count_with_deps; 1616 Node** buffer = EnsureInputBufferSize(input_count_with_deps); 1617 memcpy(buffer, value_inputs, kPointerSize * value_input_count); 1618 Node** current_input = buffer + value_input_count; 1619 if (has_context) { 1620 *current_input++ = environment()->Context(); 1621 } 1622 for (int i = 0; i < frame_state_count; i++) { 1623 // The frame state will be inserted later. Here we misuse 1624 // the {Dead} node as a sentinel to be later overwritten 1625 // with the real frame state. 1626 *current_input++ = jsgraph()->Dead(); 1627 } 1628 if (has_effect) { 1629 *current_input++ = environment()->GetEffectDependency(); 1630 } 1631 if (has_control) { 1632 *current_input++ = environment()->GetControlDependency(); 1633 } 1634 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); 1635 // Update the current control dependency for control-producing nodes. 1636 if (NodeProperties::IsControl(result)) { 1637 environment()->UpdateControlDependency(result); 1638 } 1639 // Update the current effect dependency for effect-producing nodes. 1640 if (result->op()->EffectOutputCount() > 0) { 1641 environment()->UpdateEffectDependency(result); 1642 } 1643 // Add implicit exception continuation for throwing nodes. 1644 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { 1645 int handler_offset = exception_handlers_.top().handler_offset_; 1646 int context_index = exception_handlers_.top().context_register_; 1647 CatchPrediction prediction = exception_handlers_.top().pred_; 1648 interpreter::Register context_register(context_index); 1649 IfExceptionHint hint = prediction == CatchPrediction::CAUGHT 1650 ? IfExceptionHint::kLocallyCaught 1651 : IfExceptionHint::kLocallyUncaught; 1652 Environment* success_env = environment()->CopyForConditional(); 1653 const Operator* op = common()->IfException(hint); 1654 Node* effect = environment()->GetEffectDependency(); 1655 Node* on_exception = graph()->NewNode(op, effect, result); 1656 Node* context = environment()->LookupRegister(context_register); 1657 environment()->UpdateControlDependency(on_exception); 1658 environment()->UpdateEffectDependency(on_exception); 1659 environment()->BindAccumulator(on_exception); 1660 environment()->SetContext(context); 1661 MergeIntoSuccessorEnvironment(handler_offset); 1662 set_environment(success_env); 1663 } 1664 // Add implicit success continuation for throwing nodes. 1665 if (!result->op()->HasProperty(Operator::kNoThrow)) { 1666 const Operator* if_success = common()->IfSuccess(); 1667 Node* on_success = graph()->NewNode(if_success, result); 1668 environment()->UpdateControlDependency(on_success); 1669 } 1670 } 1671 1672 return result; 1673 } 1674 1675 1676 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { 1677 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); 1678 Node** buffer = EnsureInputBufferSize(count + 1); 1679 MemsetPointer(buffer, input, count); 1680 buffer[count] = control; 1681 return graph()->NewNode(phi_op, count + 1, buffer, true); 1682 } 1683 1684 1685 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input, 1686 Node* control) { 1687 const Operator* phi_op = common()->EffectPhi(count); 1688 Node** buffer = EnsureInputBufferSize(count + 1); 1689 MemsetPointer(buffer, input, count); 1690 buffer[count] = control; 1691 return graph()->NewNode(phi_op, count + 1, buffer, true); 1692 } 1693 1694 1695 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { 1696 int inputs = control->op()->ControlInputCount() + 1; 1697 if (control->opcode() == IrOpcode::kLoop) { 1698 // Control node for loop exists, add input. 1699 const Operator* op = common()->Loop(inputs); 1700 control->AppendInput(graph_zone(), other); 1701 NodeProperties::ChangeOp(control, op); 1702 } else if (control->opcode() == IrOpcode::kMerge) { 1703 // Control node for merge exists, add input. 1704 const Operator* op = common()->Merge(inputs); 1705 control->AppendInput(graph_zone(), other); 1706 NodeProperties::ChangeOp(control, op); 1707 } else { 1708 // Control node is a singleton, introduce a merge. 1709 const Operator* op = common()->Merge(inputs); 1710 Node* merge_inputs[] = {control, other}; 1711 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); 1712 } 1713 return control; 1714 } 1715 1716 1717 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, 1718 Node* control) { 1719 int inputs = control->op()->ControlInputCount(); 1720 if (value->opcode() == IrOpcode::kEffectPhi && 1721 NodeProperties::GetControlInput(value) == control) { 1722 // Phi already exists, add input. 1723 value->InsertInput(graph_zone(), inputs - 1, other); 1724 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs)); 1725 } else if (value != other) { 1726 // Phi does not exist yet, introduce one. 1727 value = NewEffectPhi(inputs, value, control); 1728 value->ReplaceInput(inputs - 1, other); 1729 } 1730 return value; 1731 } 1732 1733 1734 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, 1735 Node* control) { 1736 int inputs = control->op()->ControlInputCount(); 1737 if (value->opcode() == IrOpcode::kPhi && 1738 NodeProperties::GetControlInput(value) == control) { 1739 // Phi already exists, add input. 1740 value->InsertInput(graph_zone(), inputs - 1, other); 1741 NodeProperties::ChangeOp( 1742 value, common()->Phi(MachineRepresentation::kTagged, inputs)); 1743 } else if (value != other) { 1744 // Phi does not exist yet, introduce one. 1745 value = NewPhi(inputs, value, control); 1746 value->ReplaceInput(inputs - 1, other); 1747 } 1748 return value; 1749 } 1750 1751 } // namespace compiler 1752 } // namespace internal 1753 } // namespace v8 1754