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