1 // Copyright 2012 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_IA32_LITHIUM_IA32_H_ 29 #define V8_IA32_LITHIUM_IA32_H_ 30 31 #include "hydrogen.h" 32 #include "lithium-allocator.h" 33 #include "lithium.h" 34 #include "safepoint-table.h" 35 #include "utils.h" 36 37 namespace v8 { 38 namespace internal { 39 40 // Forward declarations. 41 class LCodeGen; 42 43 #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \ 44 V(AccessArgumentsAt) \ 45 V(AddI) \ 46 V(Allocate) \ 47 V(ApplyArguments) \ 48 V(ArgumentsElements) \ 49 V(ArgumentsLength) \ 50 V(ArithmeticD) \ 51 V(ArithmeticT) \ 52 V(BitI) \ 53 V(BoundsCheck) \ 54 V(Branch) \ 55 V(CallConstantFunction) \ 56 V(CallFunction) \ 57 V(CallGlobal) \ 58 V(CallKeyed) \ 59 V(CallKnownGlobal) \ 60 V(CallNamed) \ 61 V(CallNew) \ 62 V(CallNewArray) \ 63 V(CallRuntime) \ 64 V(CallStub) \ 65 V(CheckFunction) \ 66 V(CheckInstanceType) \ 67 V(CheckMaps) \ 68 V(CheckMapValue) \ 69 V(CheckNonSmi) \ 70 V(CheckSmi) \ 71 V(ClampDToUint8) \ 72 V(ClampIToUint8) \ 73 V(ClampTToUint8) \ 74 V(ClampTToUint8NoSSE2) \ 75 V(ClassOfTestAndBranch) \ 76 V(CompareNumericAndBranch) \ 77 V(CmpObjectEqAndBranch) \ 78 V(CmpHoleAndBranch) \ 79 V(CmpMapAndBranch) \ 80 V(CmpT) \ 81 V(ConstantD) \ 82 V(ConstantE) \ 83 V(ConstantI) \ 84 V(ConstantS) \ 85 V(ConstantT) \ 86 V(Context) \ 87 V(DateField) \ 88 V(DebugBreak) \ 89 V(DeclareGlobals) \ 90 V(Deoptimize) \ 91 V(DivI) \ 92 V(DoubleToI) \ 93 V(DoubleToSmi) \ 94 V(Drop) \ 95 V(DummyUse) \ 96 V(ElementsKind) \ 97 V(ForInCacheArray) \ 98 V(ForInPrepareMap) \ 99 V(FunctionLiteral) \ 100 V(GetCachedArrayIndex) \ 101 V(GlobalObject) \ 102 V(GlobalReceiver) \ 103 V(Goto) \ 104 V(HasCachedArrayIndexAndBranch) \ 105 V(HasInstanceTypeAndBranch) \ 106 V(InnerAllocatedObject) \ 107 V(InstanceOf) \ 108 V(InstanceOfKnownGlobal) \ 109 V(InstanceSize) \ 110 V(InstructionGap) \ 111 V(Integer32ToDouble) \ 112 V(Integer32ToSmi) \ 113 V(InvokeFunction) \ 114 V(IsConstructCallAndBranch) \ 115 V(IsObjectAndBranch) \ 116 V(IsStringAndBranch) \ 117 V(IsSmiAndBranch) \ 118 V(IsNumberAndBranch) \ 119 V(IsUndetectableAndBranch) \ 120 V(Label) \ 121 V(LazyBailout) \ 122 V(LoadContextSlot) \ 123 V(LoadExternalArrayPointer) \ 124 V(LoadFieldByIndex) \ 125 V(LoadFunctionPrototype) \ 126 V(LoadGlobalCell) \ 127 V(LoadGlobalGeneric) \ 128 V(LoadKeyed) \ 129 V(LoadKeyedGeneric) \ 130 V(LoadNamedField) \ 131 V(LoadNamedGeneric) \ 132 V(MapEnumLength) \ 133 V(MathAbs) \ 134 V(MathCos) \ 135 V(MathExp) \ 136 V(MathFloor) \ 137 V(MathFloorOfDiv) \ 138 V(MathLog) \ 139 V(MathMinMax) \ 140 V(MathPowHalf) \ 141 V(MathRound) \ 142 V(MathSin) \ 143 V(MathSqrt) \ 144 V(MathTan) \ 145 V(ModI) \ 146 V(MulI) \ 147 V(NumberTagD) \ 148 V(NumberTagI) \ 149 V(NumberTagU) \ 150 V(NumberUntagD) \ 151 V(OsrEntry) \ 152 V(OuterContext) \ 153 V(Parameter) \ 154 V(Power) \ 155 V(Random) \ 156 V(PushArgument) \ 157 V(RegExpLiteral) \ 158 V(Return) \ 159 V(SeqStringSetChar) \ 160 V(ShiftI) \ 161 V(SmiTag) \ 162 V(SmiUntag) \ 163 V(StackCheck) \ 164 V(StoreContextSlot) \ 165 V(StoreGlobalCell) \ 166 V(StoreGlobalGeneric) \ 167 V(StoreKeyed) \ 168 V(StoreKeyedGeneric) \ 169 V(StoreNamedField) \ 170 V(StoreNamedGeneric) \ 171 V(StringAdd) \ 172 V(StringCharCodeAt) \ 173 V(StringCharFromCode) \ 174 V(StringCompareAndBranch) \ 175 V(SubI) \ 176 V(TaggedToI) \ 177 V(TaggedToINoSSE2) \ 178 V(ThisFunction) \ 179 V(Throw) \ 180 V(ToFastProperties) \ 181 V(TransitionElementsKind) \ 182 V(TrapAllocationMemento) \ 183 V(Typeof) \ 184 V(TypeofIsAndBranch) \ 185 V(Uint32ToDouble) \ 186 V(UnknownOSRValue) \ 187 V(ValueOf) \ 188 V(WrapReceiver) 189 190 191 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \ 192 virtual Opcode opcode() const { return LInstruction::k##type; } \ 193 virtual void CompileToNative(LCodeGen* generator); \ 194 virtual const char* Mnemonic() const { return mnemonic; } \ 195 static L##type* cast(LInstruction* instr) { \ 196 ASSERT(instr->Is##type()); \ 197 return reinterpret_cast<L##type*>(instr); \ 198 } 199 200 201 #define DECLARE_HYDROGEN_ACCESSOR(type) \ 202 H##type* hydrogen() const { \ 203 return H##type::cast(hydrogen_value()); \ 204 } 205 206 207 class LInstruction: public ZoneObject { 208 public: 209 LInstruction() 210 : environment_(NULL), 211 hydrogen_value_(NULL), 212 bit_field_(IsCallBits::encode(false)) { 213 set_position(RelocInfo::kNoPosition); 214 } 215 216 virtual ~LInstruction() { } 217 218 virtual void CompileToNative(LCodeGen* generator) = 0; 219 virtual const char* Mnemonic() const = 0; 220 virtual void PrintTo(StringStream* stream); 221 virtual void PrintDataTo(StringStream* stream); 222 virtual void PrintOutputOperandTo(StringStream* stream); 223 224 enum Opcode { 225 // Declare a unique enum value for each instruction. 226 #define DECLARE_OPCODE(type) k##type, 227 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE) 228 kNumberOfInstructions 229 #undef DECLARE_OPCODE 230 }; 231 232 virtual Opcode opcode() const = 0; 233 234 // Declare non-virtual type testers for all leaf IR classes. 235 #define DECLARE_PREDICATE(type) \ 236 bool Is##type() const { return opcode() == k##type; } 237 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE) 238 #undef DECLARE_PREDICATE 239 240 // Declare virtual predicates for instructions that don't have 241 // an opcode. 242 virtual bool IsGap() const { return false; } 243 244 virtual bool IsControl() const { return false; } 245 246 void set_environment(LEnvironment* env) { environment_ = env; } 247 LEnvironment* environment() const { return environment_; } 248 bool HasEnvironment() const { return environment_ != NULL; } 249 250 void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); } 251 LPointerMap* pointer_map() const { return pointer_map_.get(); } 252 bool HasPointerMap() const { return pointer_map_.is_set(); } 253 254 // The 31 bits PositionBits is used to store the int position value. And the 255 // position value may be RelocInfo::kNoPosition (-1). The accessor always 256 // +1/-1 so that the encoded value of position in bit_field_ is always >= 0 257 // and can fit into the 31 bits PositionBits. 258 void set_position(int pos) { 259 bit_field_ = PositionBits::update(bit_field_, pos + 1); 260 } 261 int position() { return PositionBits::decode(bit_field_) - 1; } 262 263 void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; } 264 HValue* hydrogen_value() const { return hydrogen_value_; } 265 266 virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { } 267 268 void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); } 269 bool IsCall() const { return IsCallBits::decode(bit_field_); } 270 271 // Interface to the register allocator and iterators. 272 bool ClobbersTemps() const { return IsCall(); } 273 bool ClobbersRegisters() const { return IsCall(); } 274 virtual bool ClobbersDoubleRegisters() const { 275 return IsCall() || 276 (!CpuFeatures::IsSupported(SSE2) && 277 // We only have rudimentary X87Stack tracking, thus in general 278 // cannot handle deoptimization nor phi-nodes. 279 (HasEnvironment() || IsControl())); 280 } 281 282 virtual bool HasResult() const = 0; 283 virtual LOperand* result() const = 0; 284 285 bool HasDoubleRegisterResult(); 286 bool HasDoubleRegisterInput(); 287 bool IsDoubleInput(X87Register reg, LCodeGen* cgen); 288 289 LOperand* FirstInput() { return InputAt(0); } 290 LOperand* Output() { return HasResult() ? result() : NULL; } 291 292 virtual bool HasInterestingComment(LCodeGen* gen) const { return true; } 293 294 #ifdef DEBUG 295 void VerifyCall(); 296 #endif 297 298 private: 299 // Iterator support. 300 friend class InputIterator; 301 virtual int InputCount() = 0; 302 virtual LOperand* InputAt(int i) = 0; 303 304 friend class TempIterator; 305 virtual int TempCount() = 0; 306 virtual LOperand* TempAt(int i) = 0; 307 308 class IsCallBits: public BitField<bool, 0, 1> {}; 309 class PositionBits: public BitField<int, 1, 31> {}; 310 311 LEnvironment* environment_; 312 SetOncePointer<LPointerMap> pointer_map_; 313 HValue* hydrogen_value_; 314 int bit_field_; 315 }; 316 317 318 // R = number of result operands (0 or 1). 319 // I = number of input operands. 320 // T = number of temporary operands. 321 template<int R, int I, int T> 322 class LTemplateInstruction: public LInstruction { 323 public: 324 // Allow 0 or 1 output operands. 325 STATIC_ASSERT(R == 0 || R == 1); 326 virtual bool HasResult() const { return R != 0 && result() != NULL; } 327 void set_result(LOperand* operand) { results_[0] = operand; } 328 LOperand* result() const { return results_[0]; } 329 330 protected: 331 EmbeddedContainer<LOperand*, R> results_; 332 EmbeddedContainer<LOperand*, I> inputs_; 333 EmbeddedContainer<LOperand*, T> temps_; 334 335 private: 336 // Iterator support. 337 virtual int InputCount() { return I; } 338 virtual LOperand* InputAt(int i) { return inputs_[i]; } 339 340 virtual int TempCount() { return T; } 341 virtual LOperand* TempAt(int i) { return temps_[i]; } 342 }; 343 344 345 class LGap: public LTemplateInstruction<0, 0, 0> { 346 public: 347 explicit LGap(HBasicBlock* block) : block_(block) { 348 parallel_moves_[BEFORE] = NULL; 349 parallel_moves_[START] = NULL; 350 parallel_moves_[END] = NULL; 351 parallel_moves_[AFTER] = NULL; 352 } 353 354 // Can't use the DECLARE-macro here because of sub-classes. 355 virtual bool IsGap() const { return true; } 356 virtual void PrintDataTo(StringStream* stream); 357 static LGap* cast(LInstruction* instr) { 358 ASSERT(instr->IsGap()); 359 return reinterpret_cast<LGap*>(instr); 360 } 361 362 bool IsRedundant() const; 363 364 HBasicBlock* block() const { return block_; } 365 366 enum InnerPosition { 367 BEFORE, 368 START, 369 END, 370 AFTER, 371 FIRST_INNER_POSITION = BEFORE, 372 LAST_INNER_POSITION = AFTER 373 }; 374 375 LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) { 376 if (parallel_moves_[pos] == NULL) { 377 parallel_moves_[pos] = new(zone) LParallelMove(zone); 378 } 379 return parallel_moves_[pos]; 380 } 381 382 LParallelMove* GetParallelMove(InnerPosition pos) { 383 return parallel_moves_[pos]; 384 } 385 386 private: 387 LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1]; 388 HBasicBlock* block_; 389 }; 390 391 392 class LInstructionGap: public LGap { 393 public: 394 explicit LInstructionGap(HBasicBlock* block) : LGap(block) { } 395 396 virtual bool HasInterestingComment(LCodeGen* gen) const { 397 return !IsRedundant(); 398 } 399 400 DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap") 401 }; 402 403 404 class LGoto: public LTemplateInstruction<0, 0, 0> { 405 public: 406 explicit LGoto(int block_id) : block_id_(block_id) { } 407 408 virtual bool HasInterestingComment(LCodeGen* gen) const; 409 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto") 410 virtual void PrintDataTo(StringStream* stream); 411 virtual bool IsControl() const { return true; } 412 413 int block_id() const { return block_id_; } 414 415 private: 416 int block_id_; 417 }; 418 419 420 class LLazyBailout: public LTemplateInstruction<0, 0, 0> { 421 public: 422 DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout") 423 }; 424 425 426 class LDummyUse: public LTemplateInstruction<1, 1, 0> { 427 public: 428 explicit LDummyUse(LOperand* value) { 429 inputs_[0] = value; 430 } 431 DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use") 432 }; 433 434 435 class LDeoptimize: public LTemplateInstruction<0, 0, 0> { 436 public: 437 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize") 438 DECLARE_HYDROGEN_ACCESSOR(Deoptimize) 439 }; 440 441 442 class LLabel: public LGap { 443 public: 444 explicit LLabel(HBasicBlock* block) 445 : LGap(block), replacement_(NULL) { } 446 447 virtual bool HasInterestingComment(LCodeGen* gen) const { return false; } 448 DECLARE_CONCRETE_INSTRUCTION(Label, "label") 449 450 virtual void PrintDataTo(StringStream* stream); 451 452 int block_id() const { return block()->block_id(); } 453 bool is_loop_header() const { return block()->IsLoopHeader(); } 454 bool is_osr_entry() const { return block()->is_osr_entry(); } 455 Label* label() { return &label_; } 456 LLabel* replacement() const { return replacement_; } 457 void set_replacement(LLabel* label) { replacement_ = label; } 458 bool HasReplacement() const { return replacement_ != NULL; } 459 460 private: 461 Label label_; 462 LLabel* replacement_; 463 }; 464 465 466 class LParameter: public LTemplateInstruction<1, 0, 0> { 467 public: 468 virtual bool HasInterestingComment(LCodeGen* gen) const { return false; } 469 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter") 470 }; 471 472 473 class LCallStub: public LTemplateInstruction<1, 1, 0> { 474 public: 475 explicit LCallStub(LOperand* context) { 476 inputs_[0] = context; 477 } 478 479 LOperand* context() { return inputs_[0]; } 480 481 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub") 482 DECLARE_HYDROGEN_ACCESSOR(CallStub) 483 484 TranscendentalCache::Type transcendental_type() { 485 return hydrogen()->transcendental_type(); 486 } 487 }; 488 489 490 class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> { 491 public: 492 virtual bool HasInterestingComment(LCodeGen* gen) const { return false; } 493 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value") 494 }; 495 496 497 template<int I, int T> 498 class LControlInstruction: public LTemplateInstruction<0, I, T> { 499 public: 500 LControlInstruction() : false_label_(NULL), true_label_(NULL) { } 501 502 virtual bool IsControl() const { return true; } 503 504 int SuccessorCount() { return hydrogen()->SuccessorCount(); } 505 HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); } 506 507 int TrueDestination(LChunk* chunk) { 508 return chunk->LookupDestination(true_block_id()); 509 } 510 int FalseDestination(LChunk* chunk) { 511 return chunk->LookupDestination(false_block_id()); 512 } 513 514 Label* TrueLabel(LChunk* chunk) { 515 if (true_label_ == NULL) { 516 true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk)); 517 } 518 return true_label_; 519 } 520 Label* FalseLabel(LChunk* chunk) { 521 if (false_label_ == NULL) { 522 false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk)); 523 } 524 return false_label_; 525 } 526 527 protected: 528 int true_block_id() { return SuccessorAt(0)->block_id(); } 529 int false_block_id() { return SuccessorAt(1)->block_id(); } 530 531 private: 532 HControlInstruction* hydrogen() { 533 return HControlInstruction::cast(this->hydrogen_value()); 534 } 535 536 Label* false_label_; 537 Label* true_label_; 538 }; 539 540 541 class LWrapReceiver: public LTemplateInstruction<1, 2, 1> { 542 public: 543 LWrapReceiver(LOperand* receiver, 544 LOperand* function, 545 LOperand* temp) { 546 inputs_[0] = receiver; 547 inputs_[1] = function; 548 temps_[0] = temp; 549 } 550 551 LOperand* receiver() { return inputs_[0]; } 552 LOperand* function() { return inputs_[1]; } 553 LOperand* temp() { return temps_[0]; } 554 555 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver") 556 }; 557 558 559 class LApplyArguments: public LTemplateInstruction<1, 4, 0> { 560 public: 561 LApplyArguments(LOperand* function, 562 LOperand* receiver, 563 LOperand* length, 564 LOperand* elements) { 565 inputs_[0] = function; 566 inputs_[1] = receiver; 567 inputs_[2] = length; 568 inputs_[3] = elements; 569 } 570 571 LOperand* function() { return inputs_[0]; } 572 LOperand* receiver() { return inputs_[1]; } 573 LOperand* length() { return inputs_[2]; } 574 LOperand* elements() { return inputs_[3]; } 575 576 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments") 577 }; 578 579 580 class LAccessArgumentsAt: public LTemplateInstruction<1, 3, 0> { 581 public: 582 LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index) { 583 inputs_[0] = arguments; 584 inputs_[1] = length; 585 inputs_[2] = index; 586 } 587 588 LOperand* arguments() { return inputs_[0]; } 589 LOperand* length() { return inputs_[1]; } 590 LOperand* index() { return inputs_[2]; } 591 592 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at") 593 594 virtual void PrintDataTo(StringStream* stream); 595 }; 596 597 598 class LArgumentsLength: public LTemplateInstruction<1, 1, 0> { 599 public: 600 explicit LArgumentsLength(LOperand* elements) { 601 inputs_[0] = elements; 602 } 603 604 LOperand* elements() { return inputs_[0]; } 605 606 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length") 607 }; 608 609 610 class LArgumentsElements: public LTemplateInstruction<1, 0, 0> { 611 public: 612 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements") 613 DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements) 614 }; 615 616 617 class LDebugBreak: public LTemplateInstruction<0, 0, 0> { 618 public: 619 DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break") 620 }; 621 622 623 class LModI: public LTemplateInstruction<1, 2, 1> { 624 public: 625 LModI(LOperand* left, LOperand* right, LOperand* temp) { 626 inputs_[0] = left; 627 inputs_[1] = right; 628 temps_[0] = temp; 629 } 630 631 LOperand* left() { return inputs_[0]; } 632 LOperand* right() { return inputs_[1]; } 633 LOperand* temp() { return temps_[0]; } 634 635 DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i") 636 DECLARE_HYDROGEN_ACCESSOR(Mod) 637 }; 638 639 640 class LDivI: public LTemplateInstruction<1, 2, 1> { 641 public: 642 LDivI(LOperand* left, LOperand* right, LOperand* temp) { 643 inputs_[0] = left; 644 inputs_[1] = right; 645 temps_[0] = temp; 646 } 647 648 LOperand* left() { return inputs_[0]; } 649 LOperand* right() { return inputs_[1]; } 650 651 bool is_flooring() { return hydrogen_value()->IsMathFloorOfDiv(); } 652 653 DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i") 654 DECLARE_HYDROGEN_ACCESSOR(Div) 655 }; 656 657 658 class LMathFloorOfDiv: public LTemplateInstruction<1, 2, 1> { 659 public: 660 LMathFloorOfDiv(LOperand* left, 661 LOperand* right, 662 LOperand* temp = NULL) { 663 inputs_[0] = left; 664 inputs_[1] = right; 665 temps_[0] = temp; 666 } 667 668 LOperand* left() { return inputs_[0]; } 669 LOperand* right() { return inputs_[1]; } 670 LOperand* temp() { return temps_[0]; } 671 672 DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv, "math-floor-of-div") 673 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv) 674 }; 675 676 677 class LMulI: public LTemplateInstruction<1, 2, 1> { 678 public: 679 LMulI(LOperand* left, LOperand* right, LOperand* temp) { 680 inputs_[0] = left; 681 inputs_[1] = right; 682 temps_[0] = temp; 683 } 684 685 LOperand* left() { return inputs_[0]; } 686 LOperand* right() { return inputs_[1]; } 687 LOperand* temp() { return temps_[0]; } 688 689 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i") 690 DECLARE_HYDROGEN_ACCESSOR(Mul) 691 }; 692 693 694 class LCompareNumericAndBranch: public LControlInstruction<2, 0> { 695 public: 696 LCompareNumericAndBranch(LOperand* left, LOperand* right) { 697 inputs_[0] = left; 698 inputs_[1] = right; 699 } 700 701 LOperand* left() { return inputs_[0]; } 702 LOperand* right() { return inputs_[1]; } 703 704 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch, 705 "compare-numeric-and-branch") 706 DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch) 707 708 Token::Value op() const { return hydrogen()->token(); } 709 bool is_double() const { 710 return hydrogen()->representation().IsDouble(); 711 } 712 713 virtual void PrintDataTo(StringStream* stream); 714 }; 715 716 717 class LMathFloor: public LTemplateInstruction<1, 1, 0> { 718 public: 719 explicit LMathFloor(LOperand* value) { 720 inputs_[0] = value; 721 } 722 723 LOperand* value() { return inputs_[0]; } 724 725 DECLARE_CONCRETE_INSTRUCTION(MathFloor, "math-floor") 726 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation) 727 }; 728 729 730 class LMathRound: public LTemplateInstruction<1, 2, 1> { 731 public: 732 LMathRound(LOperand* context, LOperand* value, LOperand* temp) { 733 inputs_[1] = context; 734 inputs_[0] = value; 735 temps_[0] = temp; 736 } 737 738 LOperand* context() { return inputs_[1]; } 739 LOperand* value() { return inputs_[0]; } 740 LOperand* temp() { return temps_[0]; } 741 742 DECLARE_CONCRETE_INSTRUCTION(MathRound, "math-round") 743 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation) 744 }; 745 746 747 class LMathAbs: public LTemplateInstruction<1, 2, 0> { 748 public: 749 LMathAbs(LOperand* context, LOperand* value) { 750 inputs_[1] = context; 751 inputs_[0] = value; 752 } 753 754 LOperand* context() { return inputs_[1]; } 755 LOperand* value() { return inputs_[0]; } 756 757 DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs") 758 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation) 759 }; 760 761 762 class LMathLog: public LTemplateInstruction<1, 1, 0> { 763 public: 764 explicit LMathLog(LOperand* value) { 765 inputs_[0] = value; 766 } 767 768 LOperand* value() { return inputs_[0]; } 769 770 DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log") 771 }; 772 773 774 class LMathSin: public LTemplateInstruction<1, 1, 0> { 775 public: 776 explicit LMathSin(LOperand* value) { 777 inputs_[0] = value; 778 } 779 780 LOperand* value() { return inputs_[0]; } 781 782 DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin") 783 }; 784 785 786 class LMathCos: public LTemplateInstruction<1, 1, 0> { 787 public: 788 explicit LMathCos(LOperand* value) { 789 inputs_[0] = value; 790 } 791 792 LOperand* value() { return inputs_[0]; } 793 794 DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos") 795 }; 796 797 798 class LMathTan: public LTemplateInstruction<1, 1, 0> { 799 public: 800 explicit LMathTan(LOperand* value) { 801 inputs_[0] = value; 802 } 803 804 LOperand* value() { return inputs_[0]; } 805 806 DECLARE_CONCRETE_INSTRUCTION(MathTan, "math-tan") 807 }; 808 809 810 class LMathExp: public LTemplateInstruction<1, 1, 2> { 811 public: 812 LMathExp(LOperand* value, 813 LOperand* temp1, 814 LOperand* temp2) { 815 inputs_[0] = value; 816 temps_[0] = temp1; 817 temps_[1] = temp2; 818 ExternalReference::InitializeMathExpData(); 819 } 820 821 LOperand* value() { return inputs_[0]; } 822 LOperand* temp1() { return temps_[0]; } 823 LOperand* temp2() { return temps_[1]; } 824 825 DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp") 826 }; 827 828 829 class LMathSqrt: public LTemplateInstruction<1, 1, 0> { 830 public: 831 explicit LMathSqrt(LOperand* value) { 832 inputs_[0] = value; 833 } 834 835 LOperand* value() { return inputs_[0]; } 836 837 DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt") 838 }; 839 840 841 class LMathPowHalf: public LTemplateInstruction<1, 2, 1> { 842 public: 843 LMathPowHalf(LOperand* context, LOperand* value, LOperand* temp) { 844 inputs_[1] = context; 845 inputs_[0] = value; 846 temps_[0] = temp; 847 } 848 849 LOperand* context() { return inputs_[1]; } 850 LOperand* value() { return inputs_[0]; } 851 LOperand* temp() { return temps_[0]; } 852 853 DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half") 854 }; 855 856 857 class LCmpObjectEqAndBranch: public LControlInstruction<2, 0> { 858 public: 859 LCmpObjectEqAndBranch(LOperand* left, LOperand* right) { 860 inputs_[0] = left; 861 inputs_[1] = right; 862 } 863 864 LOperand* left() { return inputs_[0]; } 865 LOperand* right() { return inputs_[1]; } 866 867 DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch") 868 }; 869 870 871 class LCmpHoleAndBranch: public LControlInstruction<1, 0> { 872 public: 873 explicit LCmpHoleAndBranch(LOperand* object) { 874 inputs_[0] = object; 875 } 876 877 LOperand* object() { return inputs_[0]; } 878 879 DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranch, "cmp-hole-and-branch") 880 DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch) 881 }; 882 883 884 class LIsObjectAndBranch: public LControlInstruction<1, 1> { 885 public: 886 LIsObjectAndBranch(LOperand* value, LOperand* temp) { 887 inputs_[0] = value; 888 temps_[0] = temp; 889 } 890 891 LOperand* value() { return inputs_[0]; } 892 LOperand* temp() { return temps_[0]; } 893 894 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch") 895 896 virtual void PrintDataTo(StringStream* stream); 897 }; 898 899 900 class LIsNumberAndBranch: public LControlInstruction<1, 0> { 901 public: 902 explicit LIsNumberAndBranch(LOperand* value) { 903 inputs_[0] = value; 904 } 905 906 LOperand* value() { return inputs_[0]; } 907 908 DECLARE_CONCRETE_INSTRUCTION(IsNumberAndBranch, "is-number-and-branch") 909 DECLARE_HYDROGEN_ACCESSOR(IsNumberAndBranch) 910 }; 911 912 913 class LIsStringAndBranch: public LControlInstruction<1, 1> { 914 public: 915 LIsStringAndBranch(LOperand* value, LOperand* temp) { 916 inputs_[0] = value; 917 temps_[0] = temp; 918 } 919 920 LOperand* value() { return inputs_[0]; } 921 LOperand* temp() { return temps_[0]; } 922 923 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch") 924 DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch) 925 926 virtual void PrintDataTo(StringStream* stream); 927 }; 928 929 930 class LIsSmiAndBranch: public LControlInstruction<1, 0> { 931 public: 932 explicit LIsSmiAndBranch(LOperand* value) { 933 inputs_[0] = value; 934 } 935 936 LOperand* value() { return inputs_[0]; } 937 938 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch") 939 DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch) 940 941 virtual void PrintDataTo(StringStream* stream); 942 }; 943 944 945 class LIsUndetectableAndBranch: public LControlInstruction<1, 1> { 946 public: 947 LIsUndetectableAndBranch(LOperand* value, LOperand* temp) { 948 inputs_[0] = value; 949 temps_[0] = temp; 950 } 951 952 LOperand* value() { return inputs_[0]; } 953 LOperand* temp() { return temps_[0]; } 954 955 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch, 956 "is-undetectable-and-branch") 957 DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch) 958 959 virtual void PrintDataTo(StringStream* stream); 960 }; 961 962 963 class LStringCompareAndBranch: public LControlInstruction<3, 0> { 964 public: 965 LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) { 966 inputs_[0] = context; 967 inputs_[1] = left; 968 inputs_[2] = right; 969 } 970 971 LOperand* left() { return inputs_[1]; } 972 LOperand* right() { return inputs_[2]; } 973 974 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch, 975 "string-compare-and-branch") 976 DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch) 977 978 virtual void PrintDataTo(StringStream* stream); 979 980 Token::Value op() const { return hydrogen()->token(); } 981 }; 982 983 984 class LHasInstanceTypeAndBranch: public LControlInstruction<1, 1> { 985 public: 986 LHasInstanceTypeAndBranch(LOperand* value, LOperand* temp) { 987 inputs_[0] = value; 988 temps_[0] = temp; 989 } 990 991 LOperand* value() { return inputs_[0]; } 992 LOperand* temp() { return temps_[0]; } 993 994 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch, 995 "has-instance-type-and-branch") 996 DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch) 997 998 virtual void PrintDataTo(StringStream* stream); 999 }; 1000 1001 1002 class LGetCachedArrayIndex: public LTemplateInstruction<1, 1, 0> { 1003 public: 1004 explicit LGetCachedArrayIndex(LOperand* value) { 1005 inputs_[0] = value; 1006 } 1007 1008 LOperand* value() { return inputs_[0]; } 1009 1010 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index") 1011 DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex) 1012 }; 1013 1014 1015 class LHasCachedArrayIndexAndBranch: public LControlInstruction<1, 0> { 1016 public: 1017 explicit LHasCachedArrayIndexAndBranch(LOperand* value) { 1018 inputs_[0] = value; 1019 } 1020 1021 LOperand* value() { return inputs_[0]; } 1022 1023 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch, 1024 "has-cached-array-index-and-branch") 1025 1026 virtual void PrintDataTo(StringStream* stream); 1027 }; 1028 1029 1030 class LIsConstructCallAndBranch: public LControlInstruction<0, 1> { 1031 public: 1032 explicit LIsConstructCallAndBranch(LOperand* temp) { 1033 temps_[0] = temp; 1034 } 1035 1036 LOperand* temp() { return temps_[0]; } 1037 1038 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch, 1039 "is-construct-call-and-branch") 1040 }; 1041 1042 1043 class LClassOfTestAndBranch: public LControlInstruction<1, 2> { 1044 public: 1045 LClassOfTestAndBranch(LOperand* value, LOperand* temp, LOperand* temp2) { 1046 inputs_[0] = value; 1047 temps_[0] = temp; 1048 temps_[1] = temp2; 1049 } 1050 1051 LOperand* value() { return inputs_[0]; } 1052 LOperand* temp() { return temps_[0]; } 1053 LOperand* temp2() { return temps_[1]; } 1054 1055 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch, 1056 "class-of-test-and-branch") 1057 DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch) 1058 1059 virtual void PrintDataTo(StringStream* stream); 1060 }; 1061 1062 1063 class LCmpT: public LTemplateInstruction<1, 3, 0> { 1064 public: 1065 LCmpT(LOperand* context, LOperand* left, LOperand* right) { 1066 inputs_[0] = context; 1067 inputs_[1] = left; 1068 inputs_[2] = right; 1069 } 1070 1071 DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t") 1072 DECLARE_HYDROGEN_ACCESSOR(CompareGeneric) 1073 1074 Token::Value op() const { return hydrogen()->token(); } 1075 }; 1076 1077 1078 class LInstanceOf: public LTemplateInstruction<1, 3, 0> { 1079 public: 1080 LInstanceOf(LOperand* context, LOperand* left, LOperand* right) { 1081 inputs_[0] = context; 1082 inputs_[1] = left; 1083 inputs_[2] = right; 1084 } 1085 1086 LOperand* context() { return inputs_[0]; } 1087 1088 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of") 1089 }; 1090 1091 1092 class LInstanceOfKnownGlobal: public LTemplateInstruction<1, 2, 1> { 1093 public: 1094 LInstanceOfKnownGlobal(LOperand* context, LOperand* value, LOperand* temp) { 1095 inputs_[0] = context; 1096 inputs_[1] = value; 1097 temps_[0] = temp; 1098 } 1099 1100 LOperand* value() { return inputs_[1]; } 1101 LOperand* temp() { return temps_[0]; } 1102 1103 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal, 1104 "instance-of-known-global") 1105 DECLARE_HYDROGEN_ACCESSOR(InstanceOfKnownGlobal) 1106 1107 Handle<JSFunction> function() const { return hydrogen()->function(); } 1108 LEnvironment* GetDeferredLazyDeoptimizationEnvironment() { 1109 return lazy_deopt_env_; 1110 } 1111 virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { 1112 lazy_deopt_env_ = env; 1113 } 1114 1115 private: 1116 LEnvironment* lazy_deopt_env_; 1117 }; 1118 1119 1120 class LInstanceSize: public LTemplateInstruction<1, 1, 0> { 1121 public: 1122 explicit LInstanceSize(LOperand* object) { 1123 inputs_[0] = object; 1124 } 1125 1126 LOperand* object() { return inputs_[0]; } 1127 1128 DECLARE_CONCRETE_INSTRUCTION(InstanceSize, "instance-size") 1129 DECLARE_HYDROGEN_ACCESSOR(InstanceSize) 1130 }; 1131 1132 1133 class LBoundsCheck: public LTemplateInstruction<0, 2, 0> { 1134 public: 1135 LBoundsCheck(LOperand* index, LOperand* length) { 1136 inputs_[0] = index; 1137 inputs_[1] = length; 1138 } 1139 1140 LOperand* index() { return inputs_[0]; } 1141 LOperand* length() { return inputs_[1]; } 1142 1143 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check") 1144 DECLARE_HYDROGEN_ACCESSOR(BoundsCheck) 1145 }; 1146 1147 1148 class LBitI: public LTemplateInstruction<1, 2, 0> { 1149 public: 1150 LBitI(LOperand* left, LOperand* right) { 1151 inputs_[0] = left; 1152 inputs_[1] = right; 1153 } 1154 1155 LOperand* left() { return inputs_[0]; } 1156 LOperand* right() { return inputs_[1]; } 1157 1158 DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i") 1159 DECLARE_HYDROGEN_ACCESSOR(Bitwise) 1160 1161 Token::Value op() const { return hydrogen()->op(); } 1162 }; 1163 1164 1165 class LShiftI: public LTemplateInstruction<1, 2, 0> { 1166 public: 1167 LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt) 1168 : op_(op), can_deopt_(can_deopt) { 1169 inputs_[0] = left; 1170 inputs_[1] = right; 1171 } 1172 1173 LOperand* left() { return inputs_[0]; } 1174 LOperand* right() { return inputs_[1]; } 1175 1176 DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i") 1177 1178 Token::Value op() const { return op_; } 1179 bool can_deopt() const { return can_deopt_; } 1180 1181 private: 1182 Token::Value op_; 1183 bool can_deopt_; 1184 }; 1185 1186 1187 class LSubI: public LTemplateInstruction<1, 2, 0> { 1188 public: 1189 LSubI(LOperand* left, LOperand* right) { 1190 inputs_[0] = left; 1191 inputs_[1] = right; 1192 } 1193 1194 LOperand* left() { return inputs_[0]; } 1195 LOperand* right() { return inputs_[1]; } 1196 1197 DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i") 1198 DECLARE_HYDROGEN_ACCESSOR(Sub) 1199 }; 1200 1201 1202 class LConstantI: public LTemplateInstruction<1, 0, 0> { 1203 public: 1204 DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i") 1205 DECLARE_HYDROGEN_ACCESSOR(Constant) 1206 1207 int32_t value() const { return hydrogen()->Integer32Value(); } 1208 }; 1209 1210 1211 class LConstantS: public LTemplateInstruction<1, 0, 0> { 1212 public: 1213 DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s") 1214 DECLARE_HYDROGEN_ACCESSOR(Constant) 1215 1216 Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); } 1217 }; 1218 1219 1220 class LConstantD: public LTemplateInstruction<1, 0, 1> { 1221 public: 1222 explicit LConstantD(LOperand* temp) { 1223 temps_[0] = temp; 1224 } 1225 1226 LOperand* temp() { return temps_[0]; } 1227 1228 DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d") 1229 DECLARE_HYDROGEN_ACCESSOR(Constant) 1230 1231 double value() const { return hydrogen()->DoubleValue(); } 1232 }; 1233 1234 1235 class LConstantE: public LTemplateInstruction<1, 0, 0> { 1236 public: 1237 DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e") 1238 DECLARE_HYDROGEN_ACCESSOR(Constant) 1239 1240 ExternalReference value() const { 1241 return hydrogen()->ExternalReferenceValue(); 1242 } 1243 }; 1244 1245 1246 class LConstantT: public LTemplateInstruction<1, 0, 0> { 1247 public: 1248 DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t") 1249 DECLARE_HYDROGEN_ACCESSOR(Constant) 1250 1251 Handle<Object> value() const { return hydrogen()->handle(); } 1252 }; 1253 1254 1255 class LBranch: public LControlInstruction<1, 1> { 1256 public: 1257 LBranch(LOperand* value, LOperand* temp) { 1258 inputs_[0] = value; 1259 temps_[0] = temp; 1260 } 1261 1262 LOperand* value() { return inputs_[0]; } 1263 LOperand* temp() { return temps_[0]; } 1264 1265 DECLARE_CONCRETE_INSTRUCTION(Branch, "branch") 1266 DECLARE_HYDROGEN_ACCESSOR(Branch) 1267 1268 virtual void PrintDataTo(StringStream* stream); 1269 }; 1270 1271 1272 class LCmpMapAndBranch: public LControlInstruction<1, 0> { 1273 public: 1274 explicit LCmpMapAndBranch(LOperand* value) { 1275 inputs_[0] = value; 1276 } 1277 1278 LOperand* value() { return inputs_[0]; } 1279 1280 DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch") 1281 DECLARE_HYDROGEN_ACCESSOR(CompareMap) 1282 1283 Handle<Map> map() const { return hydrogen()->map(); } 1284 }; 1285 1286 1287 class LMapEnumLength: public LTemplateInstruction<1, 1, 0> { 1288 public: 1289 explicit LMapEnumLength(LOperand* value) { 1290 inputs_[0] = value; 1291 } 1292 1293 LOperand* value() { return inputs_[0]; } 1294 1295 DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length") 1296 }; 1297 1298 1299 class LElementsKind: public LTemplateInstruction<1, 1, 0> { 1300 public: 1301 explicit LElementsKind(LOperand* value) { 1302 inputs_[0] = value; 1303 } 1304 1305 LOperand* value() { return inputs_[0]; } 1306 1307 DECLARE_CONCRETE_INSTRUCTION(ElementsKind, "elements-kind") 1308 DECLARE_HYDROGEN_ACCESSOR(ElementsKind) 1309 }; 1310 1311 1312 class LValueOf: public LTemplateInstruction<1, 1, 1> { 1313 public: 1314 LValueOf(LOperand* value, LOperand* temp) { 1315 inputs_[0] = value; 1316 temps_[0] = temp; 1317 } 1318 1319 LOperand* value() { return inputs_[0]; } 1320 LOperand* temp() { return temps_[0]; } 1321 1322 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value-of") 1323 DECLARE_HYDROGEN_ACCESSOR(ValueOf) 1324 }; 1325 1326 1327 class LDateField: public LTemplateInstruction<1, 1, 1> { 1328 public: 1329 LDateField(LOperand* date, LOperand* temp, Smi* index) 1330 : index_(index) { 1331 inputs_[0] = date; 1332 temps_[0] = temp; 1333 } 1334 1335 LOperand* date() { return inputs_[0]; } 1336 LOperand* temp() { return temps_[0]; } 1337 1338 DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field") 1339 DECLARE_HYDROGEN_ACCESSOR(DateField) 1340 1341 Smi* index() const { return index_; } 1342 1343 private: 1344 Smi* index_; 1345 }; 1346 1347 1348 class LSeqStringSetChar: public LTemplateInstruction<1, 3, 0> { 1349 public: 1350 LSeqStringSetChar(String::Encoding encoding, 1351 LOperand* string, 1352 LOperand* index, 1353 LOperand* value) : encoding_(encoding) { 1354 inputs_[0] = string; 1355 inputs_[1] = index; 1356 inputs_[2] = value; 1357 } 1358 1359 String::Encoding encoding() { return encoding_; } 1360 LOperand* string() { return inputs_[0]; } 1361 LOperand* index() { return inputs_[1]; } 1362 LOperand* value() { return inputs_[2]; } 1363 1364 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char") 1365 DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar) 1366 1367 private: 1368 String::Encoding encoding_; 1369 }; 1370 1371 1372 class LThrow: public LTemplateInstruction<0, 2, 0> { 1373 public: 1374 LThrow(LOperand* context, LOperand* value) { 1375 inputs_[0] = context; 1376 inputs_[1] = value; 1377 } 1378 1379 LOperand* context() { return inputs_[0]; } 1380 LOperand* value() { return inputs_[1]; } 1381 1382 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw") 1383 }; 1384 1385 1386 class LAddI: public LTemplateInstruction<1, 2, 0> { 1387 public: 1388 LAddI(LOperand* left, LOperand* right) { 1389 inputs_[0] = left; 1390 inputs_[1] = right; 1391 } 1392 1393 LOperand* left() { return inputs_[0]; } 1394 LOperand* right() { return inputs_[1]; } 1395 1396 static bool UseLea(HAdd* add) { 1397 return !add->CheckFlag(HValue::kCanOverflow) && 1398 add->BetterLeftOperand()->UseCount() > 1; 1399 } 1400 1401 DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i") 1402 DECLARE_HYDROGEN_ACCESSOR(Add) 1403 }; 1404 1405 1406 class LMathMinMax: public LTemplateInstruction<1, 2, 0> { 1407 public: 1408 LMathMinMax(LOperand* left, LOperand* right) { 1409 inputs_[0] = left; 1410 inputs_[1] = right; 1411 } 1412 1413 LOperand* left() { return inputs_[0]; } 1414 LOperand* right() { return inputs_[1]; } 1415 1416 DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max") 1417 DECLARE_HYDROGEN_ACCESSOR(MathMinMax) 1418 }; 1419 1420 1421 class LPower: public LTemplateInstruction<1, 2, 0> { 1422 public: 1423 LPower(LOperand* left, LOperand* right) { 1424 inputs_[0] = left; 1425 inputs_[1] = right; 1426 } 1427 1428 LOperand* left() { return inputs_[0]; } 1429 LOperand* right() { return inputs_[1]; } 1430 1431 DECLARE_CONCRETE_INSTRUCTION(Power, "power") 1432 DECLARE_HYDROGEN_ACCESSOR(Power) 1433 }; 1434 1435 1436 class LRandom: public LTemplateInstruction<1, 1, 0> { 1437 public: 1438 explicit LRandom(LOperand* global_object) { 1439 inputs_[0] = global_object; 1440 } 1441 1442 LOperand* global_object() { return inputs_[0]; } 1443 1444 DECLARE_CONCRETE_INSTRUCTION(Random, "random") 1445 DECLARE_HYDROGEN_ACCESSOR(Random) 1446 }; 1447 1448 1449 class LArithmeticD: public LTemplateInstruction<1, 2, 0> { 1450 public: 1451 LArithmeticD(Token::Value op, LOperand* left, LOperand* right) 1452 : op_(op) { 1453 inputs_[0] = left; 1454 inputs_[1] = right; 1455 } 1456 1457 LOperand* left() { return inputs_[0]; } 1458 LOperand* right() { return inputs_[1]; } 1459 1460 Token::Value op() const { return op_; } 1461 1462 virtual Opcode opcode() const { return LInstruction::kArithmeticD; } 1463 virtual void CompileToNative(LCodeGen* generator); 1464 virtual const char* Mnemonic() const; 1465 1466 private: 1467 Token::Value op_; 1468 }; 1469 1470 1471 class LArithmeticT: public LTemplateInstruction<1, 3, 0> { 1472 public: 1473 LArithmeticT(Token::Value op, 1474 LOperand* context, 1475 LOperand* left, 1476 LOperand* right) 1477 : op_(op) { 1478 inputs_[0] = context; 1479 inputs_[1] = left; 1480 inputs_[2] = right; 1481 } 1482 1483 LOperand* context() { return inputs_[0]; } 1484 LOperand* left() { return inputs_[1]; } 1485 LOperand* right() { return inputs_[2]; } 1486 1487 virtual Opcode opcode() const { return LInstruction::kArithmeticT; } 1488 virtual void CompileToNative(LCodeGen* generator); 1489 virtual const char* Mnemonic() const; 1490 1491 Token::Value op() const { return op_; } 1492 1493 private: 1494 Token::Value op_; 1495 }; 1496 1497 1498 class LReturn: public LTemplateInstruction<0, 3, 0> { 1499 public: 1500 explicit LReturn(LOperand* value, LOperand* context, 1501 LOperand* parameter_count) { 1502 inputs_[0] = value; 1503 inputs_[1] = context; 1504 inputs_[2] = parameter_count; 1505 } 1506 1507 bool has_constant_parameter_count() { 1508 return parameter_count()->IsConstantOperand(); 1509 } 1510 LConstantOperand* constant_parameter_count() { 1511 ASSERT(has_constant_parameter_count()); 1512 return LConstantOperand::cast(parameter_count()); 1513 } 1514 LOperand* parameter_count() { return inputs_[2]; } 1515 1516 DECLARE_CONCRETE_INSTRUCTION(Return, "return") 1517 DECLARE_HYDROGEN_ACCESSOR(Return) 1518 }; 1519 1520 1521 class LLoadNamedField: public LTemplateInstruction<1, 1, 0> { 1522 public: 1523 explicit LLoadNamedField(LOperand* object) { 1524 inputs_[0] = object; 1525 } 1526 1527 virtual bool ClobbersDoubleRegisters() const { 1528 return !CpuFeatures::IsSupported(SSE2) && 1529 !hydrogen()->representation().IsDouble(); 1530 } 1531 1532 LOperand* object() { return inputs_[0]; } 1533 1534 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field") 1535 DECLARE_HYDROGEN_ACCESSOR(LoadNamedField) 1536 }; 1537 1538 1539 class LLoadNamedGeneric: public LTemplateInstruction<1, 2, 0> { 1540 public: 1541 LLoadNamedGeneric(LOperand* context, LOperand* object) { 1542 inputs_[0] = context; 1543 inputs_[1] = object; 1544 } 1545 1546 LOperand* context() { return inputs_[0]; } 1547 LOperand* object() { return inputs_[1]; } 1548 1549 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic") 1550 DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric) 1551 1552 Handle<Object> name() const { return hydrogen()->name(); } 1553 }; 1554 1555 1556 class LLoadFunctionPrototype: public LTemplateInstruction<1, 1, 1> { 1557 public: 1558 LLoadFunctionPrototype(LOperand* function, LOperand* temp) { 1559 inputs_[0] = function; 1560 temps_[0] = temp; 1561 } 1562 1563 LOperand* function() { return inputs_[0]; } 1564 LOperand* temp() { return temps_[0]; } 1565 1566 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype") 1567 DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype) 1568 }; 1569 1570 1571 class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> { 1572 public: 1573 explicit LLoadExternalArrayPointer(LOperand* object) { 1574 inputs_[0] = object; 1575 } 1576 1577 LOperand* object() { return inputs_[0]; } 1578 1579 DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer, 1580 "load-external-array-pointer") 1581 }; 1582 1583 1584 class LLoadKeyed: public LTemplateInstruction<1, 2, 0> { 1585 public: 1586 LLoadKeyed(LOperand* elements, LOperand* key) { 1587 inputs_[0] = elements; 1588 inputs_[1] = key; 1589 } 1590 LOperand* elements() { return inputs_[0]; } 1591 LOperand* key() { return inputs_[1]; } 1592 ElementsKind elements_kind() const { 1593 return hydrogen()->elements_kind(); 1594 } 1595 bool is_external() const { 1596 return hydrogen()->is_external(); 1597 } 1598 1599 virtual bool ClobbersDoubleRegisters() const { 1600 return !CpuFeatures::IsSupported(SSE2) && 1601 !IsDoubleOrFloatElementsKind(hydrogen()->elements_kind()); 1602 } 1603 1604 DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed") 1605 DECLARE_HYDROGEN_ACCESSOR(LoadKeyed) 1606 1607 virtual void PrintDataTo(StringStream* stream); 1608 uint32_t additional_index() const { return hydrogen()->index_offset(); } 1609 bool key_is_smi() { 1610 return hydrogen()->key()->representation().IsTagged(); 1611 } 1612 }; 1613 1614 1615 inline static bool ExternalArrayOpRequiresTemp( 1616 Representation key_representation, 1617 ElementsKind elements_kind) { 1618 // Operations that require the key to be divided by two to be converted into 1619 // an index cannot fold the scale operation into a load and need an extra 1620 // temp register to do the work. 1621 return key_representation.IsSmi() && 1622 (elements_kind == EXTERNAL_BYTE_ELEMENTS || 1623 elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS || 1624 elements_kind == EXTERNAL_PIXEL_ELEMENTS); 1625 } 1626 1627 1628 class LLoadKeyedGeneric: public LTemplateInstruction<1, 3, 0> { 1629 public: 1630 LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key) { 1631 inputs_[0] = context; 1632 inputs_[1] = obj; 1633 inputs_[2] = key; 1634 } 1635 1636 LOperand* context() { return inputs_[0]; } 1637 LOperand* object() { return inputs_[1]; } 1638 LOperand* key() { return inputs_[2]; } 1639 1640 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic") 1641 }; 1642 1643 1644 class LLoadGlobalCell: public LTemplateInstruction<1, 0, 0> { 1645 public: 1646 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell") 1647 DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell) 1648 }; 1649 1650 1651 class LLoadGlobalGeneric: public LTemplateInstruction<1, 2, 0> { 1652 public: 1653 LLoadGlobalGeneric(LOperand* context, LOperand* global_object) { 1654 inputs_[0] = context; 1655 inputs_[1] = global_object; 1656 } 1657 1658 LOperand* context() { return inputs_[0]; } 1659 LOperand* global_object() { return inputs_[1]; } 1660 1661 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic") 1662 DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric) 1663 1664 Handle<Object> name() const { return hydrogen()->name(); } 1665 bool for_typeof() const { return hydrogen()->for_typeof(); } 1666 }; 1667 1668 1669 class LStoreGlobalCell: public LTemplateInstruction<0, 1, 0> { 1670 public: 1671 explicit LStoreGlobalCell(LOperand* value) { 1672 inputs_[0] = value; 1673 } 1674 1675 LOperand* value() { return inputs_[0]; } 1676 1677 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell") 1678 DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell) 1679 }; 1680 1681 1682 class LStoreGlobalGeneric: public LTemplateInstruction<0, 3, 0> { 1683 public: 1684 LStoreGlobalGeneric(LOperand* context, 1685 LOperand* global_object, 1686 LOperand* value) { 1687 inputs_[0] = context; 1688 inputs_[1] = global_object; 1689 inputs_[2] = value; 1690 } 1691 1692 LOperand* context() { return inputs_[0]; } 1693 LOperand* global_object() { return inputs_[1]; } 1694 LOperand* value() { return inputs_[2]; } 1695 1696 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic") 1697 DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric) 1698 1699 Handle<Object> name() const { return hydrogen()->name(); } 1700 StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); } 1701 }; 1702 1703 1704 class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> { 1705 public: 1706 explicit LLoadContextSlot(LOperand* context) { 1707 inputs_[0] = context; 1708 } 1709 1710 LOperand* context() { return inputs_[0]; } 1711 1712 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot") 1713 DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot) 1714 1715 int slot_index() { return hydrogen()->slot_index(); } 1716 1717 virtual void PrintDataTo(StringStream* stream); 1718 }; 1719 1720 1721 class LStoreContextSlot: public LTemplateInstruction<0, 2, 1> { 1722 public: 1723 LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) { 1724 inputs_[0] = context; 1725 inputs_[1] = value; 1726 temps_[0] = temp; 1727 } 1728 1729 LOperand* context() { return inputs_[0]; } 1730 LOperand* value() { return inputs_[1]; } 1731 LOperand* temp() { return temps_[0]; } 1732 1733 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot") 1734 DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot) 1735 1736 int slot_index() { return hydrogen()->slot_index(); } 1737 1738 virtual void PrintDataTo(StringStream* stream); 1739 }; 1740 1741 1742 class LPushArgument: public LTemplateInstruction<0, 1, 0> { 1743 public: 1744 explicit LPushArgument(LOperand* value) { 1745 inputs_[0] = value; 1746 } 1747 1748 LOperand* value() { return inputs_[0]; } 1749 1750 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument") 1751 }; 1752 1753 1754 class LDrop: public LTemplateInstruction<0, 0, 0> { 1755 public: 1756 explicit LDrop(int count) : count_(count) { } 1757 1758 int count() const { return count_; } 1759 1760 DECLARE_CONCRETE_INSTRUCTION(Drop, "drop") 1761 1762 private: 1763 int count_; 1764 }; 1765 1766 1767 class LInnerAllocatedObject: public LTemplateInstruction<1, 1, 0> { 1768 public: 1769 explicit LInnerAllocatedObject(LOperand* base_object) { 1770 inputs_[0] = base_object; 1771 } 1772 1773 LOperand* base_object() { return inputs_[0]; } 1774 int offset() { return hydrogen()->offset(); } 1775 1776 virtual void PrintDataTo(StringStream* stream); 1777 1778 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "sub-allocated-object") 1779 DECLARE_HYDROGEN_ACCESSOR(InnerAllocatedObject) 1780 }; 1781 1782 1783 class LThisFunction: public LTemplateInstruction<1, 0, 0> { 1784 public: 1785 DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function") 1786 DECLARE_HYDROGEN_ACCESSOR(ThisFunction) 1787 }; 1788 1789 1790 class LContext: public LTemplateInstruction<1, 0, 0> { 1791 public: 1792 DECLARE_CONCRETE_INSTRUCTION(Context, "context") 1793 DECLARE_HYDROGEN_ACCESSOR(Context) 1794 }; 1795 1796 1797 class LOuterContext: public LTemplateInstruction<1, 1, 0> { 1798 public: 1799 explicit LOuterContext(LOperand* context) { 1800 inputs_[0] = context; 1801 } 1802 1803 LOperand* context() { return inputs_[0]; } 1804 1805 DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer-context") 1806 }; 1807 1808 1809 class LDeclareGlobals: public LTemplateInstruction<0, 1, 0> { 1810 public: 1811 explicit LDeclareGlobals(LOperand* context) { 1812 inputs_[0] = context; 1813 } 1814 1815 LOperand* context() { return inputs_[0]; } 1816 1817 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals") 1818 DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals) 1819 }; 1820 1821 1822 class LGlobalObject: public LTemplateInstruction<1, 1, 0> { 1823 public: 1824 explicit LGlobalObject(LOperand* context) { 1825 inputs_[0] = context; 1826 } 1827 1828 LOperand* context() { return inputs_[0]; } 1829 1830 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object") 1831 }; 1832 1833 1834 class LGlobalReceiver: public LTemplateInstruction<1, 1, 0> { 1835 public: 1836 explicit LGlobalReceiver(LOperand* global_object) { 1837 inputs_[0] = global_object; 1838 } 1839 1840 LOperand* global() { return inputs_[0]; } 1841 1842 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global-receiver") 1843 }; 1844 1845 1846 class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> { 1847 public: 1848 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call-constant-function") 1849 DECLARE_HYDROGEN_ACCESSOR(CallConstantFunction) 1850 1851 virtual void PrintDataTo(StringStream* stream); 1852 1853 Handle<JSFunction> function() { return hydrogen()->function(); } 1854 int arity() const { return hydrogen()->argument_count() - 1; } 1855 }; 1856 1857 1858 class LInvokeFunction: public LTemplateInstruction<1, 2, 0> { 1859 public: 1860 LInvokeFunction(LOperand* context, LOperand* function) { 1861 inputs_[0] = context; 1862 inputs_[1] = function; 1863 } 1864 1865 LOperand* context() { return inputs_[0]; } 1866 LOperand* function() { return inputs_[1]; } 1867 1868 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function") 1869 DECLARE_HYDROGEN_ACCESSOR(InvokeFunction) 1870 1871 virtual void PrintDataTo(StringStream* stream); 1872 1873 int arity() const { return hydrogen()->argument_count() - 1; } 1874 }; 1875 1876 1877 class LCallKeyed: public LTemplateInstruction<1, 2, 0> { 1878 public: 1879 LCallKeyed(LOperand* context, LOperand* key) { 1880 inputs_[0] = context; 1881 inputs_[1] = key; 1882 } 1883 1884 LOperand* context() { return inputs_[0]; } 1885 LOperand* key() { return inputs_[1]; } 1886 1887 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed") 1888 DECLARE_HYDROGEN_ACCESSOR(CallKeyed) 1889 1890 virtual void PrintDataTo(StringStream* stream); 1891 1892 int arity() const { return hydrogen()->argument_count() - 1; } 1893 }; 1894 1895 1896 class LCallNamed: public LTemplateInstruction<1, 1, 0> { 1897 public: 1898 explicit LCallNamed(LOperand* context) { 1899 inputs_[0] = context; 1900 } 1901 1902 LOperand* context() { return inputs_[0]; } 1903 1904 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call-named") 1905 DECLARE_HYDROGEN_ACCESSOR(CallNamed) 1906 1907 virtual void PrintDataTo(StringStream* stream); 1908 1909 Handle<String> name() const { return hydrogen()->name(); } 1910 int arity() const { return hydrogen()->argument_count() - 1; } 1911 }; 1912 1913 1914 class LCallFunction: public LTemplateInstruction<1, 2, 0> { 1915 public: 1916 explicit LCallFunction(LOperand* context, LOperand* function) { 1917 inputs_[0] = context; 1918 inputs_[1] = function; 1919 } 1920 1921 LOperand* context() { return inputs_[0]; } 1922 LOperand* function() { return inputs_[1]; } 1923 1924 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function") 1925 DECLARE_HYDROGEN_ACCESSOR(CallFunction) 1926 1927 int arity() const { return hydrogen()->argument_count() - 1; } 1928 }; 1929 1930 1931 class LCallGlobal: public LTemplateInstruction<1, 1, 0> { 1932 public: 1933 explicit LCallGlobal(LOperand* context) { 1934 inputs_[0] = context; 1935 } 1936 1937 LOperand* context() { return inputs_[0]; } 1938 1939 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global") 1940 DECLARE_HYDROGEN_ACCESSOR(CallGlobal) 1941 1942 virtual void PrintDataTo(StringStream* stream); 1943 1944 Handle<String> name() const {return hydrogen()->name(); } 1945 int arity() const { return hydrogen()->argument_count() - 1; } 1946 }; 1947 1948 1949 class LCallKnownGlobal: public LTemplateInstruction<1, 0, 0> { 1950 public: 1951 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call-known-global") 1952 DECLARE_HYDROGEN_ACCESSOR(CallKnownGlobal) 1953 1954 virtual void PrintDataTo(StringStream* stream); 1955 1956 int arity() const { return hydrogen()->argument_count() - 1; } 1957 }; 1958 1959 1960 class LCallNew: public LTemplateInstruction<1, 2, 0> { 1961 public: 1962 LCallNew(LOperand* context, LOperand* constructor) { 1963 inputs_[0] = context; 1964 inputs_[1] = constructor; 1965 } 1966 1967 LOperand* context() { return inputs_[0]; } 1968 LOperand* constructor() { return inputs_[1]; } 1969 1970 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new") 1971 DECLARE_HYDROGEN_ACCESSOR(CallNew) 1972 1973 virtual void PrintDataTo(StringStream* stream); 1974 1975 int arity() const { return hydrogen()->argument_count() - 1; } 1976 }; 1977 1978 1979 class LCallNewArray: public LTemplateInstruction<1, 2, 0> { 1980 public: 1981 LCallNewArray(LOperand* context, LOperand* constructor) { 1982 inputs_[0] = context; 1983 inputs_[1] = constructor; 1984 } 1985 1986 LOperand* context() { return inputs_[0]; } 1987 LOperand* constructor() { return inputs_[1]; } 1988 1989 DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array") 1990 DECLARE_HYDROGEN_ACCESSOR(CallNewArray) 1991 1992 virtual void PrintDataTo(StringStream* stream); 1993 1994 int arity() const { return hydrogen()->argument_count() - 1; } 1995 }; 1996 1997 1998 class LCallRuntime: public LTemplateInstruction<1, 1, 0> { 1999 public: 2000 explicit LCallRuntime(LOperand* context) { 2001 inputs_[0] = context; 2002 } 2003 2004 LOperand* context() { return inputs_[0]; } 2005 2006 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime") 2007 DECLARE_HYDROGEN_ACCESSOR(CallRuntime) 2008 2009 const Runtime::Function* function() const { return hydrogen()->function(); } 2010 int arity() const { return hydrogen()->argument_count(); } 2011 }; 2012 2013 2014 class LInteger32ToDouble: public LTemplateInstruction<1, 1, 0> { 2015 public: 2016 explicit LInteger32ToDouble(LOperand* value) { 2017 inputs_[0] = value; 2018 } 2019 2020 LOperand* value() { return inputs_[0]; } 2021 2022 DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double") 2023 }; 2024 2025 2026 class LInteger32ToSmi: public LTemplateInstruction<1, 1, 0> { 2027 public: 2028 explicit LInteger32ToSmi(LOperand* value) { 2029 inputs_[0] = value; 2030 } 2031 2032 LOperand* value() { return inputs_[0]; } 2033 2034 DECLARE_CONCRETE_INSTRUCTION(Integer32ToSmi, "int32-to-smi") 2035 DECLARE_HYDROGEN_ACCESSOR(Change) 2036 }; 2037 2038 2039 class LUint32ToDouble: public LTemplateInstruction<1, 1, 1> { 2040 public: 2041 explicit LUint32ToDouble(LOperand* value, LOperand* temp) { 2042 inputs_[0] = value; 2043 temps_[0] = temp; 2044 } 2045 2046 LOperand* value() { return inputs_[0]; } 2047 LOperand* temp() { return temps_[0]; } 2048 2049 DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double") 2050 }; 2051 2052 2053 class LNumberTagI: public LTemplateInstruction<1, 1, 0> { 2054 public: 2055 explicit LNumberTagI(LOperand* value) { 2056 inputs_[0] = value; 2057 } 2058 2059 LOperand* value() { return inputs_[0]; } 2060 2061 DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i") 2062 }; 2063 2064 2065 class LNumberTagU: public LTemplateInstruction<1, 1, 1> { 2066 public: 2067 LNumberTagU(LOperand* value, LOperand* temp) { 2068 inputs_[0] = value; 2069 temps_[0] = temp; 2070 } 2071 2072 LOperand* value() { return inputs_[0]; } 2073 LOperand* temp() { return temps_[0]; } 2074 2075 DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u") 2076 }; 2077 2078 2079 class LNumberTagD: public LTemplateInstruction<1, 1, 1> { 2080 public: 2081 LNumberTagD(LOperand* value, LOperand* temp) { 2082 inputs_[0] = value; 2083 temps_[0] = temp; 2084 } 2085 2086 LOperand* value() { return inputs_[0]; } 2087 LOperand* temp() { return temps_[0]; } 2088 2089 DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d") 2090 DECLARE_HYDROGEN_ACCESSOR(Change) 2091 }; 2092 2093 2094 // Sometimes truncating conversion from a tagged value to an int32. 2095 class LDoubleToI: public LTemplateInstruction<1, 1, 1> { 2096 public: 2097 LDoubleToI(LOperand* value, LOperand* temp) { 2098 inputs_[0] = value; 2099 temps_[0] = temp; 2100 } 2101 2102 LOperand* value() { return inputs_[0]; } 2103 LOperand* temp() { return temps_[0]; } 2104 2105 DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i") 2106 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) 2107 2108 bool truncating() { return hydrogen()->CanTruncateToInt32(); } 2109 }; 2110 2111 2112 class LDoubleToSmi: public LTemplateInstruction<1, 1, 0> { 2113 public: 2114 explicit LDoubleToSmi(LOperand* value) { 2115 inputs_[0] = value; 2116 } 2117 2118 LOperand* value() { return inputs_[0]; } 2119 2120 DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi") 2121 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) 2122 }; 2123 2124 2125 // Truncating conversion from a tagged value to an int32. 2126 class LTaggedToI: public LTemplateInstruction<1, 1, 1> { 2127 public: 2128 LTaggedToI(LOperand* value, LOperand* temp) { 2129 inputs_[0] = value; 2130 temps_[0] = temp; 2131 } 2132 2133 LOperand* value() { return inputs_[0]; } 2134 LOperand* temp() { return temps_[0]; } 2135 2136 DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i") 2137 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) 2138 2139 bool truncating() { return hydrogen()->CanTruncateToInt32(); } 2140 }; 2141 2142 2143 // Truncating conversion from a tagged value to an int32. 2144 class LTaggedToINoSSE2: public LTemplateInstruction<1, 1, 3> { 2145 public: 2146 LTaggedToINoSSE2(LOperand* value, 2147 LOperand* temp1, 2148 LOperand* temp2, 2149 LOperand* temp3) { 2150 inputs_[0] = value; 2151 temps_[0] = temp1; 2152 temps_[1] = temp2; 2153 temps_[2] = temp3; 2154 } 2155 2156 LOperand* value() { return inputs_[0]; } 2157 LOperand* scratch() { return temps_[0]; } 2158 LOperand* scratch2() { return temps_[1]; } 2159 LOperand* scratch3() { return temps_[2]; } 2160 2161 DECLARE_CONCRETE_INSTRUCTION(TaggedToINoSSE2, "tagged-to-i-nosse2") 2162 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) 2163 2164 bool truncating() { return hydrogen()->CanTruncateToInt32(); } 2165 }; 2166 2167 2168 class LSmiTag: public LTemplateInstruction<1, 1, 0> { 2169 public: 2170 explicit LSmiTag(LOperand* value) { 2171 inputs_[0] = value; 2172 } 2173 2174 LOperand* value() { return inputs_[0]; } 2175 2176 DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag") 2177 }; 2178 2179 2180 class LNumberUntagD: public LTemplateInstruction<1, 1, 1> { 2181 public: 2182 explicit LNumberUntagD(LOperand* value, LOperand* temp) { 2183 inputs_[0] = value; 2184 temps_[0] = temp; 2185 } 2186 2187 LOperand* value() { return inputs_[0]; } 2188 LOperand* temp() { return temps_[0]; } 2189 2190 virtual bool ClobbersDoubleRegisters() const { return false; } 2191 2192 DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag") 2193 DECLARE_HYDROGEN_ACCESSOR(Change); 2194 }; 2195 2196 2197 class LSmiUntag: public LTemplateInstruction<1, 1, 0> { 2198 public: 2199 LSmiUntag(LOperand* value, bool needs_check) 2200 : needs_check_(needs_check) { 2201 inputs_[0] = value; 2202 } 2203 2204 LOperand* value() { return inputs_[0]; } 2205 2206 DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag") 2207 2208 bool needs_check() const { return needs_check_; } 2209 2210 private: 2211 bool needs_check_; 2212 }; 2213 2214 2215 class LStoreNamedField: public LTemplateInstruction<0, 2, 2> { 2216 public: 2217 LStoreNamedField(LOperand* obj, 2218 LOperand* val, 2219 LOperand* temp, 2220 LOperand* temp_map) { 2221 inputs_[0] = obj; 2222 inputs_[1] = val; 2223 temps_[0] = temp; 2224 temps_[1] = temp_map; 2225 } 2226 2227 LOperand* object() { return inputs_[0]; } 2228 LOperand* value() { return inputs_[1]; } 2229 LOperand* temp() { return temps_[0]; } 2230 LOperand* temp_map() { return temps_[1]; } 2231 2232 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field") 2233 DECLARE_HYDROGEN_ACCESSOR(StoreNamedField) 2234 2235 virtual void PrintDataTo(StringStream* stream); 2236 2237 Handle<Map> transition() const { return hydrogen()->transition_map(); } 2238 Representation representation() const { 2239 return hydrogen()->field_representation(); 2240 } 2241 }; 2242 2243 2244 class LStoreNamedGeneric: public LTemplateInstruction<0, 3, 0> { 2245 public: 2246 LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value) { 2247 inputs_[0] = context; 2248 inputs_[1] = object; 2249 inputs_[2] = value; 2250 } 2251 2252 LOperand* context() { return inputs_[0]; } 2253 LOperand* object() { return inputs_[1]; } 2254 LOperand* value() { return inputs_[2]; } 2255 2256 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic") 2257 DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric) 2258 2259 virtual void PrintDataTo(StringStream* stream); 2260 Handle<Object> name() const { return hydrogen()->name(); } 2261 StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); } 2262 }; 2263 2264 2265 class LStoreKeyed: public LTemplateInstruction<0, 3, 0> { 2266 public: 2267 LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) { 2268 inputs_[0] = obj; 2269 inputs_[1] = key; 2270 inputs_[2] = val; 2271 } 2272 2273 bool is_external() const { return hydrogen()->is_external(); } 2274 LOperand* elements() { return inputs_[0]; } 2275 LOperand* key() { return inputs_[1]; } 2276 LOperand* value() { return inputs_[2]; } 2277 ElementsKind elements_kind() const { 2278 return hydrogen()->elements_kind(); 2279 } 2280 2281 DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed") 2282 DECLARE_HYDROGEN_ACCESSOR(StoreKeyed) 2283 2284 virtual void PrintDataTo(StringStream* stream); 2285 uint32_t additional_index() const { return hydrogen()->index_offset(); } 2286 bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); } 2287 }; 2288 2289 2290 class LStoreKeyedGeneric: public LTemplateInstruction<0, 4, 0> { 2291 public: 2292 LStoreKeyedGeneric(LOperand* context, 2293 LOperand* object, 2294 LOperand* key, 2295 LOperand* value) { 2296 inputs_[0] = context; 2297 inputs_[1] = object; 2298 inputs_[2] = key; 2299 inputs_[3] = value; 2300 } 2301 2302 LOperand* context() { return inputs_[0]; } 2303 LOperand* object() { return inputs_[1]; } 2304 LOperand* key() { return inputs_[2]; } 2305 LOperand* value() { return inputs_[3]; } 2306 2307 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic") 2308 DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric) 2309 2310 virtual void PrintDataTo(StringStream* stream); 2311 2312 StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); } 2313 }; 2314 2315 2316 class LTransitionElementsKind: public LTemplateInstruction<0, 2, 2> { 2317 public: 2318 LTransitionElementsKind(LOperand* object, 2319 LOperand* context, 2320 LOperand* new_map_temp, 2321 LOperand* temp) { 2322 inputs_[0] = object; 2323 inputs_[1] = context; 2324 temps_[0] = new_map_temp; 2325 temps_[1] = temp; 2326 } 2327 2328 LOperand* context() { return inputs_[1]; } 2329 LOperand* object() { return inputs_[0]; } 2330 LOperand* new_map_temp() { return temps_[0]; } 2331 LOperand* temp() { return temps_[1]; } 2332 2333 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind, 2334 "transition-elements-kind") 2335 DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind) 2336 2337 virtual void PrintDataTo(StringStream* stream); 2338 2339 Handle<Map> original_map() { return hydrogen()->original_map(); } 2340 Handle<Map> transitioned_map() { return hydrogen()->transitioned_map(); } 2341 ElementsKind from_kind() { return hydrogen()->from_kind(); } 2342 ElementsKind to_kind() { return hydrogen()->to_kind(); } 2343 }; 2344 2345 2346 class LTrapAllocationMemento : public LTemplateInstruction<0, 1, 1> { 2347 public: 2348 LTrapAllocationMemento(LOperand* object, 2349 LOperand* temp) { 2350 inputs_[0] = object; 2351 temps_[0] = temp; 2352 } 2353 2354 LOperand* object() { return inputs_[0]; } 2355 LOperand* temp() { return temps_[0]; } 2356 2357 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento, 2358 "trap-allocation-memento") 2359 }; 2360 2361 2362 class LStringAdd: public LTemplateInstruction<1, 3, 0> { 2363 public: 2364 LStringAdd(LOperand* context, LOperand* left, LOperand* right) { 2365 inputs_[0] = context; 2366 inputs_[1] = left; 2367 inputs_[2] = right; 2368 } 2369 2370 LOperand* context() { return inputs_[0]; } 2371 LOperand* left() { return inputs_[1]; } 2372 LOperand* right() { return inputs_[2]; } 2373 2374 DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add") 2375 DECLARE_HYDROGEN_ACCESSOR(StringAdd) 2376 }; 2377 2378 2379 class LStringCharCodeAt: public LTemplateInstruction<1, 3, 0> { 2380 public: 2381 LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) { 2382 inputs_[0] = context; 2383 inputs_[1] = string; 2384 inputs_[2] = index; 2385 } 2386 2387 LOperand* context() { return inputs_[0]; } 2388 LOperand* string() { return inputs_[1]; } 2389 LOperand* index() { return inputs_[2]; } 2390 2391 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at") 2392 DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt) 2393 }; 2394 2395 2396 class LStringCharFromCode: public LTemplateInstruction<1, 2, 0> { 2397 public: 2398 LStringCharFromCode(LOperand* context, LOperand* char_code) { 2399 inputs_[0] = context; 2400 inputs_[1] = char_code; 2401 } 2402 2403 LOperand* context() { return inputs_[0]; } 2404 LOperand* char_code() { return inputs_[1]; } 2405 2406 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code") 2407 DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode) 2408 }; 2409 2410 2411 class LCheckFunction: public LTemplateInstruction<0, 1, 0> { 2412 public: 2413 explicit LCheckFunction(LOperand* value) { 2414 inputs_[0] = value; 2415 } 2416 2417 LOperand* value() { return inputs_[0]; } 2418 2419 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function") 2420 DECLARE_HYDROGEN_ACCESSOR(CheckFunction) 2421 }; 2422 2423 2424 class LCheckInstanceType: public LTemplateInstruction<0, 1, 1> { 2425 public: 2426 LCheckInstanceType(LOperand* value, LOperand* temp) { 2427 inputs_[0] = value; 2428 temps_[0] = temp; 2429 } 2430 2431 LOperand* value() { return inputs_[0]; } 2432 LOperand* temp() { return temps_[0]; } 2433 2434 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type") 2435 DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType) 2436 }; 2437 2438 2439 class LCheckMaps: public LTemplateInstruction<0, 1, 0> { 2440 public: 2441 explicit LCheckMaps(LOperand* value) { 2442 inputs_[0] = value; 2443 } 2444 2445 LOperand* value() { return inputs_[0]; } 2446 2447 DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps") 2448 DECLARE_HYDROGEN_ACCESSOR(CheckMaps) 2449 }; 2450 2451 2452 class LCheckSmi: public LTemplateInstruction<1, 1, 0> { 2453 public: 2454 explicit LCheckSmi(LOperand* value) { 2455 inputs_[0] = value; 2456 } 2457 2458 LOperand* value() { return inputs_[0]; } 2459 2460 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi") 2461 }; 2462 2463 2464 class LClampDToUint8: public LTemplateInstruction<1, 1, 0> { 2465 public: 2466 explicit LClampDToUint8(LOperand* value) { 2467 inputs_[0] = value; 2468 } 2469 2470 LOperand* unclamped() { return inputs_[0]; } 2471 2472 DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8") 2473 }; 2474 2475 2476 class LClampIToUint8: public LTemplateInstruction<1, 1, 0> { 2477 public: 2478 explicit LClampIToUint8(LOperand* value) { 2479 inputs_[0] = value; 2480 } 2481 2482 LOperand* unclamped() { return inputs_[0]; } 2483 2484 DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8") 2485 }; 2486 2487 2488 class LClampTToUint8: public LTemplateInstruction<1, 1, 1> { 2489 public: 2490 LClampTToUint8(LOperand* value, LOperand* temp) { 2491 inputs_[0] = value; 2492 temps_[0] = temp; 2493 } 2494 2495 LOperand* unclamped() { return inputs_[0]; } 2496 2497 DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8") 2498 }; 2499 2500 2501 // Truncating conversion from a tagged value to an int32. 2502 class LClampTToUint8NoSSE2: public LTemplateInstruction<1, 1, 3> { 2503 public: 2504 LClampTToUint8NoSSE2(LOperand* unclamped, 2505 LOperand* temp1, 2506 LOperand* temp2, 2507 LOperand* temp3) { 2508 inputs_[0] = unclamped; 2509 temps_[0] = temp1; 2510 temps_[1] = temp2; 2511 temps_[2] = temp3; 2512 } 2513 2514 LOperand* unclamped() { return inputs_[0]; } 2515 LOperand* scratch() { return temps_[0]; } 2516 LOperand* scratch2() { return temps_[1]; } 2517 LOperand* scratch3() { return temps_[2]; } 2518 2519 DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8NoSSE2, 2520 "clamp-t-to-uint8-nosse2") 2521 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) 2522 }; 2523 2524 2525 class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> { 2526 public: 2527 explicit LCheckNonSmi(LOperand* value) { 2528 inputs_[0] = value; 2529 } 2530 2531 LOperand* value() { return inputs_[0]; } 2532 2533 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi") 2534 DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject) 2535 }; 2536 2537 2538 class LAllocate: public LTemplateInstruction<1, 2, 1> { 2539 public: 2540 LAllocate(LOperand* context, LOperand* size, LOperand* temp) { 2541 inputs_[0] = context; 2542 inputs_[1] = size; 2543 temps_[0] = temp; 2544 } 2545 2546 LOperand* context() { return inputs_[0]; } 2547 LOperand* size() { return inputs_[1]; } 2548 LOperand* temp() { return temps_[0]; } 2549 2550 DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate") 2551 DECLARE_HYDROGEN_ACCESSOR(Allocate) 2552 }; 2553 2554 2555 class LRegExpLiteral: public LTemplateInstruction<1, 1, 0> { 2556 public: 2557 explicit LRegExpLiteral(LOperand* context) { 2558 inputs_[0] = context; 2559 } 2560 2561 LOperand* context() { return inputs_[0]; } 2562 2563 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal") 2564 DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral) 2565 }; 2566 2567 2568 class LFunctionLiteral: public LTemplateInstruction<1, 1, 0> { 2569 public: 2570 explicit LFunctionLiteral(LOperand* context) { 2571 inputs_[0] = context; 2572 } 2573 2574 LOperand* context() { return inputs_[0]; } 2575 2576 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal") 2577 DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral) 2578 }; 2579 2580 2581 class LToFastProperties: public LTemplateInstruction<1, 1, 0> { 2582 public: 2583 explicit LToFastProperties(LOperand* value) { 2584 inputs_[0] = value; 2585 } 2586 2587 LOperand* value() { return inputs_[0]; } 2588 2589 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties") 2590 DECLARE_HYDROGEN_ACCESSOR(ToFastProperties) 2591 }; 2592 2593 2594 class LTypeof: public LTemplateInstruction<1, 2, 0> { 2595 public: 2596 LTypeof(LOperand* context, LOperand* value) { 2597 inputs_[0] = context; 2598 inputs_[1] = value; 2599 } 2600 2601 LOperand* context() { return inputs_[0]; } 2602 LOperand* value() { return inputs_[1]; } 2603 2604 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof") 2605 }; 2606 2607 2608 class LTypeofIsAndBranch: public LControlInstruction<1, 0> { 2609 public: 2610 explicit LTypeofIsAndBranch(LOperand* value) { 2611 inputs_[0] = value; 2612 } 2613 2614 LOperand* value() { return inputs_[0]; } 2615 2616 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch") 2617 DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch) 2618 2619 Handle<String> type_literal() { return hydrogen()->type_literal(); } 2620 2621 virtual void PrintDataTo(StringStream* stream); 2622 }; 2623 2624 2625 class LOsrEntry: public LTemplateInstruction<0, 0, 0> { 2626 public: 2627 LOsrEntry() {} 2628 2629 virtual bool HasInterestingComment(LCodeGen* gen) const { return false; } 2630 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry") 2631 }; 2632 2633 2634 class LStackCheck: public LTemplateInstruction<0, 1, 0> { 2635 public: 2636 explicit LStackCheck(LOperand* context) { 2637 inputs_[0] = context; 2638 } 2639 2640 LOperand* context() { return inputs_[0]; } 2641 2642 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check") 2643 DECLARE_HYDROGEN_ACCESSOR(StackCheck) 2644 2645 Label* done_label() { return &done_label_; } 2646 2647 private: 2648 Label done_label_; 2649 }; 2650 2651 2652 class LForInPrepareMap: public LTemplateInstruction<1, 2, 0> { 2653 public: 2654 LForInPrepareMap(LOperand* context, LOperand* object) { 2655 inputs_[0] = context; 2656 inputs_[1] = object; 2657 } 2658 2659 LOperand* context() { return inputs_[0]; } 2660 LOperand* object() { return inputs_[1]; } 2661 2662 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map") 2663 }; 2664 2665 2666 class LForInCacheArray: public LTemplateInstruction<1, 1, 0> { 2667 public: 2668 explicit LForInCacheArray(LOperand* map) { 2669 inputs_[0] = map; 2670 } 2671 2672 LOperand* map() { return inputs_[0]; } 2673 2674 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array") 2675 2676 int idx() { 2677 return HForInCacheArray::cast(this->hydrogen_value())->idx(); 2678 } 2679 }; 2680 2681 2682 class LCheckMapValue: public LTemplateInstruction<0, 2, 0> { 2683 public: 2684 LCheckMapValue(LOperand* value, LOperand* map) { 2685 inputs_[0] = value; 2686 inputs_[1] = map; 2687 } 2688 2689 LOperand* value() { return inputs_[0]; } 2690 LOperand* map() { return inputs_[1]; } 2691 2692 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value") 2693 }; 2694 2695 2696 class LLoadFieldByIndex: public LTemplateInstruction<1, 2, 0> { 2697 public: 2698 LLoadFieldByIndex(LOperand* object, LOperand* index) { 2699 inputs_[0] = object; 2700 inputs_[1] = index; 2701 } 2702 2703 LOperand* object() { return inputs_[0]; } 2704 LOperand* index() { return inputs_[1]; } 2705 2706 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index") 2707 }; 2708 2709 2710 class LChunkBuilder; 2711 class LPlatformChunk: public LChunk { 2712 public: 2713 LPlatformChunk(CompilationInfo* info, HGraph* graph) 2714 : LChunk(info, graph), 2715 num_double_slots_(0) { } 2716 2717 int GetNextSpillIndex(bool is_double); 2718 LOperand* GetNextSpillSlot(bool is_double); 2719 2720 int num_double_slots() const { return num_double_slots_; } 2721 2722 private: 2723 int num_double_slots_; 2724 }; 2725 2726 2727 class LChunkBuilder BASE_EMBEDDED { 2728 public: 2729 LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator) 2730 : chunk_(NULL), 2731 info_(info), 2732 graph_(graph), 2733 zone_(graph->zone()), 2734 status_(UNUSED), 2735 current_instruction_(NULL), 2736 current_block_(NULL), 2737 next_block_(NULL), 2738 argument_count_(0), 2739 allocator_(allocator), 2740 position_(RelocInfo::kNoPosition), 2741 instruction_pending_deoptimization_environment_(NULL), 2742 pending_deoptimization_ast_id_(BailoutId::None()) { } 2743 2744 // Build the sequence for the graph. 2745 LPlatformChunk* Build(); 2746 2747 // Declare methods that deal with the individual node types. 2748 #define DECLARE_DO(type) LInstruction* Do##type(H##type* node); 2749 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) 2750 #undef DECLARE_DO 2751 2752 static HValue* SimplifiedDivisorForMathFloorOfDiv(HValue* val); 2753 2754 LInstruction* DoMathFloor(HUnaryMathOperation* instr); 2755 LInstruction* DoMathRound(HUnaryMathOperation* instr); 2756 LInstruction* DoMathAbs(HUnaryMathOperation* instr); 2757 LInstruction* DoMathLog(HUnaryMathOperation* instr); 2758 LInstruction* DoMathSin(HUnaryMathOperation* instr); 2759 LInstruction* DoMathCos(HUnaryMathOperation* instr); 2760 LInstruction* DoMathTan(HUnaryMathOperation* instr); 2761 LInstruction* DoMathExp(HUnaryMathOperation* instr); 2762 LInstruction* DoMathSqrt(HUnaryMathOperation* instr); 2763 LInstruction* DoMathPowHalf(HUnaryMathOperation* instr); 2764 2765 private: 2766 enum Status { 2767 UNUSED, 2768 BUILDING, 2769 DONE, 2770 ABORTED 2771 }; 2772 2773 LPlatformChunk* chunk() const { return chunk_; } 2774 CompilationInfo* info() const { return info_; } 2775 HGraph* graph() const { return graph_; } 2776 Zone* zone() const { return zone_; } 2777 2778 bool is_unused() const { return status_ == UNUSED; } 2779 bool is_building() const { return status_ == BUILDING; } 2780 bool is_done() const { return status_ == DONE; } 2781 bool is_aborted() const { return status_ == ABORTED; } 2782 2783 void Abort(BailoutReason reason); 2784 2785 // Methods for getting operands for Use / Define / Temp. 2786 LUnallocated* ToUnallocated(Register reg); 2787 LUnallocated* ToUnallocated(XMMRegister reg); 2788 LUnallocated* ToUnallocated(X87Register reg); 2789 2790 // Methods for setting up define-use relationships. 2791 MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand); 2792 MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register); 2793 MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value, 2794 XMMRegister fixed_register); 2795 2796 // A value that is guaranteed to be allocated to a register. 2797 // Operand created by UseRegister is guaranteed to be live until the end of 2798 // instruction. This means that register allocator will not reuse it's 2799 // register for any other operand inside instruction. 2800 // Operand created by UseRegisterAtStart is guaranteed to be live only at 2801 // instruction start. Register allocator is free to assign the same register 2802 // to some other operand used inside instruction (i.e. temporary or 2803 // output). 2804 MUST_USE_RESULT LOperand* UseRegister(HValue* value); 2805 MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value); 2806 2807 // An input operand in a register that may be trashed. 2808 MUST_USE_RESULT LOperand* UseTempRegister(HValue* value); 2809 2810 // An input operand in a register or stack slot. 2811 MUST_USE_RESULT LOperand* Use(HValue* value); 2812 MUST_USE_RESULT LOperand* UseAtStart(HValue* value); 2813 2814 // An input operand in a register, stack slot or a constant operand. 2815 MUST_USE_RESULT LOperand* UseOrConstant(HValue* value); 2816 MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value); 2817 2818 // An input operand in a register or a constant operand. 2819 MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value); 2820 MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value); 2821 2822 // An input operand in a constant operand. 2823 MUST_USE_RESULT LOperand* UseConstant(HValue* value); 2824 2825 // An input operand in register, stack slot or a constant operand. 2826 // Will not be moved to a register even if one is freely available. 2827 MUST_USE_RESULT LOperand* UseAny(HValue* value); 2828 2829 // Temporary operand that must be in a register. 2830 MUST_USE_RESULT LUnallocated* TempRegister(); 2831 MUST_USE_RESULT LOperand* FixedTemp(Register reg); 2832 MUST_USE_RESULT LOperand* FixedTemp(XMMRegister reg); 2833 2834 // Methods for setting up define-use relationships. 2835 // Return the same instruction that they are passed. 2836 template<int I, int T> 2837 LInstruction* Define(LTemplateInstruction<1, I, T>* instr, 2838 LUnallocated* result); 2839 template<int I, int T> 2840 LInstruction* DefineAsRegister(LTemplateInstruction<1, I, T>* instr); 2841 template<int I, int T> 2842 LInstruction* DefineAsSpilled(LTemplateInstruction<1, I, T>* instr, 2843 int index); 2844 template<int I, int T> 2845 LInstruction* DefineSameAsFirst(LTemplateInstruction<1, I, T>* instr); 2846 template<int I, int T> 2847 LInstruction* DefineFixed(LTemplateInstruction<1, I, T>* instr, 2848 Register reg); 2849 template<int I, int T> 2850 LInstruction* DefineFixedDouble(LTemplateInstruction<1, I, T>* instr, 2851 XMMRegister reg); 2852 template<int I, int T> 2853 LInstruction* DefineX87TOS(LTemplateInstruction<1, I, T>* instr); 2854 // Assigns an environment to an instruction. An instruction which can 2855 // deoptimize must have an environment. 2856 LInstruction* AssignEnvironment(LInstruction* instr); 2857 // Assigns a pointer map to an instruction. An instruction which can 2858 // trigger a GC or a lazy deoptimization must have a pointer map. 2859 LInstruction* AssignPointerMap(LInstruction* instr); 2860 2861 enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY }; 2862 2863 // Marks a call for the register allocator. Assigns a pointer map to 2864 // support GC and lazy deoptimization. Assigns an environment to support 2865 // eager deoptimization if CAN_DEOPTIMIZE_EAGERLY. 2866 LInstruction* MarkAsCall( 2867 LInstruction* instr, 2868 HInstruction* hinstr, 2869 CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY); 2870 2871 LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env, 2872 int* argument_index_accumulator, 2873 ZoneList<HValue*>* objects_to_materialize); 2874 2875 void VisitInstruction(HInstruction* current); 2876 2877 void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block); 2878 LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr); 2879 LInstruction* DoArithmeticD(Token::Value op, 2880 HArithmeticBinaryOperation* instr); 2881 LInstruction* DoArithmeticT(Token::Value op, 2882 HArithmeticBinaryOperation* instr); 2883 2884 LOperand* GetStoreKeyedValueOperand(HStoreKeyed* instr); 2885 2886 LPlatformChunk* chunk_; 2887 CompilationInfo* info_; 2888 HGraph* const graph_; 2889 Zone* zone_; 2890 Status status_; 2891 HInstruction* current_instruction_; 2892 HBasicBlock* current_block_; 2893 HBasicBlock* next_block_; 2894 int argument_count_; 2895 LAllocator* allocator_; 2896 int position_; 2897 LInstruction* instruction_pending_deoptimization_environment_; 2898 BailoutId pending_deoptimization_ast_id_; 2899 2900 DISALLOW_COPY_AND_ASSIGN(LChunkBuilder); 2901 }; 2902 2903 #undef DECLARE_HYDROGEN_ACCESSOR 2904 #undef DECLARE_CONCRETE_INSTRUCTION 2905 2906 } } // namespace v8::internal 2907 2908 #endif // V8_IA32_LITHIUM_IA32_H_ 2909