1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_X64_LITHIUM_X64_H_ 29 #define V8_X64_LITHIUM_X64_H_ 30 31 #include "hydrogen.h" 32 #include "lithium-allocator.h" 33 #include "lithium.h" 34 #include "safepoint-table.h" 35 36 namespace v8 { 37 namespace internal { 38 39 // Forward declarations. 40 class LCodeGen; 41 42 #define LITHIUM_ALL_INSTRUCTION_LIST(V) \ 43 V(ControlInstruction) \ 44 V(Call) \ 45 LITHIUM_CONCRETE_INSTRUCTION_LIST(V) 46 47 48 #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \ 49 V(AccessArgumentsAt) \ 50 V(AddI) \ 51 V(ApplyArguments) \ 52 V(ArgumentsElements) \ 53 V(ArgumentsLength) \ 54 V(ArithmeticD) \ 55 V(ArithmeticT) \ 56 V(ArrayLiteral) \ 57 V(BitI) \ 58 V(BitNotI) \ 59 V(BoundsCheck) \ 60 V(Branch) \ 61 V(CallConstantFunction) \ 62 V(CallFunction) \ 63 V(CallGlobal) \ 64 V(CallKeyed) \ 65 V(CallKnownGlobal) \ 66 V(CallNamed) \ 67 V(CallNew) \ 68 V(CallRuntime) \ 69 V(CallStub) \ 70 V(CheckFunction) \ 71 V(CheckInstanceType) \ 72 V(CheckMap) \ 73 V(CheckNonSmi) \ 74 V(CheckPrototypeMaps) \ 75 V(CheckSmi) \ 76 V(ClassOfTest) \ 77 V(ClassOfTestAndBranch) \ 78 V(CmpID) \ 79 V(CmpIDAndBranch) \ 80 V(CmpJSObjectEq) \ 81 V(CmpJSObjectEqAndBranch) \ 82 V(CmpMapAndBranch) \ 83 V(CmpT) \ 84 V(CmpTAndBranch) \ 85 V(ConstantD) \ 86 V(ConstantI) \ 87 V(ConstantT) \ 88 V(Context) \ 89 V(DeleteProperty) \ 90 V(Deoptimize) \ 91 V(DivI) \ 92 V(DoubleToI) \ 93 V(ExternalArrayLength) \ 94 V(FixedArrayLength) \ 95 V(FunctionLiteral) \ 96 V(Gap) \ 97 V(GetCachedArrayIndex) \ 98 V(GlobalObject) \ 99 V(GlobalReceiver) \ 100 V(Goto) \ 101 V(HasInstanceType) \ 102 V(HasInstanceTypeAndBranch) \ 103 V(HasCachedArrayIndex) \ 104 V(HasCachedArrayIndexAndBranch) \ 105 V(InstanceOf) \ 106 V(InstanceOfAndBranch) \ 107 V(InstanceOfKnownGlobal) \ 108 V(Integer32ToDouble) \ 109 V(IsNull) \ 110 V(IsNullAndBranch) \ 111 V(IsObject) \ 112 V(IsObjectAndBranch) \ 113 V(IsSmi) \ 114 V(IsSmiAndBranch) \ 115 V(JSArrayLength) \ 116 V(Label) \ 117 V(LazyBailout) \ 118 V(LoadContextSlot) \ 119 V(LoadElements) \ 120 V(LoadExternalArrayPointer) \ 121 V(LoadGlobalCell) \ 122 V(LoadGlobalGeneric) \ 123 V(LoadKeyedFastElement) \ 124 V(LoadKeyedGeneric) \ 125 V(LoadKeyedSpecializedArrayElement) \ 126 V(LoadNamedField) \ 127 V(LoadNamedFieldPolymorphic) \ 128 V(LoadNamedGeneric) \ 129 V(LoadFunctionPrototype) \ 130 V(ModI) \ 131 V(MulI) \ 132 V(NumberTagD) \ 133 V(NumberTagI) \ 134 V(NumberUntagD) \ 135 V(ObjectLiteral) \ 136 V(OsrEntry) \ 137 V(OuterContext) \ 138 V(Parameter) \ 139 V(Power) \ 140 V(PushArgument) \ 141 V(RegExpLiteral) \ 142 V(Return) \ 143 V(ShiftI) \ 144 V(SmiTag) \ 145 V(SmiUntag) \ 146 V(StackCheck) \ 147 V(StoreContextSlot) \ 148 V(StoreGlobalCell) \ 149 V(StoreGlobalGeneric) \ 150 V(StoreKeyedFastElement) \ 151 V(StoreKeyedGeneric) \ 152 V(StoreKeyedSpecializedArrayElement) \ 153 V(StoreNamedField) \ 154 V(StoreNamedGeneric) \ 155 V(StringCharCodeAt) \ 156 V(StringCharFromCode) \ 157 V(StringLength) \ 158 V(SubI) \ 159 V(TaggedToI) \ 160 V(ToFastProperties) \ 161 V(Throw) \ 162 V(Typeof) \ 163 V(TypeofIs) \ 164 V(TypeofIsAndBranch) \ 165 V(IsConstructCall) \ 166 V(IsConstructCallAndBranch) \ 167 V(UnaryMathOperation) \ 168 V(UnknownOSRValue) \ 169 V(ValueOf) 170 171 172 #define DECLARE_INSTRUCTION(type) \ 173 virtual bool Is##type() const { return true; } \ 174 static L##type* cast(LInstruction* instr) { \ 175 ASSERT(instr->Is##type()); \ 176 return reinterpret_cast<L##type*>(instr); \ 177 } 178 179 180 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \ 181 virtual void CompileToNative(LCodeGen* generator); \ 182 virtual const char* Mnemonic() const { return mnemonic; } \ 183 DECLARE_INSTRUCTION(type) 184 185 186 #define DECLARE_HYDROGEN_ACCESSOR(type) \ 187 H##type* hydrogen() const { \ 188 return H##type::cast(hydrogen_value()); \ 189 } 190 191 192 class LInstruction: public ZoneObject { 193 public: 194 LInstruction() 195 : environment_(NULL), 196 hydrogen_value_(NULL), 197 is_call_(false), 198 is_save_doubles_(false) { } 199 200 virtual ~LInstruction() { } 201 202 virtual void CompileToNative(LCodeGen* generator) = 0; 203 virtual const char* Mnemonic() const = 0; 204 virtual void PrintTo(StringStream* stream); 205 virtual void PrintDataTo(StringStream* stream) = 0; 206 virtual void PrintOutputOperandTo(StringStream* stream) = 0; 207 208 // Declare virtual type testers. 209 #define DECLARE_DO(type) virtual bool Is##type() const { return false; } 210 LITHIUM_ALL_INSTRUCTION_LIST(DECLARE_DO) 211 #undef DECLARE_DO 212 213 virtual bool IsControl() const { return false; } 214 virtual void SetBranchTargets(int true_block_id, int false_block_id) { } 215 216 void set_environment(LEnvironment* env) { environment_ = env; } 217 LEnvironment* environment() const { return environment_; } 218 bool HasEnvironment() const { return environment_ != NULL; } 219 220 void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); } 221 LPointerMap* pointer_map() const { return pointer_map_.get(); } 222 bool HasPointerMap() const { return pointer_map_.is_set(); } 223 224 void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; } 225 HValue* hydrogen_value() const { return hydrogen_value_; } 226 227 void set_deoptimization_environment(LEnvironment* env) { 228 deoptimization_environment_.set(env); 229 } 230 LEnvironment* deoptimization_environment() const { 231 return deoptimization_environment_.get(); 232 } 233 bool HasDeoptimizationEnvironment() const { 234 return deoptimization_environment_.is_set(); 235 } 236 237 void MarkAsCall() { is_call_ = true; } 238 void MarkAsSaveDoubles() { is_save_doubles_ = true; } 239 240 // Interface to the register allocator and iterators. 241 bool IsMarkedAsCall() const { return is_call_; } 242 bool IsMarkedAsSaveDoubles() const { return is_save_doubles_; } 243 244 virtual bool HasResult() const = 0; 245 virtual LOperand* result() = 0; 246 247 virtual int InputCount() = 0; 248 virtual LOperand* InputAt(int i) = 0; 249 virtual int TempCount() = 0; 250 virtual LOperand* TempAt(int i) = 0; 251 252 LOperand* FirstInput() { return InputAt(0); } 253 LOperand* Output() { return HasResult() ? result() : NULL; } 254 255 #ifdef DEBUG 256 void VerifyCall(); 257 #endif 258 259 private: 260 LEnvironment* environment_; 261 SetOncePointer<LPointerMap> pointer_map_; 262 HValue* hydrogen_value_; 263 SetOncePointer<LEnvironment> deoptimization_environment_; 264 bool is_call_; 265 bool is_save_doubles_; 266 }; 267 268 269 template<typename ElementType, int NumElements> 270 class OperandContainer { 271 public: 272 OperandContainer() { 273 for (int i = 0; i < NumElements; i++) elems_[i] = NULL; 274 } 275 int length() { return NumElements; } 276 ElementType& operator[](int i) { 277 ASSERT(i < length()); 278 return elems_[i]; 279 } 280 void PrintOperandsTo(StringStream* stream); 281 282 private: 283 ElementType elems_[NumElements]; 284 }; 285 286 287 template<typename ElementType> 288 class OperandContainer<ElementType, 0> { 289 public: 290 int length() { return 0; } 291 void PrintOperandsTo(StringStream* stream) { } 292 ElementType& operator[](int i) { 293 UNREACHABLE(); 294 static ElementType t = 0; 295 return t; 296 } 297 }; 298 299 300 // R = number of result operands (0 or 1). 301 // I = number of input operands. 302 // T = number of temporary operands. 303 template<int R, int I, int T> 304 class LTemplateInstruction: public LInstruction { 305 public: 306 // Allow 0 or 1 output operands. 307 STATIC_ASSERT(R == 0 || R == 1); 308 virtual bool HasResult() const { return R != 0; } 309 void set_result(LOperand* operand) { results_[0] = operand; } 310 LOperand* result() { return results_[0]; } 311 312 int InputCount() { return I; } 313 LOperand* InputAt(int i) { return inputs_[i]; } 314 315 int TempCount() { return T; } 316 LOperand* TempAt(int i) { return temps_[i]; } 317 318 virtual void PrintDataTo(StringStream* stream); 319 virtual void PrintOutputOperandTo(StringStream* stream); 320 321 protected: 322 OperandContainer<LOperand*, R> results_; 323 OperandContainer<LOperand*, I> inputs_; 324 OperandContainer<LOperand*, T> temps_; 325 }; 326 327 328 class LGap: public LTemplateInstruction<0, 0, 0> { 329 public: 330 explicit LGap(HBasicBlock* block) 331 : block_(block) { 332 parallel_moves_[BEFORE] = NULL; 333 parallel_moves_[START] = NULL; 334 parallel_moves_[END] = NULL; 335 parallel_moves_[AFTER] = NULL; 336 } 337 338 DECLARE_CONCRETE_INSTRUCTION(Gap, "gap") 339 virtual void PrintDataTo(StringStream* stream); 340 341 bool IsRedundant() const; 342 343 HBasicBlock* block() const { return block_; } 344 345 enum InnerPosition { 346 BEFORE, 347 START, 348 END, 349 AFTER, 350 FIRST_INNER_POSITION = BEFORE, 351 LAST_INNER_POSITION = AFTER 352 }; 353 354 LParallelMove* GetOrCreateParallelMove(InnerPosition pos) { 355 if (parallel_moves_[pos] == NULL) parallel_moves_[pos] = new LParallelMove; 356 return parallel_moves_[pos]; 357 } 358 359 LParallelMove* GetParallelMove(InnerPosition pos) { 360 return parallel_moves_[pos]; 361 } 362 363 private: 364 LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1]; 365 HBasicBlock* block_; 366 }; 367 368 369 class LGoto: public LTemplateInstruction<0, 0, 0> { 370 public: 371 LGoto(int block_id, bool include_stack_check = false) 372 : block_id_(block_id), include_stack_check_(include_stack_check) { } 373 374 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto") 375 virtual void PrintDataTo(StringStream* stream); 376 virtual bool IsControl() const { return true; } 377 378 int block_id() const { return block_id_; } 379 bool include_stack_check() const { return include_stack_check_; } 380 381 private: 382 int block_id_; 383 bool include_stack_check_; 384 }; 385 386 387 class LLazyBailout: public LTemplateInstruction<0, 0, 0> { 388 public: 389 LLazyBailout() : gap_instructions_size_(0) { } 390 391 DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout") 392 393 void set_gap_instructions_size(int gap_instructions_size) { 394 gap_instructions_size_ = gap_instructions_size; 395 } 396 int gap_instructions_size() { return gap_instructions_size_; } 397 398 private: 399 int gap_instructions_size_; 400 }; 401 402 403 class LDeoptimize: public LTemplateInstruction<0, 0, 0> { 404 public: 405 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize") 406 }; 407 408 409 class LLabel: public LGap { 410 public: 411 explicit LLabel(HBasicBlock* block) 412 : LGap(block), replacement_(NULL) { } 413 414 DECLARE_CONCRETE_INSTRUCTION(Label, "label") 415 416 virtual void PrintDataTo(StringStream* stream); 417 418 int block_id() const { return block()->block_id(); } 419 bool is_loop_header() const { return block()->IsLoopHeader(); } 420 Label* label() { return &label_; } 421 LLabel* replacement() const { return replacement_; } 422 void set_replacement(LLabel* label) { replacement_ = label; } 423 bool HasReplacement() const { return replacement_ != NULL; } 424 425 private: 426 Label label_; 427 LLabel* replacement_; 428 }; 429 430 431 class LParameter: public LTemplateInstruction<1, 0, 0> { 432 public: 433 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter") 434 }; 435 436 437 class LCallStub: public LTemplateInstruction<1, 0, 0> { 438 public: 439 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub") 440 DECLARE_HYDROGEN_ACCESSOR(CallStub) 441 442 TranscendentalCache::Type transcendental_type() { 443 return hydrogen()->transcendental_type(); 444 } 445 }; 446 447 448 class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> { 449 public: 450 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value") 451 }; 452 453 454 template<int I, int T> 455 class LControlInstruction: public LTemplateInstruction<0, I, T> { 456 public: 457 DECLARE_INSTRUCTION(ControlInstruction) 458 virtual bool IsControl() const { return true; } 459 460 int true_block_id() const { return true_block_id_; } 461 int false_block_id() const { return false_block_id_; } 462 void SetBranchTargets(int true_block_id, int false_block_id) { 463 true_block_id_ = true_block_id; 464 false_block_id_ = false_block_id; 465 } 466 467 private: 468 int true_block_id_; 469 int false_block_id_; 470 }; 471 472 473 class LApplyArguments: public LTemplateInstruction<1, 4, 0> { 474 public: 475 LApplyArguments(LOperand* function, 476 LOperand* receiver, 477 LOperand* length, 478 LOperand* elements) { 479 inputs_[0] = function; 480 inputs_[1] = receiver; 481 inputs_[2] = length; 482 inputs_[3] = elements; 483 } 484 485 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments") 486 487 LOperand* function() { return inputs_[0]; } 488 LOperand* receiver() { return inputs_[1]; } 489 LOperand* length() { return inputs_[2]; } 490 LOperand* elements() { return inputs_[3]; } 491 }; 492 493 494 class LAccessArgumentsAt: public LTemplateInstruction<1, 3, 0> { 495 public: 496 LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index) { 497 inputs_[0] = arguments; 498 inputs_[1] = length; 499 inputs_[2] = index; 500 } 501 502 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at") 503 504 LOperand* arguments() { return inputs_[0]; } 505 LOperand* length() { return inputs_[1]; } 506 LOperand* index() { return inputs_[2]; } 507 508 virtual void PrintDataTo(StringStream* stream); 509 }; 510 511 512 class LArgumentsLength: public LTemplateInstruction<1, 1, 0> { 513 public: 514 explicit LArgumentsLength(LOperand* elements) { 515 inputs_[0] = elements; 516 } 517 518 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length") 519 }; 520 521 522 class LArgumentsElements: public LTemplateInstruction<1, 0, 0> { 523 public: 524 LArgumentsElements() { } 525 526 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements") 527 }; 528 529 530 class LModI: public LTemplateInstruction<1, 2, 1> { 531 public: 532 LModI(LOperand* left, LOperand* right, LOperand* temp) { 533 inputs_[0] = left; 534 inputs_[1] = right; 535 temps_[0] = temp; 536 } 537 538 DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i") 539 DECLARE_HYDROGEN_ACCESSOR(Mod) 540 }; 541 542 543 class LDivI: public LTemplateInstruction<1, 2, 1> { 544 public: 545 LDivI(LOperand* left, LOperand* right, LOperand* temp) { 546 inputs_[0] = left; 547 inputs_[1] = right; 548 temps_[0] = temp; 549 } 550 551 DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i") 552 DECLARE_HYDROGEN_ACCESSOR(Div) 553 }; 554 555 556 class LMulI: public LTemplateInstruction<1, 2, 0> { 557 public: 558 LMulI(LOperand* left, LOperand* right) { 559 inputs_[0] = left; 560 inputs_[1] = right; 561 } 562 563 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i") 564 DECLARE_HYDROGEN_ACCESSOR(Mul) 565 }; 566 567 568 class LCmpID: public LTemplateInstruction<1, 2, 0> { 569 public: 570 LCmpID(LOperand* left, LOperand* right) { 571 inputs_[0] = left; 572 inputs_[1] = right; 573 } 574 575 DECLARE_CONCRETE_INSTRUCTION(CmpID, "cmp-id") 576 DECLARE_HYDROGEN_ACCESSOR(Compare) 577 578 Token::Value op() const { return hydrogen()->token(); } 579 bool is_double() const { 580 return hydrogen()->GetInputRepresentation().IsDouble(); 581 } 582 }; 583 584 585 class LCmpIDAndBranch: public LControlInstruction<2, 0> { 586 public: 587 LCmpIDAndBranch(LOperand* left, LOperand* right) { 588 inputs_[0] = left; 589 inputs_[1] = right; 590 } 591 592 DECLARE_CONCRETE_INSTRUCTION(CmpIDAndBranch, "cmp-id-and-branch") 593 DECLARE_HYDROGEN_ACCESSOR(Compare) 594 595 Token::Value op() const { return hydrogen()->token(); } 596 bool is_double() const { 597 return hydrogen()->GetInputRepresentation().IsDouble(); 598 } 599 600 virtual void PrintDataTo(StringStream* stream); 601 }; 602 603 604 class LUnaryMathOperation: public LTemplateInstruction<1, 1, 0> { 605 public: 606 explicit LUnaryMathOperation(LOperand* value) { 607 inputs_[0] = value; 608 } 609 610 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary-math-operation") 611 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation) 612 613 virtual void PrintDataTo(StringStream* stream); 614 BuiltinFunctionId op() const { return hydrogen()->op(); } 615 }; 616 617 618 class LCmpJSObjectEq: public LTemplateInstruction<1, 2, 0> { 619 public: 620 LCmpJSObjectEq(LOperand* left, LOperand* right) { 621 inputs_[0] = left; 622 inputs_[1] = right; 623 } 624 625 DECLARE_CONCRETE_INSTRUCTION(CmpJSObjectEq, "cmp-jsobject-eq") 626 }; 627 628 629 class LCmpJSObjectEqAndBranch: public LControlInstruction<2, 0> { 630 public: 631 LCmpJSObjectEqAndBranch(LOperand* left, LOperand* right) { 632 inputs_[0] = left; 633 inputs_[1] = right; 634 } 635 636 DECLARE_CONCRETE_INSTRUCTION(CmpJSObjectEqAndBranch, 637 "cmp-jsobject-eq-and-branch") 638 }; 639 640 641 class LIsNull: public LTemplateInstruction<1, 1, 0> { 642 public: 643 explicit LIsNull(LOperand* value) { 644 inputs_[0] = value; 645 } 646 647 DECLARE_CONCRETE_INSTRUCTION(IsNull, "is-null") 648 DECLARE_HYDROGEN_ACCESSOR(IsNull) 649 650 bool is_strict() const { return hydrogen()->is_strict(); } 651 }; 652 653 654 class LIsNullAndBranch: public LControlInstruction<1, 1> { 655 public: 656 LIsNullAndBranch(LOperand* value, LOperand* temp) { 657 inputs_[0] = value; 658 temps_[0] = temp; 659 } 660 661 DECLARE_CONCRETE_INSTRUCTION(IsNullAndBranch, "is-null-and-branch") 662 DECLARE_HYDROGEN_ACCESSOR(IsNull) 663 664 bool is_strict() const { return hydrogen()->is_strict(); } 665 666 virtual void PrintDataTo(StringStream* stream); 667 }; 668 669 670 class LIsObject: public LTemplateInstruction<1, 1, 0> { 671 public: 672 explicit LIsObject(LOperand* value) { 673 inputs_[0] = value; 674 } 675 676 DECLARE_CONCRETE_INSTRUCTION(IsObject, "is-object") 677 }; 678 679 680 class LIsObjectAndBranch: public LControlInstruction<1, 0> { 681 public: 682 explicit LIsObjectAndBranch(LOperand* value) { 683 inputs_[0] = value; 684 } 685 686 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch") 687 688 virtual void PrintDataTo(StringStream* stream); 689 }; 690 691 692 class LIsSmi: public LTemplateInstruction<1, 1, 0> { 693 public: 694 explicit LIsSmi(LOperand* value) { 695 inputs_[0] = value; 696 } 697 698 DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is-smi") 699 DECLARE_HYDROGEN_ACCESSOR(IsSmi) 700 }; 701 702 703 class LIsSmiAndBranch: public LControlInstruction<1, 0> { 704 public: 705 explicit LIsSmiAndBranch(LOperand* value) { 706 inputs_[0] = value; 707 } 708 709 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch") 710 711 virtual void PrintDataTo(StringStream* stream); 712 }; 713 714 715 class LHasInstanceType: public LTemplateInstruction<1, 1, 0> { 716 public: 717 explicit LHasInstanceType(LOperand* value) { 718 inputs_[0] = value; 719 } 720 721 DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has-instance-type") 722 DECLARE_HYDROGEN_ACCESSOR(HasInstanceType) 723 }; 724 725 726 class LHasInstanceTypeAndBranch: public LControlInstruction<1, 0> { 727 public: 728 explicit LHasInstanceTypeAndBranch(LOperand* value) { 729 inputs_[0] = value; 730 } 731 732 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch, 733 "has-instance-type-and-branch") 734 DECLARE_HYDROGEN_ACCESSOR(HasInstanceType) 735 736 virtual void PrintDataTo(StringStream* stream); 737 }; 738 739 740 class LGetCachedArrayIndex: public LTemplateInstruction<1, 1, 0> { 741 public: 742 explicit LGetCachedArrayIndex(LOperand* value) { 743 inputs_[0] = value; 744 } 745 746 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index") 747 DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex) 748 }; 749 750 751 class LHasCachedArrayIndex: public LTemplateInstruction<1, 1, 0> { 752 public: 753 explicit LHasCachedArrayIndex(LOperand* value) { 754 inputs_[0] = value; 755 } 756 757 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has-cached-array-index") 758 DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndex) 759 }; 760 761 762 class LHasCachedArrayIndexAndBranch: public LControlInstruction<1, 0> { 763 public: 764 explicit LHasCachedArrayIndexAndBranch(LOperand* value) { 765 inputs_[0] = value; 766 } 767 768 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch, 769 "has-cached-array-index-and-branch") 770 virtual void PrintDataTo(StringStream* stream); 771 }; 772 773 774 class LClassOfTest: public LTemplateInstruction<1, 1, 1> { 775 public: 776 LClassOfTest(LOperand* value, LOperand* temp) { 777 inputs_[0] = value; 778 temps_[0] = temp; 779 } 780 781 DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class-of-test") 782 DECLARE_HYDROGEN_ACCESSOR(ClassOfTest) 783 784 virtual void PrintDataTo(StringStream* stream); 785 }; 786 787 788 class LClassOfTestAndBranch: public LControlInstruction<1, 1> { 789 public: 790 LClassOfTestAndBranch(LOperand* value, LOperand* temp) { 791 inputs_[0] = value; 792 temps_[0] = temp; 793 } 794 795 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch, 796 "class-of-test-and-branch") 797 DECLARE_HYDROGEN_ACCESSOR(ClassOfTest) 798 799 virtual void PrintDataTo(StringStream* stream); 800 }; 801 802 803 class LCmpT: public LTemplateInstruction<1, 2, 0> { 804 public: 805 LCmpT(LOperand* left, LOperand* right) { 806 inputs_[0] = left; 807 inputs_[1] = right; 808 } 809 810 DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t") 811 DECLARE_HYDROGEN_ACCESSOR(Compare) 812 813 Token::Value op() const { return hydrogen()->token(); } 814 }; 815 816 817 class LCmpTAndBranch: public LControlInstruction<2, 0> { 818 public: 819 LCmpTAndBranch(LOperand* left, LOperand* right) { 820 inputs_[0] = left; 821 inputs_[1] = right; 822 } 823 824 DECLARE_CONCRETE_INSTRUCTION(CmpTAndBranch, "cmp-t-and-branch") 825 DECLARE_HYDROGEN_ACCESSOR(Compare) 826 827 Token::Value op() const { return hydrogen()->token(); } 828 }; 829 830 831 class LInstanceOf: public LTemplateInstruction<1, 2, 0> { 832 public: 833 LInstanceOf(LOperand* left, LOperand* right) { 834 inputs_[0] = left; 835 inputs_[1] = right; 836 } 837 838 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of") 839 }; 840 841 842 class LInstanceOfAndBranch: public LControlInstruction<2, 0> { 843 public: 844 LInstanceOfAndBranch(LOperand* left, LOperand* right) { 845 inputs_[0] = left; 846 inputs_[1] = right; 847 } 848 849 DECLARE_CONCRETE_INSTRUCTION(InstanceOfAndBranch, "instance-of-and-branch") 850 }; 851 852 853 class LInstanceOfKnownGlobal: public LTemplateInstruction<1, 1, 1> { 854 public: 855 LInstanceOfKnownGlobal(LOperand* value, LOperand* temp) { 856 inputs_[0] = value; 857 temps_[0] = temp; 858 } 859 860 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal, 861 "instance-of-known-global") 862 DECLARE_HYDROGEN_ACCESSOR(InstanceOfKnownGlobal) 863 864 Handle<JSFunction> function() const { return hydrogen()->function(); } 865 }; 866 867 868 class LBoundsCheck: public LTemplateInstruction<0, 2, 0> { 869 public: 870 LBoundsCheck(LOperand* index, LOperand* length) { 871 inputs_[0] = index; 872 inputs_[1] = length; 873 } 874 875 LOperand* index() { return inputs_[0]; } 876 LOperand* length() { return inputs_[1]; } 877 878 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check") 879 }; 880 881 882 class LBitI: public LTemplateInstruction<1, 2, 0> { 883 public: 884 LBitI(Token::Value op, LOperand* left, LOperand* right) 885 : op_(op) { 886 inputs_[0] = left; 887 inputs_[1] = right; 888 } 889 890 Token::Value op() const { return op_; } 891 892 DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i") 893 894 private: 895 Token::Value op_; 896 }; 897 898 899 class LShiftI: public LTemplateInstruction<1, 2, 0> { 900 public: 901 LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt) 902 : op_(op), can_deopt_(can_deopt) { 903 inputs_[0] = left; 904 inputs_[1] = right; 905 } 906 907 Token::Value op() const { return op_; } 908 909 bool can_deopt() const { return can_deopt_; } 910 911 DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i") 912 913 private: 914 Token::Value op_; 915 bool can_deopt_; 916 }; 917 918 919 class LSubI: public LTemplateInstruction<1, 2, 0> { 920 public: 921 LSubI(LOperand* left, LOperand* right) { 922 inputs_[0] = left; 923 inputs_[1] = right; 924 } 925 926 DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i") 927 DECLARE_HYDROGEN_ACCESSOR(Sub) 928 }; 929 930 931 class LConstantI: public LTemplateInstruction<1, 0, 0> { 932 public: 933 DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i") 934 DECLARE_HYDROGEN_ACCESSOR(Constant) 935 936 int32_t value() const { return hydrogen()->Integer32Value(); } 937 }; 938 939 940 class LConstantD: public LTemplateInstruction<1, 0, 1> { 941 public: 942 explicit LConstantD(LOperand* temp) { 943 temps_[0] = temp; 944 } 945 DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d") 946 DECLARE_HYDROGEN_ACCESSOR(Constant) 947 948 double value() const { return hydrogen()->DoubleValue(); } 949 }; 950 951 952 class LConstantT: public LTemplateInstruction<1, 0, 0> { 953 public: 954 DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t") 955 DECLARE_HYDROGEN_ACCESSOR(Constant) 956 957 Handle<Object> value() const { return hydrogen()->handle(); } 958 }; 959 960 961 class LBranch: public LControlInstruction<1, 0> { 962 public: 963 explicit LBranch(LOperand* value) { 964 inputs_[0] = value; 965 } 966 967 DECLARE_CONCRETE_INSTRUCTION(Branch, "branch") 968 DECLARE_HYDROGEN_ACCESSOR(Value) 969 970 virtual void PrintDataTo(StringStream* stream); 971 }; 972 973 974 class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 0> { 975 public: 976 explicit LCmpMapAndBranch(LOperand* value) { 977 inputs_[0] = value; 978 } 979 980 DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch") 981 DECLARE_HYDROGEN_ACCESSOR(CompareMap) 982 983 virtual bool IsControl() const { return true; } 984 985 Handle<Map> map() const { return hydrogen()->map(); } 986 int true_block_id() const { 987 return hydrogen()->FirstSuccessor()->block_id(); 988 } 989 int false_block_id() const { 990 return hydrogen()->SecondSuccessor()->block_id(); 991 } 992 }; 993 994 995 class LJSArrayLength: public LTemplateInstruction<1, 1, 0> { 996 public: 997 explicit LJSArrayLength(LOperand* value) { 998 inputs_[0] = value; 999 } 1000 1001 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length") 1002 DECLARE_HYDROGEN_ACCESSOR(JSArrayLength) 1003 }; 1004 1005 1006 class LExternalArrayLength: public LTemplateInstruction<1, 1, 0> { 1007 public: 1008 explicit LExternalArrayLength(LOperand* value) { 1009 inputs_[0] = value; 1010 } 1011 1012 DECLARE_CONCRETE_INSTRUCTION(ExternalArrayLength, "external-array-length") 1013 DECLARE_HYDROGEN_ACCESSOR(ExternalArrayLength) 1014 }; 1015 1016 1017 class LFixedArrayLength: public LTemplateInstruction<1, 1, 0> { 1018 public: 1019 explicit LFixedArrayLength(LOperand* value) { 1020 inputs_[0] = value; 1021 } 1022 1023 DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed-array-length") 1024 DECLARE_HYDROGEN_ACCESSOR(FixedArrayLength) 1025 }; 1026 1027 1028 class LValueOf: public LTemplateInstruction<1, 1, 0> { 1029 public: 1030 explicit LValueOf(LOperand* value) { 1031 inputs_[0] = value; 1032 } 1033 1034 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value-of") 1035 DECLARE_HYDROGEN_ACCESSOR(ValueOf) 1036 }; 1037 1038 1039 class LThrow: public LTemplateInstruction<0, 1, 0> { 1040 public: 1041 explicit LThrow(LOperand* value) { 1042 inputs_[0] = value; 1043 } 1044 1045 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw") 1046 }; 1047 1048 1049 class LBitNotI: public LTemplateInstruction<1, 1, 0> { 1050 public: 1051 explicit LBitNotI(LOperand* value) { 1052 inputs_[0] = value; 1053 } 1054 1055 DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i") 1056 }; 1057 1058 1059 class LAddI: public LTemplateInstruction<1, 2, 0> { 1060 public: 1061 LAddI(LOperand* left, LOperand* right) { 1062 inputs_[0] = left; 1063 inputs_[1] = right; 1064 } 1065 1066 DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i") 1067 DECLARE_HYDROGEN_ACCESSOR(Add) 1068 }; 1069 1070 1071 class LPower: public LTemplateInstruction<1, 2, 0> { 1072 public: 1073 LPower(LOperand* left, LOperand* right) { 1074 inputs_[0] = left; 1075 inputs_[1] = right; 1076 } 1077 1078 DECLARE_CONCRETE_INSTRUCTION(Power, "power") 1079 DECLARE_HYDROGEN_ACCESSOR(Power) 1080 }; 1081 1082 1083 class LArithmeticD: public LTemplateInstruction<1, 2, 0> { 1084 public: 1085 LArithmeticD(Token::Value op, LOperand* left, LOperand* right) 1086 : op_(op) { 1087 inputs_[0] = left; 1088 inputs_[1] = right; 1089 } 1090 1091 Token::Value op() const { return op_; } 1092 1093 virtual void CompileToNative(LCodeGen* generator); 1094 virtual const char* Mnemonic() const; 1095 1096 private: 1097 Token::Value op_; 1098 }; 1099 1100 1101 class LArithmeticT: public LTemplateInstruction<1, 2, 0> { 1102 public: 1103 LArithmeticT(Token::Value op, LOperand* left, LOperand* right) 1104 : op_(op) { 1105 inputs_[0] = left; 1106 inputs_[1] = right; 1107 } 1108 1109 virtual void CompileToNative(LCodeGen* generator); 1110 virtual const char* Mnemonic() const; 1111 1112 Token::Value op() const { return op_; } 1113 1114 private: 1115 Token::Value op_; 1116 }; 1117 1118 1119 class LReturn: public LTemplateInstruction<0, 1, 0> { 1120 public: 1121 explicit LReturn(LOperand* value) { 1122 inputs_[0] = value; 1123 } 1124 1125 DECLARE_CONCRETE_INSTRUCTION(Return, "return") 1126 }; 1127 1128 1129 class LLoadNamedField: public LTemplateInstruction<1, 1, 0> { 1130 public: 1131 explicit LLoadNamedField(LOperand* object) { 1132 inputs_[0] = object; 1133 } 1134 1135 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field") 1136 DECLARE_HYDROGEN_ACCESSOR(LoadNamedField) 1137 }; 1138 1139 1140 class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> { 1141 public: 1142 explicit LLoadNamedFieldPolymorphic(LOperand* object) { 1143 inputs_[0] = object; 1144 } 1145 1146 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic") 1147 DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic) 1148 1149 LOperand* object() { return inputs_[0]; } 1150 }; 1151 1152 1153 class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> { 1154 public: 1155 explicit LLoadNamedGeneric(LOperand* object) { 1156 inputs_[0] = object; 1157 } 1158 1159 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic") 1160 DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric) 1161 1162 LOperand* object() { return inputs_[0]; } 1163 Handle<Object> name() const { return hydrogen()->name(); } 1164 }; 1165 1166 1167 class LLoadFunctionPrototype: public LTemplateInstruction<1, 1, 0> { 1168 public: 1169 explicit LLoadFunctionPrototype(LOperand* function) { 1170 inputs_[0] = function; 1171 } 1172 1173 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype") 1174 DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype) 1175 1176 LOperand* function() { return inputs_[0]; } 1177 }; 1178 1179 1180 class LLoadElements: public LTemplateInstruction<1, 1, 0> { 1181 public: 1182 explicit LLoadElements(LOperand* object) { 1183 inputs_[0] = object; 1184 } 1185 1186 DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements") 1187 }; 1188 1189 1190 class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> { 1191 public: 1192 explicit LLoadExternalArrayPointer(LOperand* object) { 1193 inputs_[0] = object; 1194 } 1195 1196 DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer, 1197 "load-external-array-pointer") 1198 }; 1199 1200 1201 class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> { 1202 public: 1203 LLoadKeyedFastElement(LOperand* elements, LOperand* key) { 1204 inputs_[0] = elements; 1205 inputs_[1] = key; 1206 } 1207 1208 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, "load-keyed-fast-element") 1209 DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastElement) 1210 1211 LOperand* elements() { return inputs_[0]; } 1212 LOperand* key() { return inputs_[1]; } 1213 }; 1214 1215 1216 class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> { 1217 public: 1218 LLoadKeyedSpecializedArrayElement(LOperand* external_pointer, 1219 LOperand* key) { 1220 inputs_[0] = external_pointer; 1221 inputs_[1] = key; 1222 } 1223 1224 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement, 1225 "load-keyed-specialized-array-element") 1226 DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement) 1227 1228 LOperand* external_pointer() { return inputs_[0]; } 1229 LOperand* key() { return inputs_[1]; } 1230 ExternalArrayType array_type() const { 1231 return hydrogen()->array_type(); 1232 } 1233 }; 1234 1235 1236 class LLoadKeyedGeneric: public LTemplateInstruction<1, 2, 0> { 1237 public: 1238 LLoadKeyedGeneric(LOperand* obj, LOperand* key) { 1239 inputs_[0] = obj; 1240 inputs_[1] = key; 1241 } 1242 1243 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic") 1244 1245 LOperand* object() { return inputs_[0]; } 1246 LOperand* key() { return inputs_[1]; } 1247 }; 1248 1249 1250 class LLoadGlobalCell: public LTemplateInstruction<1, 0, 0> { 1251 public: 1252 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell") 1253 DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell) 1254 }; 1255 1256 1257 class LLoadGlobalGeneric: public LTemplateInstruction<1, 1, 0> { 1258 public: 1259 explicit LLoadGlobalGeneric(LOperand* global_object) { 1260 inputs_[0] = global_object; 1261 } 1262 1263 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic") 1264 DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric) 1265 1266 LOperand* global_object() { return inputs_[0]; } 1267 Handle<Object> name() const { return hydrogen()->name(); } 1268 bool for_typeof() const { return hydrogen()->for_typeof(); } 1269 }; 1270 1271 1272 class LStoreGlobalCell: public LTemplateInstruction<0, 1, 1> { 1273 public: 1274 explicit LStoreGlobalCell(LOperand* value, LOperand* temp) { 1275 inputs_[0] = value; 1276 temps_[0] = temp; 1277 } 1278 1279 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell") 1280 DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell) 1281 }; 1282 1283 1284 class LStoreGlobalGeneric: public LTemplateInstruction<0, 2, 0> { 1285 public: 1286 explicit LStoreGlobalGeneric(LOperand* global_object, 1287 LOperand* value) { 1288 inputs_[0] = global_object; 1289 inputs_[1] = value; 1290 } 1291 1292 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic") 1293 DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric) 1294 1295 LOperand* global_object() { return InputAt(0); } 1296 Handle<Object> name() const { return hydrogen()->name(); } 1297 LOperand* value() { return InputAt(1); } 1298 bool strict_mode() { return hydrogen()->strict_mode(); } 1299 }; 1300 1301 1302 class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> { 1303 public: 1304 explicit LLoadContextSlot(LOperand* context) { 1305 inputs_[0] = context; 1306 } 1307 1308 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot") 1309 DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot) 1310 1311 LOperand* context() { return InputAt(0); } 1312 int slot_index() { return hydrogen()->slot_index(); } 1313 1314 virtual void PrintDataTo(StringStream* stream); 1315 }; 1316 1317 1318 class LStoreContextSlot: public LTemplateInstruction<0, 2, 1> { 1319 public: 1320 LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) { 1321 inputs_[0] = context; 1322 inputs_[1] = value; 1323 temps_[0] = temp; 1324 } 1325 1326 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot") 1327 DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot) 1328 1329 LOperand* context() { return InputAt(0); } 1330 LOperand* value() { return InputAt(1); } 1331 int slot_index() { return hydrogen()->slot_index(); } 1332 int needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); } 1333 1334 virtual void PrintDataTo(StringStream* stream); 1335 }; 1336 1337 1338 class LPushArgument: public LTemplateInstruction<0, 1, 0> { 1339 public: 1340 explicit LPushArgument(LOperand* value) { 1341 inputs_[0] = value; 1342 } 1343 1344 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument") 1345 }; 1346 1347 1348 class LContext: public LTemplateInstruction<1, 0, 0> { 1349 public: 1350 DECLARE_CONCRETE_INSTRUCTION(Context, "context") 1351 }; 1352 1353 1354 class LOuterContext: public LTemplateInstruction<1, 1, 0> { 1355 public: 1356 explicit LOuterContext(LOperand* context) { 1357 inputs_[0] = context; 1358 } 1359 1360 DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer-context") 1361 1362 LOperand* context() { return InputAt(0); } 1363 }; 1364 1365 1366 class LGlobalObject: public LTemplateInstruction<1, 0, 0> { 1367 public: 1368 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object") 1369 }; 1370 1371 1372 class LGlobalReceiver: public LTemplateInstruction<1, 1, 0> { 1373 public: 1374 explicit LGlobalReceiver(LOperand* global_object) { 1375 inputs_[0] = global_object; 1376 } 1377 1378 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global-receiver") 1379 1380 LOperand* global() { return InputAt(0); } 1381 }; 1382 1383 1384 class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> { 1385 public: 1386 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call-constant-function") 1387 DECLARE_HYDROGEN_ACCESSOR(CallConstantFunction) 1388 1389 virtual void PrintDataTo(StringStream* stream); 1390 1391 Handle<JSFunction> function() { return hydrogen()->function(); } 1392 int arity() const { return hydrogen()->argument_count() - 1; } 1393 }; 1394 1395 1396 class LCallKeyed: public LTemplateInstruction<1, 1, 0> { 1397 public: 1398 explicit LCallKeyed(LOperand* key) { 1399 inputs_[0] = key; 1400 } 1401 1402 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed") 1403 DECLARE_HYDROGEN_ACCESSOR(CallKeyed) 1404 1405 LOperand* key() { return inputs_[0]; } 1406 1407 virtual void PrintDataTo(StringStream* stream); 1408 1409 int arity() const { return hydrogen()->argument_count() - 1; } 1410 }; 1411 1412 1413 class LCallNamed: public LTemplateInstruction<1, 0, 0> { 1414 public: 1415 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call-named") 1416 DECLARE_HYDROGEN_ACCESSOR(CallNamed) 1417 1418 virtual void PrintDataTo(StringStream* stream); 1419 1420 Handle<String> name() const { return hydrogen()->name(); } 1421 int arity() const { return hydrogen()->argument_count() - 1; } 1422 }; 1423 1424 1425 class LCallFunction: public LTemplateInstruction<1, 0, 0> { 1426 public: 1427 LCallFunction() {} 1428 1429 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function") 1430 DECLARE_HYDROGEN_ACCESSOR(CallFunction) 1431 1432 int arity() const { return hydrogen()->argument_count() - 2; } 1433 }; 1434 1435 1436 class LCallGlobal: public LTemplateInstruction<1, 0, 0> { 1437 public: 1438 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global") 1439 DECLARE_HYDROGEN_ACCESSOR(CallGlobal) 1440 1441 virtual void PrintDataTo(StringStream* stream); 1442 1443 Handle<String> name() const {return hydrogen()->name(); } 1444 int arity() const { return hydrogen()->argument_count() - 1; } 1445 }; 1446 1447 1448 class LCallKnownGlobal: public LTemplateInstruction<1, 0, 0> { 1449 public: 1450 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call-known-global") 1451 DECLARE_HYDROGEN_ACCESSOR(CallKnownGlobal) 1452 1453 virtual void PrintDataTo(StringStream* stream); 1454 1455 Handle<JSFunction> target() const { return hydrogen()->target(); } 1456 int arity() const { return hydrogen()->argument_count() - 1; } 1457 }; 1458 1459 1460 class LCallNew: public LTemplateInstruction<1, 1, 0> { 1461 public: 1462 explicit LCallNew(LOperand* constructor) { 1463 inputs_[0] = constructor; 1464 } 1465 1466 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new") 1467 DECLARE_HYDROGEN_ACCESSOR(CallNew) 1468 1469 virtual void PrintDataTo(StringStream* stream); 1470 1471 int arity() const { return hydrogen()->argument_count() - 1; } 1472 }; 1473 1474 1475 class LCallRuntime: public LTemplateInstruction<1, 0, 0> { 1476 public: 1477 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime") 1478 DECLARE_HYDROGEN_ACCESSOR(CallRuntime) 1479 1480 const Runtime::Function* function() const { return hydrogen()->function(); } 1481 int arity() const { return hydrogen()->argument_count(); } 1482 }; 1483 1484 1485 class LInteger32ToDouble: public LTemplateInstruction<1, 1, 0> { 1486 public: 1487 explicit LInteger32ToDouble(LOperand* value) { 1488 inputs_[0] = value; 1489 } 1490 1491 DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double") 1492 }; 1493 1494 1495 class LNumberTagI: public LTemplateInstruction<1, 1, 0> { 1496 public: 1497 explicit LNumberTagI(LOperand* value) { 1498 inputs_[0] = value; 1499 } 1500 1501 DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i") 1502 }; 1503 1504 1505 class LNumberTagD: public LTemplateInstruction<1, 1, 1> { 1506 public: 1507 explicit LNumberTagD(LOperand* value, LOperand* temp) { 1508 inputs_[0] = value; 1509 temps_[0] = temp; 1510 } 1511 1512 DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d") 1513 }; 1514 1515 1516 // Sometimes truncating conversion from a tagged value to an int32. 1517 class LDoubleToI: public LTemplateInstruction<1, 1, 0> { 1518 public: 1519 explicit LDoubleToI(LOperand* value) { 1520 inputs_[0] = value; 1521 } 1522 1523 DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i") 1524 DECLARE_HYDROGEN_ACCESSOR(Change) 1525 1526 bool truncating() { return hydrogen()->CanTruncateToInt32(); } 1527 }; 1528 1529 1530 // Truncating conversion from a tagged value to an int32. 1531 class LTaggedToI: public LTemplateInstruction<1, 1, 1> { 1532 public: 1533 LTaggedToI(LOperand* value, LOperand* temp) { 1534 inputs_[0] = value; 1535 temps_[0] = temp; 1536 } 1537 1538 DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i") 1539 DECLARE_HYDROGEN_ACCESSOR(Change) 1540 1541 bool truncating() { return hydrogen()->CanTruncateToInt32(); } 1542 }; 1543 1544 1545 class LSmiTag: public LTemplateInstruction<1, 1, 0> { 1546 public: 1547 explicit LSmiTag(LOperand* value) { 1548 inputs_[0] = value; 1549 } 1550 1551 DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag") 1552 }; 1553 1554 1555 class LNumberUntagD: public LTemplateInstruction<1, 1, 0> { 1556 public: 1557 explicit LNumberUntagD(LOperand* value) { 1558 inputs_[0] = value; 1559 } 1560 1561 DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag") 1562 DECLARE_HYDROGEN_ACCESSOR(Change); 1563 }; 1564 1565 1566 class LSmiUntag: public LTemplateInstruction<1, 1, 0> { 1567 public: 1568 LSmiUntag(LOperand* value, bool needs_check) 1569 : needs_check_(needs_check) { 1570 inputs_[0] = value; 1571 } 1572 1573 DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag") 1574 1575 bool needs_check() const { return needs_check_; } 1576 1577 private: 1578 bool needs_check_; 1579 }; 1580 1581 1582 class LStoreNamedField: public LTemplateInstruction<0, 2, 1> { 1583 public: 1584 LStoreNamedField(LOperand* object, LOperand* value, LOperand* temp) { 1585 inputs_[0] = object; 1586 inputs_[1] = value; 1587 temps_[0] = temp; 1588 } 1589 1590 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field") 1591 DECLARE_HYDROGEN_ACCESSOR(StoreNamedField) 1592 1593 virtual void PrintDataTo(StringStream* stream); 1594 1595 LOperand* object() { return inputs_[0]; } 1596 LOperand* value() { return inputs_[1]; } 1597 1598 Handle<Object> name() const { return hydrogen()->name(); } 1599 bool is_in_object() { return hydrogen()->is_in_object(); } 1600 int offset() { return hydrogen()->offset(); } 1601 bool needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); } 1602 Handle<Map> transition() const { return hydrogen()->transition(); } 1603 }; 1604 1605 1606 class LStoreNamedGeneric: public LTemplateInstruction<0, 2, 0> { 1607 public: 1608 LStoreNamedGeneric(LOperand* object, LOperand* value) { 1609 inputs_[0] = object; 1610 inputs_[1] = value; 1611 } 1612 1613 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic") 1614 DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric) 1615 1616 virtual void PrintDataTo(StringStream* stream); 1617 1618 LOperand* object() { return inputs_[0]; } 1619 LOperand* value() { return inputs_[1]; } 1620 Handle<Object> name() const { return hydrogen()->name(); } 1621 bool strict_mode() { return hydrogen()->strict_mode(); } 1622 }; 1623 1624 1625 class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> { 1626 public: 1627 LStoreKeyedFastElement(LOperand* obj, LOperand* key, LOperand* val) { 1628 inputs_[0] = obj; 1629 inputs_[1] = key; 1630 inputs_[2] = val; 1631 } 1632 1633 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement, 1634 "store-keyed-fast-element") 1635 DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement) 1636 1637 virtual void PrintDataTo(StringStream* stream); 1638 1639 LOperand* object() { return inputs_[0]; } 1640 LOperand* key() { return inputs_[1]; } 1641 LOperand* value() { return inputs_[2]; } 1642 }; 1643 1644 1645 class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> { 1646 public: 1647 LStoreKeyedSpecializedArrayElement(LOperand* external_pointer, 1648 LOperand* key, 1649 LOperand* val) { 1650 inputs_[0] = external_pointer; 1651 inputs_[1] = key; 1652 inputs_[2] = val; 1653 } 1654 1655 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement, 1656 "store-keyed-specialized-array-element") 1657 DECLARE_HYDROGEN_ACCESSOR(StoreKeyedSpecializedArrayElement) 1658 1659 LOperand* external_pointer() { return inputs_[0]; } 1660 LOperand* key() { return inputs_[1]; } 1661 LOperand* value() { return inputs_[2]; } 1662 ExternalArrayType array_type() const { 1663 return hydrogen()->array_type(); 1664 } 1665 }; 1666 1667 1668 class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> { 1669 public: 1670 LStoreKeyedGeneric(LOperand* object, LOperand* key, LOperand* value) { 1671 inputs_[0] = object; 1672 inputs_[1] = key; 1673 inputs_[2] = value; 1674 } 1675 1676 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic") 1677 DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric) 1678 1679 virtual void PrintDataTo(StringStream* stream); 1680 1681 LOperand* object() { return inputs_[0]; } 1682 LOperand* key() { return inputs_[1]; } 1683 LOperand* value() { return inputs_[2]; } 1684 bool strict_mode() { return hydrogen()->strict_mode(); } 1685 }; 1686 1687 1688 class LStringCharCodeAt: public LTemplateInstruction<1, 2, 0> { 1689 public: 1690 LStringCharCodeAt(LOperand* string, LOperand* index) { 1691 inputs_[0] = string; 1692 inputs_[1] = index; 1693 } 1694 1695 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at") 1696 DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt) 1697 1698 LOperand* string() { return inputs_[0]; } 1699 LOperand* index() { return inputs_[1]; } 1700 }; 1701 1702 1703 class LStringCharFromCode: public LTemplateInstruction<1, 1, 0> { 1704 public: 1705 explicit LStringCharFromCode(LOperand* char_code) { 1706 inputs_[0] = char_code; 1707 } 1708 1709 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code") 1710 DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode) 1711 1712 LOperand* char_code() { return inputs_[0]; } 1713 }; 1714 1715 1716 class LStringLength: public LTemplateInstruction<1, 1, 0> { 1717 public: 1718 explicit LStringLength(LOperand* string) { 1719 inputs_[0] = string; 1720 } 1721 1722 DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length") 1723 DECLARE_HYDROGEN_ACCESSOR(StringLength) 1724 1725 LOperand* string() { return inputs_[0]; } 1726 }; 1727 1728 1729 class LCheckFunction: public LTemplateInstruction<0, 1, 0> { 1730 public: 1731 explicit LCheckFunction(LOperand* value) { 1732 inputs_[0] = value; 1733 } 1734 1735 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function") 1736 DECLARE_HYDROGEN_ACCESSOR(CheckFunction) 1737 }; 1738 1739 1740 class LCheckInstanceType: public LTemplateInstruction<0, 1, 0> { 1741 public: 1742 explicit LCheckInstanceType(LOperand* value) { 1743 inputs_[0] = value; 1744 } 1745 1746 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type") 1747 DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType) 1748 }; 1749 1750 1751 class LCheckMap: public LTemplateInstruction<0, 1, 0> { 1752 public: 1753 explicit LCheckMap(LOperand* value) { 1754 inputs_[0] = value; 1755 } 1756 1757 DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check-map") 1758 DECLARE_HYDROGEN_ACCESSOR(CheckMap) 1759 }; 1760 1761 1762 class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 1> { 1763 public: 1764 explicit LCheckPrototypeMaps(LOperand* temp) { 1765 temps_[0] = temp; 1766 } 1767 1768 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps") 1769 DECLARE_HYDROGEN_ACCESSOR(CheckPrototypeMaps) 1770 1771 Handle<JSObject> prototype() const { return hydrogen()->prototype(); } 1772 Handle<JSObject> holder() const { return hydrogen()->holder(); } 1773 }; 1774 1775 1776 class LCheckSmi: public LTemplateInstruction<0, 1, 0> { 1777 public: 1778 explicit LCheckSmi(LOperand* value) { 1779 inputs_[0] = value; 1780 } 1781 1782 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi") 1783 }; 1784 1785 1786 class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> { 1787 public: 1788 explicit LCheckNonSmi(LOperand* value) { 1789 inputs_[0] = value; 1790 } 1791 1792 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi") 1793 }; 1794 1795 1796 class LArrayLiteral: public LTemplateInstruction<1, 0, 0> { 1797 public: 1798 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array-literal") 1799 DECLARE_HYDROGEN_ACCESSOR(ArrayLiteral) 1800 }; 1801 1802 1803 class LObjectLiteral: public LTemplateInstruction<1, 0, 0> { 1804 public: 1805 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object-literal") 1806 DECLARE_HYDROGEN_ACCESSOR(ObjectLiteral) 1807 }; 1808 1809 1810 class LRegExpLiteral: public LTemplateInstruction<1, 0, 0> { 1811 public: 1812 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal") 1813 DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral) 1814 }; 1815 1816 1817 class LFunctionLiteral: public LTemplateInstruction<1, 0, 0> { 1818 public: 1819 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal") 1820 DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral) 1821 1822 Handle<SharedFunctionInfo> shared_info() { return hydrogen()->shared_info(); } 1823 }; 1824 1825 1826 class LToFastProperties: public LTemplateInstruction<1, 1, 0> { 1827 public: 1828 explicit LToFastProperties(LOperand* value) { 1829 inputs_[0] = value; 1830 } 1831 1832 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties") 1833 DECLARE_HYDROGEN_ACCESSOR(ToFastProperties) 1834 }; 1835 1836 1837 class LTypeof: public LTemplateInstruction<1, 1, 0> { 1838 public: 1839 explicit LTypeof(LOperand* value) { 1840 inputs_[0] = value; 1841 } 1842 1843 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof") 1844 }; 1845 1846 1847 class LTypeofIs: public LTemplateInstruction<1, 1, 0> { 1848 public: 1849 explicit LTypeofIs(LOperand* value) { 1850 inputs_[0] = value; 1851 } 1852 1853 DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof-is") 1854 DECLARE_HYDROGEN_ACCESSOR(TypeofIs) 1855 1856 Handle<String> type_literal() { return hydrogen()->type_literal(); } 1857 1858 virtual void PrintDataTo(StringStream* stream); 1859 }; 1860 1861 1862 class LTypeofIsAndBranch: public LControlInstruction<1, 0> { 1863 public: 1864 explicit LTypeofIsAndBranch(LOperand* value) { 1865 inputs_[0] = value; 1866 } 1867 1868 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch") 1869 DECLARE_HYDROGEN_ACCESSOR(TypeofIs) 1870 1871 Handle<String> type_literal() { return hydrogen()->type_literal(); } 1872 1873 virtual void PrintDataTo(StringStream* stream); 1874 }; 1875 1876 1877 class LIsConstructCall: public LTemplateInstruction<1, 0, 0> { 1878 public: 1879 DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is-construct-call") 1880 DECLARE_HYDROGEN_ACCESSOR(IsConstructCall) 1881 }; 1882 1883 1884 class LIsConstructCallAndBranch: public LControlInstruction<0, 1> { 1885 public: 1886 explicit LIsConstructCallAndBranch(LOperand* temp) { 1887 temps_[0] = temp; 1888 } 1889 1890 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch, 1891 "is-construct-call-and-branch") 1892 }; 1893 1894 1895 class LDeleteProperty: public LTemplateInstruction<1, 2, 0> { 1896 public: 1897 LDeleteProperty(LOperand* obj, LOperand* key) { 1898 inputs_[0] = obj; 1899 inputs_[1] = key; 1900 } 1901 1902 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete-property") 1903 1904 LOperand* object() { return inputs_[0]; } 1905 LOperand* key() { return inputs_[1]; } 1906 }; 1907 1908 1909 class LOsrEntry: public LTemplateInstruction<0, 0, 0> { 1910 public: 1911 LOsrEntry(); 1912 1913 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry") 1914 1915 LOperand** SpilledRegisterArray() { return register_spills_; } 1916 LOperand** SpilledDoubleRegisterArray() { return double_register_spills_; } 1917 1918 void MarkSpilledRegister(int allocation_index, LOperand* spill_operand); 1919 void MarkSpilledDoubleRegister(int allocation_index, 1920 LOperand* spill_operand); 1921 1922 private: 1923 // Arrays of spill slot operands for registers with an assigned spill 1924 // slot, i.e., that must also be restored to the spill slot on OSR entry. 1925 // NULL if the register has no assigned spill slot. Indexed by allocation 1926 // index. 1927 LOperand* register_spills_[Register::kNumAllocatableRegisters]; 1928 LOperand* double_register_spills_[DoubleRegister::kNumAllocatableRegisters]; 1929 }; 1930 1931 1932 class LStackCheck: public LTemplateInstruction<0, 0, 0> { 1933 public: 1934 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check") 1935 }; 1936 1937 1938 class LChunkBuilder; 1939 class LChunk: public ZoneObject { 1940 public: 1941 explicit LChunk(CompilationInfo* info, HGraph* graph) 1942 : spill_slot_count_(0), 1943 info_(info), 1944 graph_(graph), 1945 instructions_(32), 1946 pointer_maps_(8), 1947 inlined_closures_(1) { } 1948 1949 void AddInstruction(LInstruction* instruction, HBasicBlock* block); 1950 LConstantOperand* DefineConstantOperand(HConstant* constant); 1951 Handle<Object> LookupLiteral(LConstantOperand* operand) const; 1952 Representation LookupLiteralRepresentation(LConstantOperand* operand) const; 1953 1954 int GetNextSpillIndex(bool is_double); 1955 LOperand* GetNextSpillSlot(bool is_double); 1956 1957 int ParameterAt(int index); 1958 int GetParameterStackSlot(int index) const; 1959 int spill_slot_count() const { return spill_slot_count_; } 1960 CompilationInfo* info() const { return info_; } 1961 HGraph* graph() const { return graph_; } 1962 const ZoneList<LInstruction*>* instructions() const { return &instructions_; } 1963 void AddGapMove(int index, LOperand* from, LOperand* to); 1964 LGap* GetGapAt(int index) const; 1965 bool IsGapAt(int index) const; 1966 int NearestGapPos(int index) const; 1967 void MarkEmptyBlocks(); 1968 const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; } 1969 LLabel* GetLabel(int block_id) const { 1970 HBasicBlock* block = graph_->blocks()->at(block_id); 1971 int first_instruction = block->first_instruction_index(); 1972 return LLabel::cast(instructions_[first_instruction]); 1973 } 1974 int LookupDestination(int block_id) const { 1975 LLabel* cur = GetLabel(block_id); 1976 while (cur->replacement() != NULL) { 1977 cur = cur->replacement(); 1978 } 1979 return cur->block_id(); 1980 } 1981 Label* GetAssemblyLabel(int block_id) const { 1982 LLabel* label = GetLabel(block_id); 1983 ASSERT(!label->HasReplacement()); 1984 return label->label(); 1985 } 1986 1987 const ZoneList<Handle<JSFunction> >* inlined_closures() const { 1988 return &inlined_closures_; 1989 } 1990 1991 void AddInlinedClosure(Handle<JSFunction> closure) { 1992 inlined_closures_.Add(closure); 1993 } 1994 1995 private: 1996 int spill_slot_count_; 1997 CompilationInfo* info_; 1998 HGraph* const graph_; 1999 ZoneList<LInstruction*> instructions_; 2000 ZoneList<LPointerMap*> pointer_maps_; 2001 ZoneList<Handle<JSFunction> > inlined_closures_; 2002 }; 2003 2004 2005 class LChunkBuilder BASE_EMBEDDED { 2006 public: 2007 LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator) 2008 : chunk_(NULL), 2009 info_(info), 2010 graph_(graph), 2011 status_(UNUSED), 2012 current_instruction_(NULL), 2013 current_block_(NULL), 2014 next_block_(NULL), 2015 argument_count_(0), 2016 allocator_(allocator), 2017 position_(RelocInfo::kNoPosition), 2018 instruction_pending_deoptimization_environment_(NULL), 2019 pending_deoptimization_ast_id_(AstNode::kNoNumber) { } 2020 2021 // Build the sequence for the graph. 2022 LChunk* Build(); 2023 2024 // Declare methods that deal with the individual node types. 2025 #define DECLARE_DO(type) LInstruction* Do##type(H##type* node); 2026 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) 2027 #undef DECLARE_DO 2028 2029 private: 2030 enum Status { 2031 UNUSED, 2032 BUILDING, 2033 DONE, 2034 ABORTED 2035 }; 2036 2037 LChunk* chunk() const { return chunk_; } 2038 CompilationInfo* info() const { return info_; } 2039 HGraph* graph() const { return graph_; } 2040 2041 bool is_unused() const { return status_ == UNUSED; } 2042 bool is_building() const { return status_ == BUILDING; } 2043 bool is_done() const { return status_ == DONE; } 2044 bool is_aborted() const { return status_ == ABORTED; } 2045 2046 void Abort(const char* format, ...); 2047 2048 // Methods for getting operands for Use / Define / Temp. 2049 LRegister* ToOperand(Register reg); 2050 LUnallocated* ToUnallocated(Register reg); 2051 LUnallocated* ToUnallocated(XMMRegister reg); 2052 2053 // Methods for setting up define-use relationships. 2054 MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand); 2055 MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register); 2056 MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value, 2057 XMMRegister fixed_register); 2058 2059 // A value that is guaranteed to be allocated to a register. 2060 // Operand created by UseRegister is guaranteed to be live until the end of 2061 // instruction. This means that register allocator will not reuse it's 2062 // register for any other operand inside instruction. 2063 // Operand created by UseRegisterAtStart is guaranteed to be live only at 2064 // instruction start. Register allocator is free to assign the same register 2065 // to some other operand used inside instruction (i.e. temporary or 2066 // output). 2067 MUST_USE_RESULT LOperand* UseRegister(HValue* value); 2068 MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value); 2069 2070 // An input operand in a register that may be trashed. 2071 MUST_USE_RESULT LOperand* UseTempRegister(HValue* value); 2072 2073 // An input operand in a register or stack slot. 2074 MUST_USE_RESULT LOperand* Use(HValue* value); 2075 MUST_USE_RESULT LOperand* UseAtStart(HValue* value); 2076 2077 // An input operand in a register, stack slot or a constant operand. 2078 MUST_USE_RESULT LOperand* UseOrConstant(HValue* value); 2079 MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value); 2080 2081 // An input operand in a register or a constant operand. 2082 MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value); 2083 MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value); 2084 2085 // An input operand in register, stack slot or a constant operand. 2086 // Will not be moved to a register even if one is freely available. 2087 MUST_USE_RESULT LOperand* UseAny(HValue* value); 2088 2089 // Temporary operand that must be in a register. 2090 MUST_USE_RESULT LUnallocated* TempRegister(); 2091 MUST_USE_RESULT LOperand* FixedTemp(Register reg); 2092 MUST_USE_RESULT LOperand* FixedTemp(XMMRegister reg); 2093 2094 // Methods for setting up define-use relationships. 2095 // Return the same instruction that they are passed. 2096 template<int I, int T> 2097 LInstruction* Define(LTemplateInstruction<1, I, T>* instr, 2098 LUnallocated* result); 2099 template<int I, int T> 2100 LInstruction* Define(LTemplateInstruction<1, I, T>* instr); 2101 template<int I, int T> 2102 LInstruction* DefineAsRegister(LTemplateInstruction<1, I, T>* instr); 2103 template<int I, int T> 2104 LInstruction* DefineAsSpilled(LTemplateInstruction<1, I, T>* instr, 2105 int index); 2106 template<int I, int T> 2107 LInstruction* DefineSameAsFirst(LTemplateInstruction<1, I, T>* instr); 2108 template<int I, int T> 2109 LInstruction* DefineFixed(LTemplateInstruction<1, I, T>* instr, 2110 Register reg); 2111 template<int I, int T> 2112 LInstruction* DefineFixedDouble(LTemplateInstruction<1, I, T>* instr, 2113 XMMRegister reg); 2114 LInstruction* AssignEnvironment(LInstruction* instr); 2115 LInstruction* AssignPointerMap(LInstruction* instr); 2116 2117 enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY }; 2118 2119 // By default we assume that instruction sequences generated for calls 2120 // cannot deoptimize eagerly and we do not attach environment to this 2121 // instruction. 2122 LInstruction* MarkAsCall( 2123 LInstruction* instr, 2124 HInstruction* hinstr, 2125 CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY); 2126 LInstruction* MarkAsSaveDoubles(LInstruction* instr); 2127 2128 LInstruction* SetInstructionPendingDeoptimizationEnvironment( 2129 LInstruction* instr, int ast_id); 2130 void ClearInstructionPendingDeoptimizationEnvironment(); 2131 2132 LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env); 2133 2134 void VisitInstruction(HInstruction* current); 2135 2136 void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block); 2137 LInstruction* DoBit(Token::Value op, HBitwiseBinaryOperation* instr); 2138 LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr); 2139 LInstruction* DoArithmeticD(Token::Value op, 2140 HArithmeticBinaryOperation* instr); 2141 LInstruction* DoArithmeticT(Token::Value op, 2142 HArithmeticBinaryOperation* instr); 2143 2144 LChunk* chunk_; 2145 CompilationInfo* info_; 2146 HGraph* const graph_; 2147 Status status_; 2148 HInstruction* current_instruction_; 2149 HBasicBlock* current_block_; 2150 HBasicBlock* next_block_; 2151 int argument_count_; 2152 LAllocator* allocator_; 2153 int position_; 2154 LInstruction* instruction_pending_deoptimization_environment_; 2155 int pending_deoptimization_ast_id_; 2156 2157 DISALLOW_COPY_AND_ASSIGN(LChunkBuilder); 2158 }; 2159 2160 #undef DECLARE_HYDROGEN_ACCESSOR 2161 #undef DECLARE_INSTRUCTION 2162 #undef DECLARE_CONCRETE_INSTRUCTION 2163 2164 } } // namespace v8::int 2165 2166 #endif // V8_X64_LITHIUM_X64_H_ 2167