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