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