1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_ARM64_LITHIUM_ARM64_H_
6 #define V8_ARM64_LITHIUM_ARM64_H_
8 #include "src/hydrogen.h"
9 #include "src/lithium.h"
10 #include "src/lithium-allocator.h"
11 #include "src/safepoint-table.h"
12 #include "src/utils.h"
17 // Forward declarations.
20 #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
21 V(AccessArgumentsAt) \
26 V(AllocateBlockContext) \
28 V(ArgumentsElements) \
42 V(CallWithDescriptor) \
43 V(CheckArrayBufferNotNeutered) \
44 V(CheckInstanceType) \
53 V(ClassOfTestAndBranch) \
54 V(CmpHoleAndBranchD) \
55 V(CmpHoleAndBranchT) \
57 V(CmpObjectEqAndBranch) \
59 V(CompareMinusZeroAndBranch) \
60 V(CompareNumericAndBranch) \
80 V(FlooringDivByConstI) \
81 V(FlooringDivByPowerOf2I) \
85 V(GetCachedArrayIndex) \
87 V(HasCachedArrayIndexAndBranch) \
88 V(HasInPrototypeChainAndBranch) \
89 V(HasInstanceTypeAndBranch) \
90 V(InnerAllocatedObject) \
93 V(Integer32ToDouble) \
95 V(IsConstructCallAndBranch) \
97 V(IsStringAndBranch) \
98 V(IsUndetectableAndBranch) \
102 V(LoadFieldByIndex) \
103 V(LoadFunctionPrototype) \
104 V(LoadGlobalGeneric) \
105 V(LoadGlobalViaContext) \
106 V(LoadKeyedExternal) \
108 V(LoadKeyedFixedDouble) \
109 V(LoadKeyedGeneric) \
111 V(LoadNamedGeneric) \
127 V(MaybeGrowElements) \
141 V(PreparePushArguments) \
145 V(SeqStringGetChar) \
146 V(SeqStringSetChar) \
153 V(StoreContextSlot) \
154 V(StoreFrameContext) \
155 V(StoreGlobalViaContext) \
156 V(StoreKeyedExternal) \
158 V(StoreKeyedFixedDouble) \
159 V(StoreKeyedGeneric) \
161 V(StoreNamedGeneric) \
163 V(StringCharCodeAt) \
164 V(StringCharFromCode) \
165 V(StringCompareAndBranch) \
170 V(ToFastProperties) \
171 V(TransitionElementsKind) \
172 V(TrapAllocationMemento) \
173 V(TruncateDoubleToIntOrSmi) \
175 V(TypeofIsAndBranch) \
181 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
182 Opcode opcode() const final { return LInstruction::k##type; } \
183 void CompileToNative(LCodeGen* generator) final; \
184 const char* Mnemonic() const final { return mnemonic; } \
185 static L##type* cast(LInstruction* instr) { \
186 DCHECK(instr->Is##type()); \
187 return reinterpret_cast<L##type*>(instr); \
191 #define DECLARE_HYDROGEN_ACCESSOR(type) \
192 H##type* hydrogen() const { \
193 return H##type::cast(this->hydrogen_value()); \
197 class LInstruction : public ZoneObject {
200 : environment_(NULL),
201 hydrogen_value_(NULL),
202 bit_field_(IsCallBits::encode(false)) { }
204 virtual ~LInstruction() { }
206 virtual void CompileToNative(LCodeGen* generator) = 0;
207 virtual const char* Mnemonic() const = 0;
208 virtual void PrintTo(StringStream* stream);
209 virtual void PrintDataTo(StringStream* stream);
210 virtual void PrintOutputOperandTo(StringStream* stream);
213 // Declare a unique enum value for each instruction.
214 #define DECLARE_OPCODE(type) k##type,
215 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
216 kNumberOfInstructions
217 #undef DECLARE_OPCODE
220 virtual Opcode opcode() const = 0;
222 // Declare non-virtual type testers for all leaf IR classes.
223 #define DECLARE_PREDICATE(type) \
224 bool Is##type() const { return opcode() == k##type; }
225 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
226 #undef DECLARE_PREDICATE
228 // Declare virtual predicates for instructions that don't have
230 virtual bool IsGap() const { return false; }
232 virtual bool IsControl() const { return false; }
234 // Try deleting this instruction if possible.
235 virtual bool TryDelete() { return false; }
237 void set_environment(LEnvironment* env) { environment_ = env; }
238 LEnvironment* environment() const { return environment_; }
239 bool HasEnvironment() const { return environment_ != NULL; }
241 void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
242 LPointerMap* pointer_map() const { return pointer_map_.get(); }
243 bool HasPointerMap() const { return pointer_map_.is_set(); }
245 void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
246 HValue* hydrogen_value() const { return hydrogen_value_; }
248 void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
249 bool IsCall() const { return IsCallBits::decode(bit_field_); }
251 // Interface to the register allocator and iterators.
252 bool ClobbersTemps() const { return IsCall(); }
253 bool ClobbersRegisters() const { return IsCall(); }
254 virtual bool ClobbersDoubleRegisters(Isolate* isolate) const {
257 bool IsMarkedAsCall() const { return IsCall(); }
259 virtual bool HasResult() const = 0;
260 virtual LOperand* result() const = 0;
262 virtual int InputCount() = 0;
263 virtual LOperand* InputAt(int i) = 0;
264 virtual int TempCount() = 0;
265 virtual LOperand* TempAt(int i) = 0;
267 LOperand* FirstInput() { return InputAt(0); }
268 LOperand* Output() { return HasResult() ? result() : NULL; }
270 virtual bool HasInterestingComment(LCodeGen* gen) const { return true; }
277 class IsCallBits: public BitField<bool, 0, 1> {};
279 LEnvironment* environment_;
280 SetOncePointer<LPointerMap> pointer_map_;
281 HValue* hydrogen_value_;
286 // R = number of result operands (0 or 1).
288 class LTemplateResultInstruction : public LInstruction {
290 // Allow 0 or 1 output operands.
291 STATIC_ASSERT(R == 0 || R == 1);
292 bool HasResult() const final { return (R != 0) && (result() != NULL); }
293 void set_result(LOperand* operand) { results_[0] = operand; }
294 LOperand* result() const override { return results_[0]; }
297 EmbeddedContainer<LOperand*, R> results_;
301 // R = number of result operands (0 or 1).
302 // I = number of input operands.
303 // T = number of temporary operands.
304 template<int R, int I, int T>
305 class LTemplateInstruction : public LTemplateResultInstruction<R> {
307 EmbeddedContainer<LOperand*, I> inputs_;
308 EmbeddedContainer<LOperand*, T> temps_;
312 int InputCount() final { return I; }
313 LOperand* InputAt(int i) final { return inputs_[i]; }
315 int TempCount() final { return T; }
316 LOperand* TempAt(int i) final { return temps_[i]; }
320 class LUnknownOSRValue final : public LTemplateInstruction<1, 0, 0> {
322 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
323 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
327 template<int I, int T>
328 class LControlInstruction : public LTemplateInstruction<0, I, T> {
330 LControlInstruction() : false_label_(NULL), true_label_(NULL) { }
332 bool IsControl() const final { return true; }
334 int SuccessorCount() { return hydrogen()->SuccessorCount(); }
335 HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
337 int TrueDestination(LChunk* chunk) {
338 return chunk->LookupDestination(true_block_id());
341 int FalseDestination(LChunk* chunk) {
342 return chunk->LookupDestination(false_block_id());
345 Label* TrueLabel(LChunk* chunk) {
346 if (true_label_ == NULL) {
347 true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk));
352 Label* FalseLabel(LChunk* chunk) {
353 if (false_label_ == NULL) {
354 false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk));
360 int true_block_id() { return SuccessorAt(0)->block_id(); }
361 int false_block_id() { return SuccessorAt(1)->block_id(); }
364 DECLARE_HYDROGEN_ACCESSOR(ControlInstruction);
371 class LGap : public LTemplateInstruction<0, 0, 0> {
373 explicit LGap(HBasicBlock* block)
375 parallel_moves_[BEFORE] = NULL;
376 parallel_moves_[START] = NULL;
377 parallel_moves_[END] = NULL;
378 parallel_moves_[AFTER] = NULL;
381 // Can't use the DECLARE-macro here because of sub-classes.
382 bool IsGap() const override { return true; }
383 void PrintDataTo(StringStream* stream) override;
384 static LGap* cast(LInstruction* instr) {
385 DCHECK(instr->IsGap());
386 return reinterpret_cast<LGap*>(instr);
389 bool IsRedundant() const;
391 HBasicBlock* block() const { return block_; }
398 FIRST_INNER_POSITION = BEFORE,
399 LAST_INNER_POSITION = AFTER
402 LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) {
403 if (parallel_moves_[pos] == NULL) {
404 parallel_moves_[pos] = new(zone) LParallelMove(zone);
406 return parallel_moves_[pos];
409 LParallelMove* GetParallelMove(InnerPosition pos) {
410 return parallel_moves_[pos];
414 LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
419 class LInstructionGap final : public LGap {
421 explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
423 bool HasInterestingComment(LCodeGen* gen) const override {
424 return !IsRedundant();
427 DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
431 class LDrop final : public LTemplateInstruction<0, 0, 0> {
433 explicit LDrop(int count) : count_(count) { }
435 int count() const { return count_; }
437 DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")
444 class LDummy final : public LTemplateInstruction<1, 0, 0> {
447 DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
451 class LDummyUse final : public LTemplateInstruction<1, 1, 0> {
453 explicit LDummyUse(LOperand* value) {
456 DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
460 class LGoto final : public LTemplateInstruction<0, 0, 0> {
462 explicit LGoto(HBasicBlock* block) : block_(block) { }
464 bool HasInterestingComment(LCodeGen* gen) const override;
465 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
466 void PrintDataTo(StringStream* stream) override;
467 bool IsControl() const override { return true; }
469 int block_id() const { return block_->block_id(); }
476 class LPrologue final : public LTemplateInstruction<0, 0, 0> {
478 DECLARE_CONCRETE_INSTRUCTION(Prologue, "prologue")
482 class LLazyBailout final : public LTemplateInstruction<0, 0, 0> {
484 LLazyBailout() : gap_instructions_size_(0) { }
486 DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
488 void set_gap_instructions_size(int gap_instructions_size) {
489 gap_instructions_size_ = gap_instructions_size;
491 int gap_instructions_size() { return gap_instructions_size_; }
494 int gap_instructions_size_;
498 class LLabel final : public LGap {
500 explicit LLabel(HBasicBlock* block)
501 : LGap(block), replacement_(NULL) { }
503 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
504 DECLARE_CONCRETE_INSTRUCTION(Label, "label")
506 void PrintDataTo(StringStream* stream) override;
508 int block_id() const { return block()->block_id(); }
509 bool is_loop_header() const { return block()->IsLoopHeader(); }
510 bool is_osr_entry() const { return block()->is_osr_entry(); }
511 Label* label() { return &label_; }
512 LLabel* replacement() const { return replacement_; }
513 void set_replacement(LLabel* label) { replacement_ = label; }
514 bool HasReplacement() const { return replacement_ != NULL; }
518 LLabel* replacement_;
522 class LOsrEntry final : public LTemplateInstruction<0, 0, 0> {
526 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
527 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
531 class LAccessArgumentsAt final : public LTemplateInstruction<1, 3, 0> {
533 LAccessArgumentsAt(LOperand* arguments,
536 inputs_[0] = arguments;
541 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
543 LOperand* arguments() { return inputs_[0]; }
544 LOperand* length() { return inputs_[1]; }
545 LOperand* index() { return inputs_[2]; }
547 void PrintDataTo(StringStream* stream) override;
551 class LAddE final : public LTemplateInstruction<1, 2, 0> {
553 LAddE(LOperand* left, LOperand* right) {
558 LOperand* left() { return inputs_[0]; }
559 LOperand* right() { return inputs_[1]; }
561 DECLARE_CONCRETE_INSTRUCTION(AddE, "add-e")
562 DECLARE_HYDROGEN_ACCESSOR(Add)
566 class LAddI final : public LTemplateInstruction<1, 2, 0> {
568 LAddI(LOperand* left, LOperand* right)
569 : shift_(NO_SHIFT), shift_amount_(0) {
574 LAddI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
575 : shift_(shift), shift_amount_(shift_amount) {
580 LOperand* left() { return inputs_[0]; }
581 LOperand* right() { return inputs_[1]; }
583 Shift shift() const { return shift_; }
584 LOperand* shift_amount() const { return shift_amount_; }
586 DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
587 DECLARE_HYDROGEN_ACCESSOR(Add)
591 LOperand* shift_amount_;
595 class LAddS final : public LTemplateInstruction<1, 2, 0> {
597 LAddS(LOperand* left, LOperand* right) {
602 LOperand* left() { return inputs_[0]; }
603 LOperand* right() { return inputs_[1]; }
605 DECLARE_CONCRETE_INSTRUCTION(AddS, "add-s")
606 DECLARE_HYDROGEN_ACCESSOR(Add)
610 class LAllocate final : public LTemplateInstruction<1, 2, 3> {
612 LAllocate(LOperand* context,
617 inputs_[0] = context;
624 LOperand* context() { return inputs_[0]; }
625 LOperand* size() { return inputs_[1]; }
626 LOperand* temp1() { return temps_[0]; }
627 LOperand* temp2() { return temps_[1]; }
628 LOperand* temp3() { return temps_[2]; }
630 DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
631 DECLARE_HYDROGEN_ACCESSOR(Allocate)
635 class LApplyArguments final : public LTemplateInstruction<1, 4, 0> {
637 LApplyArguments(LOperand* function,
640 LOperand* elements) {
641 inputs_[0] = function;
642 inputs_[1] = receiver;
644 inputs_[3] = elements;
647 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
649 LOperand* function() { return inputs_[0]; }
650 LOperand* receiver() { return inputs_[1]; }
651 LOperand* length() { return inputs_[2]; }
652 LOperand* elements() { return inputs_[3]; }
656 class LArgumentsElements final : public LTemplateInstruction<1, 0, 1> {
658 explicit LArgumentsElements(LOperand* temp) {
662 LOperand* temp() { return temps_[0]; }
664 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
665 DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements)
669 class LArgumentsLength final : public LTemplateInstruction<1, 1, 0> {
671 explicit LArgumentsLength(LOperand* elements) {
672 inputs_[0] = elements;
675 LOperand* elements() { return inputs_[0]; }
677 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
681 class LArithmeticD final : public LTemplateInstruction<1, 2, 0> {
683 LArithmeticD(Token::Value op,
691 Token::Value op() const { return op_; }
692 LOperand* left() { return inputs_[0]; }
693 LOperand* right() { return inputs_[1]; }
695 Opcode opcode() const override { return LInstruction::kArithmeticD; }
696 void CompileToNative(LCodeGen* generator) override;
697 const char* Mnemonic() const override;
704 class LArithmeticT final : public LTemplateInstruction<1, 3, 0> {
706 LArithmeticT(Token::Value op,
711 inputs_[0] = context;
716 LOperand* context() { return inputs_[0]; }
717 LOperand* left() { return inputs_[1]; }
718 LOperand* right() { return inputs_[2]; }
719 Token::Value op() const { return op_; }
721 Opcode opcode() const override { return LInstruction::kArithmeticT; }
722 void CompileToNative(LCodeGen* generator) override;
723 const char* Mnemonic() const override;
725 DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
727 Strength strength() { return hydrogen()->strength(); }
734 class LBoundsCheck final : public LTemplateInstruction<0, 2, 0> {
736 explicit LBoundsCheck(LOperand* index, LOperand* length) {
741 LOperand* index() { return inputs_[0]; }
742 LOperand* length() { return inputs_[1]; }
744 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
745 DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
749 class LBitI final : public LTemplateInstruction<1, 2, 0> {
751 LBitI(LOperand* left, LOperand* right)
752 : shift_(NO_SHIFT), shift_amount_(0) {
757 LBitI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
758 : shift_(shift), shift_amount_(shift_amount) {
763 LOperand* left() { return inputs_[0]; }
764 LOperand* right() { return inputs_[1]; }
766 Shift shift() const { return shift_; }
767 LOperand* shift_amount() const { return shift_amount_; }
769 Token::Value op() const { return hydrogen()->op(); }
771 DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
772 DECLARE_HYDROGEN_ACCESSOR(Bitwise)
776 LOperand* shift_amount_;
780 class LBitS final : public LTemplateInstruction<1, 2, 0> {
782 LBitS(LOperand* left, LOperand* right) {
787 LOperand* left() { return inputs_[0]; }
788 LOperand* right() { return inputs_[1]; }
790 Token::Value op() const { return hydrogen()->op(); }
792 DECLARE_CONCRETE_INSTRUCTION(BitS, "bit-s")
793 DECLARE_HYDROGEN_ACCESSOR(Bitwise)
797 class LBranch final : public LControlInstruction<1, 2> {
799 explicit LBranch(LOperand* value, LOperand *temp1, LOperand *temp2) {
805 LOperand* value() { return inputs_[0]; }
806 LOperand* temp1() { return temps_[0]; }
807 LOperand* temp2() { return temps_[1]; }
809 DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
810 DECLARE_HYDROGEN_ACCESSOR(Branch)
812 void PrintDataTo(StringStream* stream) override;
816 class LCallJSFunction final : public LTemplateInstruction<1, 1, 0> {
818 explicit LCallJSFunction(LOperand* function) {
819 inputs_[0] = function;
822 LOperand* function() { return inputs_[0]; }
824 DECLARE_CONCRETE_INSTRUCTION(CallJSFunction, "call-js-function")
825 DECLARE_HYDROGEN_ACCESSOR(CallJSFunction)
827 void PrintDataTo(StringStream* stream) override;
829 int arity() const { return hydrogen()->argument_count() - 1; }
833 class LCallFunction final : public LTemplateInstruction<1, 2, 2> {
835 LCallFunction(LOperand* context, LOperand* function, LOperand* slot,
837 inputs_[0] = context;
838 inputs_[1] = function;
843 LOperand* context() { return inputs_[0]; }
844 LOperand* function() { return inputs_[1]; }
845 LOperand* temp_slot() { return temps_[0]; }
846 LOperand* temp_vector() { return temps_[1]; }
848 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
849 DECLARE_HYDROGEN_ACCESSOR(CallFunction)
851 int arity() const { return hydrogen()->argument_count() - 1; }
852 void PrintDataTo(StringStream* stream) override;
856 class LCallNew final : public LTemplateInstruction<1, 2, 0> {
858 LCallNew(LOperand* context, LOperand* constructor) {
859 inputs_[0] = context;
860 inputs_[1] = constructor;
863 LOperand* context() { return inputs_[0]; }
864 LOperand* constructor() { return inputs_[1]; }
866 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
867 DECLARE_HYDROGEN_ACCESSOR(CallNew)
869 void PrintDataTo(StringStream* stream) override;
871 int arity() const { return hydrogen()->argument_count() - 1; }
875 class LCallNewArray final : public LTemplateInstruction<1, 2, 0> {
877 LCallNewArray(LOperand* context, LOperand* constructor) {
878 inputs_[0] = context;
879 inputs_[1] = constructor;
882 LOperand* context() { return inputs_[0]; }
883 LOperand* constructor() { return inputs_[1]; }
885 DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
886 DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
888 void PrintDataTo(StringStream* stream) override;
890 int arity() const { return hydrogen()->argument_count() - 1; }
894 class LCallRuntime final : public LTemplateInstruction<1, 1, 0> {
896 explicit LCallRuntime(LOperand* context) {
897 inputs_[0] = context;
900 LOperand* context() { return inputs_[0]; }
902 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
903 DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
905 bool ClobbersDoubleRegisters(Isolate* isolate) const override {
906 return save_doubles() == kDontSaveFPRegs;
909 const Runtime::Function* function() const { return hydrogen()->function(); }
910 int arity() const { return hydrogen()->argument_count(); }
911 SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); }
915 class LCallStub final : public LTemplateInstruction<1, 1, 0> {
917 explicit LCallStub(LOperand* context) {
918 inputs_[0] = context;
921 LOperand* context() { return inputs_[0]; }
923 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
924 DECLARE_HYDROGEN_ACCESSOR(CallStub)
928 class LCheckArrayBufferNotNeutered final
929 : public LTemplateInstruction<0, 1, 0> {
931 explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; }
933 LOperand* view() { return inputs_[0]; }
935 DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
936 "check-array-buffer-not-neutered")
937 DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
941 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 1> {
943 explicit LCheckInstanceType(LOperand* value, LOperand* temp) {
948 LOperand* value() { return inputs_[0]; }
949 LOperand* temp() { return temps_[0]; }
951 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
952 DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
956 class LCheckMaps final : public LTemplateInstruction<0, 1, 1> {
958 explicit LCheckMaps(LOperand* value = NULL, LOperand* temp = NULL) {
963 LOperand* value() { return inputs_[0]; }
964 LOperand* temp() { return temps_[0]; }
966 DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
967 DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
971 class LCheckNonSmi final : public LTemplateInstruction<0, 1, 0> {
973 explicit LCheckNonSmi(LOperand* value) {
977 LOperand* value() { return inputs_[0]; }
979 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
980 DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject)
984 class LCheckSmi final : public LTemplateInstruction<1, 1, 0> {
986 explicit LCheckSmi(LOperand* value) {
990 LOperand* value() { return inputs_[0]; }
992 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
996 class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
998 explicit LCheckValue(LOperand* value) {
1002 LOperand* value() { return inputs_[0]; }
1004 DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value")
1005 DECLARE_HYDROGEN_ACCESSOR(CheckValue)
1009 class LClampDToUint8 final : public LTemplateInstruction<1, 1, 0> {
1011 explicit LClampDToUint8(LOperand* unclamped) {
1012 inputs_[0] = unclamped;
1015 LOperand* unclamped() { return inputs_[0]; }
1017 DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
1021 class LClampIToUint8 final : public LTemplateInstruction<1, 1, 0> {
1023 explicit LClampIToUint8(LOperand* unclamped) {
1024 inputs_[0] = unclamped;
1027 LOperand* unclamped() { return inputs_[0]; }
1029 DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
1033 class LClampTToUint8 final : public LTemplateInstruction<1, 1, 1> {
1035 LClampTToUint8(LOperand* unclamped, LOperand* temp1) {
1036 inputs_[0] = unclamped;
1040 LOperand* unclamped() { return inputs_[0]; }
1041 LOperand* temp1() { return temps_[0]; }
1043 DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
1047 class LDoubleBits final : public LTemplateInstruction<1, 1, 0> {
1049 explicit LDoubleBits(LOperand* value) {
1053 LOperand* value() { return inputs_[0]; }
1055 DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
1056 DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
1060 class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
1062 LConstructDouble(LOperand* hi, LOperand* lo) {
1067 LOperand* hi() { return inputs_[0]; }
1068 LOperand* lo() { return inputs_[1]; }
1070 DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
1074 class LClassOfTestAndBranch final : public LControlInstruction<1, 2> {
1076 LClassOfTestAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
1082 LOperand* value() { return inputs_[0]; }
1083 LOperand* temp1() { return temps_[0]; }
1084 LOperand* temp2() { return temps_[1]; }
1086 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
1087 "class-of-test-and-branch")
1088 DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
1090 void PrintDataTo(StringStream* stream) override;
1094 class LCmpHoleAndBranchD final : public LControlInstruction<1, 1> {
1096 explicit LCmpHoleAndBranchD(LOperand* object, LOperand* temp) {
1097 inputs_[0] = object;
1101 LOperand* object() { return inputs_[0]; }
1102 LOperand* temp() { return temps_[0]; }
1104 DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchD, "cmp-hole-and-branch-d")
1105 DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
1109 class LCmpHoleAndBranchT final : public LControlInstruction<1, 0> {
1111 explicit LCmpHoleAndBranchT(LOperand* object) {
1112 inputs_[0] = object;
1115 LOperand* object() { return inputs_[0]; }
1117 DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchT, "cmp-hole-and-branch-t")
1118 DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
1122 class LCmpMapAndBranch final : public LControlInstruction<1, 1> {
1124 LCmpMapAndBranch(LOperand* value, LOperand* temp) {
1129 LOperand* value() { return inputs_[0]; }
1130 LOperand* temp() { return temps_[0]; }
1132 DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
1133 DECLARE_HYDROGEN_ACCESSOR(CompareMap)
1135 Handle<Map> map() const { return hydrogen()->map().handle(); }
1139 class LCmpObjectEqAndBranch final : public LControlInstruction<2, 0> {
1141 LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
1146 LOperand* left() { return inputs_[0]; }
1147 LOperand* right() { return inputs_[1]; }
1149 DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
1150 DECLARE_HYDROGEN_ACCESSOR(CompareObjectEqAndBranch)
1154 class LCmpT final : public LTemplateInstruction<1, 3, 0> {
1156 LCmpT(LOperand* context, LOperand* left, LOperand* right) {
1157 inputs_[0] = context;
1162 LOperand* context() { return inputs_[0]; }
1163 LOperand* left() { return inputs_[1]; }
1164 LOperand* right() { return inputs_[2]; }
1166 DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
1167 DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
1169 Strength strength() { return hydrogen()->strength(); }
1171 Token::Value op() const { return hydrogen()->token(); }
1175 class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 1> {
1177 LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
1182 LOperand* value() { return inputs_[0]; }
1183 LOperand* temp() { return temps_[0]; }
1185 DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
1186 "cmp-minus-zero-and-branch")
1187 DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
1191 class LCompareNumericAndBranch final : public LControlInstruction<2, 0> {
1193 LCompareNumericAndBranch(LOperand* left, LOperand* right) {
1198 LOperand* left() { return inputs_[0]; }
1199 LOperand* right() { return inputs_[1]; }
1201 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
1202 "compare-numeric-and-branch")
1203 DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
1205 Token::Value op() const { return hydrogen()->token(); }
1206 bool is_double() const {
1207 return hydrogen()->representation().IsDouble();
1210 void PrintDataTo(StringStream* stream) override;
1214 class LConstantD final : public LTemplateInstruction<1, 0, 0> {
1216 DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
1217 DECLARE_HYDROGEN_ACCESSOR(Constant)
1219 double value() const { return hydrogen()->DoubleValue(); }
1223 class LConstantE final : public LTemplateInstruction<1, 0, 0> {
1225 DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
1226 DECLARE_HYDROGEN_ACCESSOR(Constant)
1228 ExternalReference value() const {
1229 return hydrogen()->ExternalReferenceValue();
1234 class LConstantI final : public LTemplateInstruction<1, 0, 0> {
1236 DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
1237 DECLARE_HYDROGEN_ACCESSOR(Constant)
1239 int32_t value() const { return hydrogen()->Integer32Value(); }
1243 class LConstantS final : public LTemplateInstruction<1, 0, 0> {
1245 DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
1246 DECLARE_HYDROGEN_ACCESSOR(Constant)
1248 Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
1252 class LConstantT final : public LTemplateInstruction<1, 0, 0> {
1254 DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
1255 DECLARE_HYDROGEN_ACCESSOR(Constant)
1257 Handle<Object> value(Isolate* isolate) const {
1258 return hydrogen()->handle(isolate);
1263 class LContext final : public LTemplateInstruction<1, 0, 0> {
1265 DECLARE_CONCRETE_INSTRUCTION(Context, "context")
1266 DECLARE_HYDROGEN_ACCESSOR(Context)
1270 class LDateField final : public LTemplateInstruction<1, 1, 0> {
1272 LDateField(LOperand* date, Smi* index) : index_(index) {
1276 LOperand* date() { return inputs_[0]; }
1277 Smi* index() const { return index_; }
1279 DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
1280 DECLARE_HYDROGEN_ACCESSOR(DateField)
1287 class LDebugBreak final : public LTemplateInstruction<0, 0, 0> {
1289 DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break")
1293 class LDeclareGlobals final : public LTemplateInstruction<0, 1, 0> {
1295 explicit LDeclareGlobals(LOperand* context) {
1296 inputs_[0] = context;
1299 LOperand* context() { return inputs_[0]; }
1301 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
1302 DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
1306 class LDeoptimize final : public LTemplateInstruction<0, 0, 0> {
1308 bool IsControl() const override { return true; }
1309 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
1310 DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
1314 class LDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
1316 LDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
1317 inputs_[0] = dividend;
1321 LOperand* dividend() { return inputs_[0]; }
1322 int32_t divisor() const { return divisor_; }
1324 DECLARE_CONCRETE_INSTRUCTION(DivByPowerOf2I, "div-by-power-of-2-i")
1325 DECLARE_HYDROGEN_ACCESSOR(Div)
1332 class LDivByConstI final : public LTemplateInstruction<1, 1, 1> {
1334 LDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
1335 inputs_[0] = dividend;
1340 LOperand* dividend() { return inputs_[0]; }
1341 int32_t divisor() const { return divisor_; }
1342 LOperand* temp() { return temps_[0]; }
1344 DECLARE_CONCRETE_INSTRUCTION(DivByConstI, "div-by-const-i")
1345 DECLARE_HYDROGEN_ACCESSOR(Div)
1352 class LDivI final : public LTemplateInstruction<1, 2, 1> {
1354 LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
1355 inputs_[0] = dividend;
1356 inputs_[1] = divisor;
1360 LOperand* dividend() { return inputs_[0]; }
1361 LOperand* divisor() { return inputs_[1]; }
1362 LOperand* temp() { return temps_[0]; }
1364 DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
1365 DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
1369 class LDoubleToIntOrSmi final : public LTemplateInstruction<1, 1, 0> {
1371 explicit LDoubleToIntOrSmi(LOperand* value) {
1375 LOperand* value() { return inputs_[0]; }
1377 DECLARE_CONCRETE_INSTRUCTION(DoubleToIntOrSmi, "double-to-int-or-smi")
1378 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
1380 bool tag_result() { return hydrogen()->representation().IsSmi(); }
1384 class LForInCacheArray final : public LTemplateInstruction<1, 1, 0> {
1386 explicit LForInCacheArray(LOperand* map) {
1390 LOperand* map() { return inputs_[0]; }
1392 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
1395 return HForInCacheArray::cast(this->hydrogen_value())->idx();
1400 class LForInPrepareMap final : public LTemplateInstruction<1, 2, 0> {
1402 LForInPrepareMap(LOperand* context, LOperand* object) {
1403 inputs_[0] = context;
1404 inputs_[1] = object;
1407 LOperand* context() { return inputs_[0]; }
1408 LOperand* object() { return inputs_[1]; }
1410 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
1414 class LGetCachedArrayIndex final : public LTemplateInstruction<1, 1, 0> {
1416 explicit LGetCachedArrayIndex(LOperand* value) {
1420 LOperand* value() { return inputs_[0]; }
1422 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
1423 DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
1427 class LHasCachedArrayIndexAndBranch final : public LControlInstruction<1, 1> {
1429 LHasCachedArrayIndexAndBranch(LOperand* value, LOperand* temp) {
1434 LOperand* value() { return inputs_[0]; }
1435 LOperand* temp() { return temps_[0]; }
1437 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
1438 "has-cached-array-index-and-branch")
1439 DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndexAndBranch)
1441 void PrintDataTo(StringStream* stream) override;
1445 class LHasInstanceTypeAndBranch final : public LControlInstruction<1, 1> {
1447 LHasInstanceTypeAndBranch(LOperand* value, LOperand* temp) {
1452 LOperand* value() { return inputs_[0]; }
1453 LOperand* temp() { return temps_[0]; }
1455 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
1456 "has-instance-type-and-branch")
1457 DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
1459 void PrintDataTo(StringStream* stream) override;
1463 class LInnerAllocatedObject final : public LTemplateInstruction<1, 2, 0> {
1465 LInnerAllocatedObject(LOperand* base_object, LOperand* offset) {
1466 inputs_[0] = base_object;
1467 inputs_[1] = offset;
1470 LOperand* base_object() const { return inputs_[0]; }
1471 LOperand* offset() const { return inputs_[1]; }
1473 void PrintDataTo(StringStream* stream) override;
1475 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object")
1479 class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
1481 LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
1482 inputs_[0] = context;
1487 LOperand* context() const { return inputs_[0]; }
1488 LOperand* left() const { return inputs_[1]; }
1489 LOperand* right() const { return inputs_[2]; }
1491 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
1495 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 1> {
1497 LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype,
1498 LOperand* scratch) {
1499 inputs_[0] = object;
1500 inputs_[1] = prototype;
1501 temps_[0] = scratch;
1504 LOperand* object() const { return inputs_[0]; }
1505 LOperand* prototype() const { return inputs_[1]; }
1506 LOperand* scratch() const { return temps_[0]; }
1508 DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch,
1509 "has-in-prototype-chain-and-branch")
1510 DECLARE_HYDROGEN_ACCESSOR(HasInPrototypeChainAndBranch)
1514 class LInteger32ToDouble final : public LTemplateInstruction<1, 1, 0> {
1516 explicit LInteger32ToDouble(LOperand* value) {
1520 LOperand* value() { return inputs_[0]; }
1522 DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
1526 class LCallWithDescriptor final : public LTemplateResultInstruction<1> {
1528 LCallWithDescriptor(CallInterfaceDescriptor descriptor,
1529 const ZoneList<LOperand*>& operands, Zone* zone)
1530 : descriptor_(descriptor),
1531 inputs_(descriptor.GetRegisterParameterCount() +
1532 kImplicitRegisterParameterCount,
1534 DCHECK(descriptor.GetRegisterParameterCount() +
1535 kImplicitRegisterParameterCount ==
1537 inputs_.AddAll(operands, zone);
1540 LOperand* target() const { return inputs_[0]; }
1542 CallInterfaceDescriptor descriptor() { return descriptor_; }
1544 DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)
1546 // The target and context are passed as implicit parameters that are not
1547 // explicitly listed in the descriptor.
1548 static const int kImplicitRegisterParameterCount = 2;
1551 DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
1553 void PrintDataTo(StringStream* stream) override;
1555 int arity() const { return hydrogen()->argument_count() - 1; }
1557 CallInterfaceDescriptor descriptor_;
1558 ZoneList<LOperand*> inputs_;
1560 // Iterator support.
1561 int InputCount() final { return inputs_.length(); }
1562 LOperand* InputAt(int i) final { return inputs_[i]; }
1564 int TempCount() final { return 0; }
1565 LOperand* TempAt(int i) final { return NULL; }
1569 class LInvokeFunction final : public LTemplateInstruction<1, 2, 0> {
1571 LInvokeFunction(LOperand* context, LOperand* function) {
1572 inputs_[0] = context;
1573 inputs_[1] = function;
1576 LOperand* context() { return inputs_[0]; }
1577 LOperand* function() { return inputs_[1]; }
1579 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
1580 DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
1582 void PrintDataTo(StringStream* stream) override;
1584 int arity() const { return hydrogen()->argument_count() - 1; }
1588 class LIsConstructCallAndBranch final : public LControlInstruction<0, 2> {
1590 LIsConstructCallAndBranch(LOperand* temp1, LOperand* temp2) {
1595 LOperand* temp1() { return temps_[0]; }
1596 LOperand* temp2() { return temps_[1]; }
1598 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
1599 "is-construct-call-and-branch")
1603 class LIsStringAndBranch final : public LControlInstruction<1, 1> {
1605 LIsStringAndBranch(LOperand* value, LOperand* temp) {
1610 LOperand* value() { return inputs_[0]; }
1611 LOperand* temp() { return temps_[0]; }
1613 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
1614 DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
1616 void PrintDataTo(StringStream* stream) override;
1620 class LIsSmiAndBranch final : public LControlInstruction<1, 0> {
1622 explicit LIsSmiAndBranch(LOperand* value) {
1626 LOperand* value() { return inputs_[0]; }
1628 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
1629 DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
1631 void PrintDataTo(StringStream* stream) override;
1635 class LIsUndetectableAndBranch final : public LControlInstruction<1, 1> {
1637 explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
1642 LOperand* value() { return inputs_[0]; }
1643 LOperand* temp() { return temps_[0]; }
1645 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
1646 "is-undetectable-and-branch")
1647 DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
1649 void PrintDataTo(StringStream* stream) override;
1653 class LLoadGlobalViaContext final : public LTemplateInstruction<1, 1, 1> {
1655 explicit LLoadGlobalViaContext(LOperand* context) { inputs_[0] = context; }
1657 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalViaContext, "load-global-via-context")
1658 DECLARE_HYDROGEN_ACCESSOR(LoadGlobalViaContext)
1660 void PrintDataTo(StringStream* stream) override;
1662 LOperand* context() { return inputs_[0]; }
1664 int depth() const { return hydrogen()->depth(); }
1665 int slot_index() const { return hydrogen()->slot_index(); }
1669 class LLoadContextSlot final : public LTemplateInstruction<1, 1, 0> {
1671 explicit LLoadContextSlot(LOperand* context) {
1672 inputs_[0] = context;
1675 LOperand* context() { return inputs_[0]; }
1677 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
1678 DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
1680 int slot_index() const { return hydrogen()->slot_index(); }
1682 void PrintDataTo(StringStream* stream) override;
1686 class LLoadNamedField final : public LTemplateInstruction<1, 1, 0> {
1688 explicit LLoadNamedField(LOperand* object) {
1689 inputs_[0] = object;
1692 LOperand* object() { return inputs_[0]; }
1694 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
1695 DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
1699 class LLoadFunctionPrototype final : public LTemplateInstruction<1, 1, 1> {
1701 LLoadFunctionPrototype(LOperand* function, LOperand* temp) {
1702 inputs_[0] = function;
1706 LOperand* function() { return inputs_[0]; }
1707 LOperand* temp() { return temps_[0]; }
1709 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
1710 DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
1714 class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
1716 LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
1718 inputs_[0] = context;
1719 inputs_[1] = global_object;
1723 LOperand* context() { return inputs_[0]; }
1724 LOperand* global_object() { return inputs_[1]; }
1725 LOperand* temp_vector() { return temps_[0]; }
1727 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
1728 DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
1730 Handle<Object> name() const { return hydrogen()->name(); }
1731 TypeofMode typeof_mode() const { return hydrogen()->typeof_mode(); }
1736 class LLoadKeyed : public LTemplateInstruction<1, 2, T> {
1738 LLoadKeyed(LOperand* elements, LOperand* key) {
1739 this->inputs_[0] = elements;
1740 this->inputs_[1] = key;
1743 LOperand* elements() { return this->inputs_[0]; }
1744 LOperand* key() { return this->inputs_[1]; }
1745 ElementsKind elements_kind() const {
1746 return this->hydrogen()->elements_kind();
1748 bool is_external() const {
1749 return this->hydrogen()->is_external();
1751 bool is_fixed_typed_array() const {
1752 return hydrogen()->is_fixed_typed_array();
1754 bool is_typed_elements() const {
1755 return is_external() || is_fixed_typed_array();
1757 uint32_t base_offset() const {
1758 return this->hydrogen()->base_offset();
1760 void PrintDataTo(StringStream* stream) override {
1761 this->elements()->PrintTo(stream);
1763 this->key()->PrintTo(stream);
1764 if (this->base_offset() != 0) {
1765 stream->Add(" + %d]", this->base_offset());
1771 DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
1775 class LLoadKeyedExternal: public LLoadKeyed<1> {
1777 LLoadKeyedExternal(LOperand* elements, LOperand* key, LOperand* temp) :
1778 LLoadKeyed<1>(elements, key) {
1782 LOperand* temp() { return temps_[0]; }
1784 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedExternal, "load-keyed-external");
1788 class LLoadKeyedFixed: public LLoadKeyed<1> {
1790 LLoadKeyedFixed(LOperand* elements, LOperand* key, LOperand* temp) :
1791 LLoadKeyed<1>(elements, key) {
1795 LOperand* temp() { return temps_[0]; }
1797 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixed, "load-keyed-fixed");
1801 class LLoadKeyedFixedDouble: public LLoadKeyed<1> {
1803 LLoadKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* temp) :
1804 LLoadKeyed<1>(elements, key) {
1808 LOperand* temp() { return temps_[0]; }
1810 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixedDouble, "load-keyed-fixed-double");
1814 class LLoadKeyedGeneric final : public LTemplateInstruction<1, 3, 1> {
1816 LLoadKeyedGeneric(LOperand* context, LOperand* object, LOperand* key,
1818 inputs_[0] = context;
1819 inputs_[1] = object;
1824 LOperand* context() { return inputs_[0]; }
1825 LOperand* object() { return inputs_[1]; }
1826 LOperand* key() { return inputs_[2]; }
1827 LOperand* temp_vector() { return temps_[0]; }
1829 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
1830 DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
1834 class LLoadNamedGeneric final : public LTemplateInstruction<1, 2, 1> {
1836 LLoadNamedGeneric(LOperand* context, LOperand* object, LOperand* vector) {
1837 inputs_[0] = context;
1838 inputs_[1] = object;
1842 LOperand* context() { return inputs_[0]; }
1843 LOperand* object() { return inputs_[1]; }
1844 LOperand* temp_vector() { return temps_[0]; }
1846 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
1847 DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
1849 Handle<Object> name() const { return hydrogen()->name(); }
1853 class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
1855 DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root")
1856 DECLARE_HYDROGEN_ACCESSOR(LoadRoot)
1858 Heap::RootListIndex index() const { return hydrogen()->index(); }
1862 class LMapEnumLength final : public LTemplateInstruction<1, 1, 0> {
1864 explicit LMapEnumLength(LOperand* value) {
1868 LOperand* value() { return inputs_[0]; }
1870 DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length")
1875 class LUnaryMathOperation : public LTemplateInstruction<1, 1, T> {
1877 explicit LUnaryMathOperation(LOperand* value) {
1878 this->inputs_[0] = value;
1881 LOperand* value() { return this->inputs_[0]; }
1882 BuiltinFunctionId op() const { return this->hydrogen()->op(); }
1884 void PrintDataTo(StringStream* stream) override;
1886 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
1890 class LMathAbs final : public LUnaryMathOperation<0> {
1892 explicit LMathAbs(LOperand* value) : LUnaryMathOperation<0>(value) {}
1894 DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs")
1898 class LMathAbsTagged: public LTemplateInstruction<1, 2, 3> {
1900 LMathAbsTagged(LOperand* context, LOperand* value,
1901 LOperand* temp1, LOperand* temp2, LOperand* temp3) {
1902 inputs_[0] = context;
1909 LOperand* context() { return inputs_[0]; }
1910 LOperand* value() { return inputs_[1]; }
1911 LOperand* temp1() { return temps_[0]; }
1912 LOperand* temp2() { return temps_[1]; }
1913 LOperand* temp3() { return temps_[2]; }
1915 DECLARE_CONCRETE_INSTRUCTION(MathAbsTagged, "math-abs-tagged")
1916 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
1920 class LMathExp final : public LUnaryMathOperation<4> {
1922 LMathExp(LOperand* value,
1923 LOperand* double_temp1,
1927 : LUnaryMathOperation<4>(value) {
1928 temps_[0] = double_temp1;
1932 ExternalReference::InitializeMathExpData();
1935 LOperand* double_temp1() { return temps_[0]; }
1936 LOperand* temp1() { return temps_[1]; }
1937 LOperand* temp2() { return temps_[2]; }
1938 LOperand* temp3() { return temps_[3]; }
1940 DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
1944 // Math.floor with a double result.
1945 class LMathFloorD final : public LUnaryMathOperation<0> {
1947 explicit LMathFloorD(LOperand* value) : LUnaryMathOperation<0>(value) { }
1948 DECLARE_CONCRETE_INSTRUCTION(MathFloorD, "math-floor-d")
1952 // Math.floor with an integer result.
1953 class LMathFloorI final : public LUnaryMathOperation<0> {
1955 explicit LMathFloorI(LOperand* value) : LUnaryMathOperation<0>(value) { }
1956 DECLARE_CONCRETE_INSTRUCTION(MathFloorI, "math-floor-i")
1960 class LFlooringDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
1962 LFlooringDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
1963 inputs_[0] = dividend;
1967 LOperand* dividend() { return inputs_[0]; }
1968 int32_t divisor() const { return divisor_; }
1970 DECLARE_CONCRETE_INSTRUCTION(FlooringDivByPowerOf2I,
1971 "flooring-div-by-power-of-2-i")
1972 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
1979 class LFlooringDivByConstI final : public LTemplateInstruction<1, 1, 2> {
1981 LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
1982 inputs_[0] = dividend;
1987 LOperand* dividend() { return inputs_[0]; }
1988 int32_t divisor() const { return divisor_; }
1989 LOperand* temp() { return temps_[0]; }
1991 DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
1992 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
1999 class LFlooringDivI final : public LTemplateInstruction<1, 2, 1> {
2001 LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
2002 inputs_[0] = dividend;
2003 inputs_[1] = divisor;
2007 LOperand* dividend() { return inputs_[0]; }
2008 LOperand* divisor() { return inputs_[1]; }
2009 LOperand* temp() { return temps_[0]; }
2011 DECLARE_CONCRETE_INSTRUCTION(FlooringDivI, "flooring-div-i")
2012 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
2016 class LMathLog final : public LUnaryMathOperation<0> {
2018 explicit LMathLog(LOperand* value) : LUnaryMathOperation<0>(value) { }
2019 DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
2023 class LMathClz32 final : public LUnaryMathOperation<0> {
2025 explicit LMathClz32(LOperand* value) : LUnaryMathOperation<0>(value) { }
2026 DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
2030 class LMathMinMax final : public LTemplateInstruction<1, 2, 0> {
2032 LMathMinMax(LOperand* left, LOperand* right) {
2037 LOperand* left() { return inputs_[0]; }
2038 LOperand* right() { return inputs_[1]; }
2040 DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max")
2041 DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
2045 class LMathPowHalf final : public LUnaryMathOperation<0> {
2047 explicit LMathPowHalf(LOperand* value) : LUnaryMathOperation<0>(value) { }
2048 DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half")
2052 // Math.round with an integer result.
2053 class LMathRoundD final : public LUnaryMathOperation<0> {
2055 explicit LMathRoundD(LOperand* value)
2056 : LUnaryMathOperation<0>(value) {
2059 DECLARE_CONCRETE_INSTRUCTION(MathRoundD, "math-round-d")
2063 // Math.round with an integer result.
2064 class LMathRoundI final : public LUnaryMathOperation<1> {
2066 LMathRoundI(LOperand* value, LOperand* temp1)
2067 : LUnaryMathOperation<1>(value) {
2071 LOperand* temp1() { return temps_[0]; }
2073 DECLARE_CONCRETE_INSTRUCTION(MathRoundI, "math-round-i")
2077 class LMathFround final : public LUnaryMathOperation<0> {
2079 explicit LMathFround(LOperand* value) : LUnaryMathOperation<0>(value) {}
2081 DECLARE_CONCRETE_INSTRUCTION(MathFround, "math-fround")
2085 class LMathSqrt final : public LUnaryMathOperation<0> {
2087 explicit LMathSqrt(LOperand* value) : LUnaryMathOperation<0>(value) { }
2088 DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt")
2092 class LModByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
2094 LModByPowerOf2I(LOperand* dividend, int32_t divisor) {
2095 inputs_[0] = dividend;
2099 LOperand* dividend() { return inputs_[0]; }
2100 int32_t divisor() const { return divisor_; }
2102 DECLARE_CONCRETE_INSTRUCTION(ModByPowerOf2I, "mod-by-power-of-2-i")
2103 DECLARE_HYDROGEN_ACCESSOR(Mod)
2110 class LModByConstI final : public LTemplateInstruction<1, 1, 1> {
2112 LModByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
2113 inputs_[0] = dividend;
2118 LOperand* dividend() { return inputs_[0]; }
2119 int32_t divisor() const { return divisor_; }
2120 LOperand* temp() { return temps_[0]; }
2122 DECLARE_CONCRETE_INSTRUCTION(ModByConstI, "mod-by-const-i")
2123 DECLARE_HYDROGEN_ACCESSOR(Mod)
2130 class LModI final : public LTemplateInstruction<1, 2, 0> {
2132 LModI(LOperand* left, LOperand* right) {
2137 LOperand* left() { return inputs_[0]; }
2138 LOperand* right() { return inputs_[1]; }
2140 DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
2141 DECLARE_HYDROGEN_ACCESSOR(Mod)
2145 class LMulConstIS final : public LTemplateInstruction<1, 2, 0> {
2147 LMulConstIS(LOperand* left, LConstantOperand* right) {
2152 LOperand* left() { return inputs_[0]; }
2153 LConstantOperand* right() { return LConstantOperand::cast(inputs_[1]); }
2155 DECLARE_CONCRETE_INSTRUCTION(MulConstIS, "mul-const-i-s")
2156 DECLARE_HYDROGEN_ACCESSOR(Mul)
2160 class LMulI final : public LTemplateInstruction<1, 2, 0> {
2162 LMulI(LOperand* left, LOperand* right) {
2167 LOperand* left() { return inputs_[0]; }
2168 LOperand* right() { return inputs_[1]; }
2170 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
2171 DECLARE_HYDROGEN_ACCESSOR(Mul)
2175 class LMulS final : public LTemplateInstruction<1, 2, 0> {
2177 LMulS(LOperand* left, LOperand* right) {
2182 LOperand* left() { return inputs_[0]; }
2183 LOperand* right() { return inputs_[1]; }
2185 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-s")
2186 DECLARE_HYDROGEN_ACCESSOR(Mul)
2190 class LNumberTagD final : public LTemplateInstruction<1, 1, 2> {
2192 LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2) {
2198 LOperand* value() { return inputs_[0]; }
2199 LOperand* temp1() { return temps_[0]; }
2200 LOperand* temp2() { return temps_[1]; }
2202 DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
2203 DECLARE_HYDROGEN_ACCESSOR(Change)
2207 class LNumberTagU final : public LTemplateInstruction<1, 1, 2> {
2209 explicit LNumberTagU(LOperand* value,
2217 LOperand* value() { return inputs_[0]; }
2218 LOperand* temp1() { return temps_[0]; }
2219 LOperand* temp2() { return temps_[1]; }
2221 DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
2225 class LNumberUntagD final : public LTemplateInstruction<1, 1, 1> {
2227 LNumberUntagD(LOperand* value, LOperand* temp) {
2232 LOperand* value() { return inputs_[0]; }
2234 LOperand* temp() { return temps_[0]; }
2236 DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
2237 DECLARE_HYDROGEN_ACCESSOR(Change)
2241 class LParameter final : public LTemplateInstruction<1, 0, 0> {
2243 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
2244 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2248 class LPower final : public LTemplateInstruction<1, 2, 0> {
2250 LPower(LOperand* left, LOperand* right) {
2255 LOperand* left() { return inputs_[0]; }
2256 LOperand* right() { return inputs_[1]; }
2258 DECLARE_CONCRETE_INSTRUCTION(Power, "power")
2259 DECLARE_HYDROGEN_ACCESSOR(Power)
2263 class LPreparePushArguments final : public LTemplateInstruction<0, 0, 0> {
2265 explicit LPreparePushArguments(int argc) : argc_(argc) {}
2267 inline int argc() const { return argc_; }
2269 DECLARE_CONCRETE_INSTRUCTION(PreparePushArguments, "prepare-push-arguments")
2276 class LPushArguments final : public LTemplateResultInstruction<0> {
2278 explicit LPushArguments(Zone* zone,
2279 int capacity = kRecommendedMaxPushedArgs)
2280 : zone_(zone), inputs_(capacity, zone) {}
2282 LOperand* argument(int i) { return inputs_[i]; }
2283 int ArgumentCount() const { return inputs_.length(); }
2285 void AddArgument(LOperand* arg) { inputs_.Add(arg, zone_); }
2287 DECLARE_CONCRETE_INSTRUCTION(PushArguments, "push-arguments")
2289 // It is better to limit the number of arguments pushed simultaneously to
2290 // avoid pressure on the register allocator.
2291 static const int kRecommendedMaxPushedArgs = 4;
2292 bool ShouldSplitPush() const {
2293 return inputs_.length() >= kRecommendedMaxPushedArgs;
2298 ZoneList<LOperand*> inputs_;
2301 // Iterator support.
2302 int InputCount() final { return inputs_.length(); }
2303 LOperand* InputAt(int i) final { return inputs_[i]; }
2305 int TempCount() final { return 0; }
2306 LOperand* TempAt(int i) final { return NULL; }
2310 class LRegExpLiteral final : public LTemplateInstruction<1, 1, 0> {
2312 explicit LRegExpLiteral(LOperand* context) {
2313 inputs_[0] = context;
2316 LOperand* context() { return inputs_[0]; }
2318 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
2319 DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
2323 class LReturn final : public LTemplateInstruction<0, 3, 0> {
2325 LReturn(LOperand* value, LOperand* context, LOperand* parameter_count) {
2327 inputs_[1] = context;
2328 inputs_[2] = parameter_count;
2331 LOperand* value() { return inputs_[0]; }
2332 LOperand* parameter_count() { return inputs_[2]; }
2334 bool has_constant_parameter_count() {
2335 return parameter_count()->IsConstantOperand();
2337 LConstantOperand* constant_parameter_count() {
2338 DCHECK(has_constant_parameter_count());
2339 return LConstantOperand::cast(parameter_count());
2342 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
2346 class LSeqStringGetChar final : public LTemplateInstruction<1, 2, 1> {
2348 LSeqStringGetChar(LOperand* string,
2351 inputs_[0] = string;
2356 LOperand* string() { return inputs_[0]; }
2357 LOperand* index() { return inputs_[1]; }
2358 LOperand* temp() { return temps_[0]; }
2360 DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char")
2361 DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar)
2365 class LSeqStringSetChar final : public LTemplateInstruction<1, 4, 1> {
2367 LSeqStringSetChar(LOperand* context,
2372 inputs_[0] = context;
2373 inputs_[1] = string;
2379 LOperand* context() { return inputs_[0]; }
2380 LOperand* string() { return inputs_[1]; }
2381 LOperand* index() { return inputs_[2]; }
2382 LOperand* value() { return inputs_[3]; }
2383 LOperand* temp() { return temps_[0]; }
2385 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
2386 DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
2390 class LSmiTag final : public LTemplateInstruction<1, 1, 0> {
2392 explicit LSmiTag(LOperand* value) {
2396 LOperand* value() { return inputs_[0]; }
2398 DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
2399 DECLARE_HYDROGEN_ACCESSOR(Change)
2403 class LSmiUntag final : public LTemplateInstruction<1, 1, 0> {
2405 LSmiUntag(LOperand* value, bool needs_check)
2406 : needs_check_(needs_check) {
2410 LOperand* value() { return inputs_[0]; }
2411 bool needs_check() const { return needs_check_; }
2413 DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
2420 class LStackCheck final : public LTemplateInstruction<0, 1, 0> {
2422 explicit LStackCheck(LOperand* context) {
2423 inputs_[0] = context;
2426 LOperand* context() { return inputs_[0]; }
2428 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
2429 DECLARE_HYDROGEN_ACCESSOR(StackCheck)
2431 Label* done_label() { return &done_label_; }
2438 class LStoreGlobalViaContext final : public LTemplateInstruction<0, 2, 0> {
2440 LStoreGlobalViaContext(LOperand* context, LOperand* value) {
2441 inputs_[0] = context;
2445 LOperand* context() { return inputs_[0]; }
2446 LOperand* value() { return inputs_[1]; }
2448 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalViaContext,
2449 "store-global-via-context")
2450 DECLARE_HYDROGEN_ACCESSOR(StoreGlobalViaContext)
2452 void PrintDataTo(StringStream* stream) override;
2454 int depth() { return hydrogen()->depth(); }
2455 int slot_index() { return hydrogen()->slot_index(); }
2456 LanguageMode language_mode() { return hydrogen()->language_mode(); }
2461 class LStoreKeyed : public LTemplateInstruction<0, 3, T> {
2463 LStoreKeyed(LOperand* elements, LOperand* key, LOperand* value) {
2464 this->inputs_[0] = elements;
2465 this->inputs_[1] = key;
2466 this->inputs_[2] = value;
2469 bool is_external() const { return this->hydrogen()->is_external(); }
2470 bool is_fixed_typed_array() const {
2471 return hydrogen()->is_fixed_typed_array();
2473 bool is_typed_elements() const {
2474 return is_external() || is_fixed_typed_array();
2476 LOperand* elements() { return this->inputs_[0]; }
2477 LOperand* key() { return this->inputs_[1]; }
2478 LOperand* value() { return this->inputs_[2]; }
2479 ElementsKind elements_kind() const {
2480 return this->hydrogen()->elements_kind();
2483 bool NeedsCanonicalization() {
2484 if (hydrogen()->value()->IsAdd() || hydrogen()->value()->IsSub() ||
2485 hydrogen()->value()->IsMul() || hydrogen()->value()->IsDiv()) {
2488 return this->hydrogen()->NeedsCanonicalization();
2490 uint32_t base_offset() const { return this->hydrogen()->base_offset(); }
2492 void PrintDataTo(StringStream* stream) override {
2493 this->elements()->PrintTo(stream);
2495 this->key()->PrintTo(stream);
2496 if (this->base_offset() != 0) {
2497 stream->Add(" + %d] <-", this->base_offset());
2499 stream->Add("] <- ");
2502 if (this->value() == NULL) {
2503 DCHECK(hydrogen()->IsConstantHoleStore() &&
2504 hydrogen()->value()->representation().IsDouble());
2505 stream->Add("<the hole(nan)>");
2507 this->value()->PrintTo(stream);
2511 DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
2515 class LStoreKeyedExternal final : public LStoreKeyed<1> {
2517 LStoreKeyedExternal(LOperand* elements, LOperand* key, LOperand* value,
2519 LStoreKeyed<1>(elements, key, value) {
2523 LOperand* temp() { return temps_[0]; }
2525 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedExternal, "store-keyed-external")
2529 class LStoreKeyedFixed final : public LStoreKeyed<1> {
2531 LStoreKeyedFixed(LOperand* elements, LOperand* key, LOperand* value,
2533 LStoreKeyed<1>(elements, key, value) {
2537 LOperand* temp() { return temps_[0]; }
2539 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixed, "store-keyed-fixed")
2543 class LStoreKeyedFixedDouble final : public LStoreKeyed<1> {
2545 LStoreKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* value,
2547 LStoreKeyed<1>(elements, key, value) {
2551 LOperand* temp() { return temps_[0]; }
2553 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixedDouble,
2554 "store-keyed-fixed-double")
2558 class LStoreKeyedGeneric final : public LTemplateInstruction<0, 4, 2> {
2560 LStoreKeyedGeneric(LOperand* context, LOperand* object, LOperand* key,
2561 LOperand* value, LOperand* slot, LOperand* vector) {
2562 inputs_[0] = context;
2563 inputs_[1] = object;
2570 LOperand* context() { return inputs_[0]; }
2571 LOperand* object() { return inputs_[1]; }
2572 LOperand* key() { return inputs_[2]; }
2573 LOperand* value() { return inputs_[3]; }
2574 LOperand* temp_slot() { return temps_[0]; }
2575 LOperand* temp_vector() { return temps_[1]; }
2577 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
2578 DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
2580 void PrintDataTo(StringStream* stream) override;
2582 LanguageMode language_mode() { return hydrogen()->language_mode(); }
2586 class LStoreNamedField final : public LTemplateInstruction<0, 2, 2> {
2588 LStoreNamedField(LOperand* object, LOperand* value,
2589 LOperand* temp0, LOperand* temp1) {
2590 inputs_[0] = object;
2596 LOperand* object() { return inputs_[0]; }
2597 LOperand* value() { return inputs_[1]; }
2598 LOperand* temp0() { return temps_[0]; }
2599 LOperand* temp1() { return temps_[1]; }
2601 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
2602 DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
2604 void PrintDataTo(StringStream* stream) override;
2606 Representation representation() const {
2607 return hydrogen()->field_representation();
2612 class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
2614 LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value,
2615 LOperand* slot, LOperand* vector) {
2616 inputs_[0] = context;
2617 inputs_[1] = object;
2623 LOperand* context() { return inputs_[0]; }
2624 LOperand* object() { return inputs_[1]; }
2625 LOperand* value() { return inputs_[2]; }
2626 LOperand* temp_slot() { return temps_[0]; }
2627 LOperand* temp_vector() { return temps_[1]; }
2629 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
2630 DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
2632 void PrintDataTo(StringStream* stream) override;
2634 Handle<Object> name() const { return hydrogen()->name(); }
2635 LanguageMode language_mode() { return hydrogen()->language_mode(); }
2639 class LMaybeGrowElements final : public LTemplateInstruction<1, 5, 0> {
2641 LMaybeGrowElements(LOperand* context, LOperand* object, LOperand* elements,
2642 LOperand* key, LOperand* current_capacity) {
2643 inputs_[0] = context;
2644 inputs_[1] = object;
2645 inputs_[2] = elements;
2647 inputs_[4] = current_capacity;
2650 LOperand* context() { return inputs_[0]; }
2651 LOperand* object() { return inputs_[1]; }
2652 LOperand* elements() { return inputs_[2]; }
2653 LOperand* key() { return inputs_[3]; }
2654 LOperand* current_capacity() { return inputs_[4]; }
2656 DECLARE_HYDROGEN_ACCESSOR(MaybeGrowElements)
2657 DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements, "maybe-grow-elements")
2661 class LStringAdd final : public LTemplateInstruction<1, 3, 0> {
2663 LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
2664 inputs_[0] = context;
2669 LOperand* context() { return inputs_[0]; }
2670 LOperand* left() { return inputs_[1]; }
2671 LOperand* right() { return inputs_[2]; }
2673 DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
2674 DECLARE_HYDROGEN_ACCESSOR(StringAdd)
2678 class LStringCharCodeAt final : public LTemplateInstruction<1, 3, 0> {
2680 LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
2681 inputs_[0] = context;
2682 inputs_[1] = string;
2686 LOperand* context() { return inputs_[0]; }
2687 LOperand* string() { return inputs_[1]; }
2688 LOperand* index() { return inputs_[2]; }
2690 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
2691 DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
2695 class LStringCharFromCode final : public LTemplateInstruction<1, 2, 0> {
2697 LStringCharFromCode(LOperand* context, LOperand* char_code) {
2698 inputs_[0] = context;
2699 inputs_[1] = char_code;
2702 LOperand* context() { return inputs_[0]; }
2703 LOperand* char_code() { return inputs_[1]; }
2705 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
2706 DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
2710 class LStringCompareAndBranch final : public LControlInstruction<3, 0> {
2712 LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) {
2713 inputs_[0] = context;
2718 LOperand* context() { return inputs_[0]; }
2719 LOperand* left() { return inputs_[1]; }
2720 LOperand* right() { return inputs_[2]; }
2722 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
2723 "string-compare-and-branch")
2724 DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
2726 Token::Value op() const { return hydrogen()->token(); }
2728 void PrintDataTo(StringStream* stream) override;
2732 // Truncating conversion from a tagged value to an int32.
2733 class LTaggedToI final : public LTemplateInstruction<1, 1, 2> {
2735 explicit LTaggedToI(LOperand* value, LOperand* temp1, LOperand* temp2) {
2741 LOperand* value() { return inputs_[0]; }
2742 LOperand* temp1() { return temps_[0]; }
2743 LOperand* temp2() { return temps_[1]; }
2745 DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
2746 DECLARE_HYDROGEN_ACCESSOR(Change)
2748 bool truncating() { return hydrogen()->CanTruncateToInt32(); }
2752 class LShiftI final : public LTemplateInstruction<1, 2, 0> {
2754 LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
2755 : op_(op), can_deopt_(can_deopt) {
2760 Token::Value op() const { return op_; }
2761 LOperand* left() { return inputs_[0]; }
2762 LOperand* right() { return inputs_[1]; }
2763 bool can_deopt() const { return can_deopt_; }
2765 DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")
2773 class LShiftS final : public LTemplateInstruction<1, 2, 0> {
2775 LShiftS(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
2776 : op_(op), can_deopt_(can_deopt) {
2781 Token::Value op() const { return op_; }
2782 LOperand* left() { return inputs_[0]; }
2783 LOperand* right() { return inputs_[1]; }
2784 bool can_deopt() const { return can_deopt_; }
2786 DECLARE_CONCRETE_INSTRUCTION(ShiftS, "shift-s")
2794 class LStoreCodeEntry final : public LTemplateInstruction<0, 2, 1> {
2796 LStoreCodeEntry(LOperand* function, LOperand* code_object,
2798 inputs_[0] = function;
2799 inputs_[1] = code_object;
2803 LOperand* function() { return inputs_[0]; }
2804 LOperand* code_object() { return inputs_[1]; }
2805 LOperand* temp() { return temps_[0]; }
2807 void PrintDataTo(StringStream* stream) override;
2809 DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
2810 DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
2814 class LStoreContextSlot final : public LTemplateInstruction<0, 2, 1> {
2816 LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
2817 inputs_[0] = context;
2822 LOperand* context() { return inputs_[0]; }
2823 LOperand* value() { return inputs_[1]; }
2824 LOperand* temp() { return temps_[0]; }
2826 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
2827 DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
2829 int slot_index() { return hydrogen()->slot_index(); }
2831 void PrintDataTo(StringStream* stream) override;
2835 class LSubI final : public LTemplateInstruction<1, 2, 0> {
2837 LSubI(LOperand* left, LOperand* right)
2838 : shift_(NO_SHIFT), shift_amount_(0) {
2843 LSubI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
2844 : shift_(shift), shift_amount_(shift_amount) {
2849 LOperand* left() { return inputs_[0]; }
2850 LOperand* right() { return inputs_[1]; }
2852 Shift shift() const { return shift_; }
2853 LOperand* shift_amount() const { return shift_amount_; }
2855 DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
2856 DECLARE_HYDROGEN_ACCESSOR(Sub)
2860 LOperand* shift_amount_;
2864 class LSubS: public LTemplateInstruction<1, 2, 0> {
2866 LSubS(LOperand* left, LOperand* right) {
2871 LOperand* left() { return inputs_[0]; }
2872 LOperand* right() { return inputs_[1]; }
2874 DECLARE_CONCRETE_INSTRUCTION(SubS, "sub-s")
2875 DECLARE_HYDROGEN_ACCESSOR(Sub)
2879 class LThisFunction final : public LTemplateInstruction<1, 0, 0> {
2881 DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
2882 DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
2886 class LToFastProperties final : public LTemplateInstruction<1, 1, 0> {
2888 explicit LToFastProperties(LOperand* value) {
2892 LOperand* value() { return inputs_[0]; }
2894 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
2895 DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
2899 class LTransitionElementsKind final : public LTemplateInstruction<0, 2, 2> {
2901 LTransitionElementsKind(LOperand* object,
2905 inputs_[0] = object;
2906 inputs_[1] = context;
2911 LOperand* object() { return inputs_[0]; }
2912 LOperand* context() { return inputs_[1]; }
2913 LOperand* temp1() { return temps_[0]; }
2914 LOperand* temp2() { return temps_[1]; }
2916 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
2917 "transition-elements-kind")
2918 DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
2920 void PrintDataTo(StringStream* stream) override;
2922 Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
2923 Handle<Map> transitioned_map() {
2924 return hydrogen()->transitioned_map().handle();
2926 ElementsKind from_kind() const { return hydrogen()->from_kind(); }
2927 ElementsKind to_kind() const { return hydrogen()->to_kind(); }
2931 class LTrapAllocationMemento final : public LTemplateInstruction<0, 1, 2> {
2933 LTrapAllocationMemento(LOperand* object, LOperand* temp1, LOperand* temp2) {
2934 inputs_[0] = object;
2939 LOperand* object() { return inputs_[0]; }
2940 LOperand* temp1() { return temps_[0]; }
2941 LOperand* temp2() { return temps_[1]; }
2943 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento, "trap-allocation-memento")
2947 class LTruncateDoubleToIntOrSmi final : public LTemplateInstruction<1, 1, 0> {
2949 explicit LTruncateDoubleToIntOrSmi(LOperand* value) {
2953 LOperand* value() { return inputs_[0]; }
2955 DECLARE_CONCRETE_INSTRUCTION(TruncateDoubleToIntOrSmi,
2956 "truncate-double-to-int-or-smi")
2957 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
2959 bool tag_result() { return hydrogen()->representation().IsSmi(); }
2963 class LTypeof final : public LTemplateInstruction<1, 2, 0> {
2965 LTypeof(LOperand* context, LOperand* value) {
2966 inputs_[0] = context;
2970 LOperand* context() { return inputs_[0]; }
2971 LOperand* value() { return inputs_[1]; }
2973 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
2977 class LTypeofIsAndBranch final : public LControlInstruction<1, 2> {
2979 LTypeofIsAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
2985 LOperand* value() { return inputs_[0]; }
2986 LOperand* temp1() { return temps_[0]; }
2987 LOperand* temp2() { return temps_[1]; }
2989 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
2990 DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
2992 Handle<String> type_literal() const { return hydrogen()->type_literal(); }
2994 void PrintDataTo(StringStream* stream) override;
2998 class LUint32ToDouble final : public LTemplateInstruction<1, 1, 0> {
3000 explicit LUint32ToDouble(LOperand* value) {
3004 LOperand* value() { return inputs_[0]; }
3006 DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
3010 class LCheckMapValue final : public LTemplateInstruction<0, 2, 1> {
3012 LCheckMapValue(LOperand* value, LOperand* map, LOperand* temp) {
3018 LOperand* value() { return inputs_[0]; }
3019 LOperand* map() { return inputs_[1]; }
3020 LOperand* temp() { return temps_[0]; }
3022 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
3026 class LLoadFieldByIndex final : public LTemplateInstruction<1, 2, 0> {
3028 LLoadFieldByIndex(LOperand* object, LOperand* index) {
3029 inputs_[0] = object;
3033 LOperand* object() { return inputs_[0]; }
3034 LOperand* index() { return inputs_[1]; }
3036 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
3040 class LStoreFrameContext: public LTemplateInstruction<0, 1, 0> {
3042 explicit LStoreFrameContext(LOperand* context) {
3043 inputs_[0] = context;
3046 LOperand* context() { return inputs_[0]; }
3048 DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext, "store-frame-context")
3052 class LAllocateBlockContext: public LTemplateInstruction<1, 2, 0> {
3054 LAllocateBlockContext(LOperand* context, LOperand* function) {
3055 inputs_[0] = context;
3056 inputs_[1] = function;
3059 LOperand* context() { return inputs_[0]; }
3060 LOperand* function() { return inputs_[1]; }
3062 Handle<ScopeInfo> scope_info() { return hydrogen()->scope_info(); }
3064 DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext, "allocate-block-context")
3065 DECLARE_HYDROGEN_ACCESSOR(AllocateBlockContext)
3069 class LWrapReceiver final : public LTemplateInstruction<1, 2, 0> {
3071 LWrapReceiver(LOperand* receiver, LOperand* function) {
3072 inputs_[0] = receiver;
3073 inputs_[1] = function;
3076 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
3077 DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
3079 LOperand* receiver() { return inputs_[0]; }
3080 LOperand* function() { return inputs_[1]; }
3084 class LChunkBuilder;
3085 class LPlatformChunk final : public LChunk {
3087 LPlatformChunk(CompilationInfo* info, HGraph* graph)
3088 : LChunk(info, graph) { }
3090 int GetNextSpillIndex();
3091 LOperand* GetNextSpillSlot(RegisterKind kind);
3095 class LChunkBuilder final : public LChunkBuilderBase {
3097 LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
3098 : LChunkBuilderBase(info, graph),
3099 current_instruction_(NULL),
3100 current_block_(NULL),
3101 allocator_(allocator) {}
3103 // Build the sequence for the graph.
3104 LPlatformChunk* Build();
3106 // Declare methods that deal with the individual node types.
3107 #define DECLARE_DO(type) LInstruction* Do##type(H##type* node);
3108 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
3111 LInstruction* DoDivByPowerOf2I(HDiv* instr);
3112 LInstruction* DoDivByConstI(HDiv* instr);
3113 LInstruction* DoDivI(HBinaryOperation* instr);
3114 LInstruction* DoModByPowerOf2I(HMod* instr);
3115 LInstruction* DoModByConstI(HMod* instr);
3116 LInstruction* DoModI(HMod* instr);
3117 LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr);
3118 LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr);
3119 LInstruction* DoFlooringDivI(HMathFloorOfDiv* instr);
3121 static bool HasMagicNumberForDivision(int32_t divisor);
3124 // Methods for getting operands for Use / Define / Temp.
3125 LUnallocated* ToUnallocated(Register reg);
3126 LUnallocated* ToUnallocated(DoubleRegister reg);
3128 // Methods for setting up define-use relationships.
3129 MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
3130 MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
3131 MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
3132 DoubleRegister fixed_register);
3134 // A value that is guaranteed to be allocated to a register.
3135 // The operand created by UseRegister is guaranteed to be live until the end
3136 // of the instruction. This means that register allocator will not reuse its
3137 // register for any other operand inside instruction.
3138 MUST_USE_RESULT LOperand* UseRegister(HValue* value);
3140 // The operand created by UseRegisterAndClobber is guaranteed to be live until
3141 // the end of the end of the instruction, and it may also be used as a scratch
3142 // register by the instruction implementation.
3144 // This behaves identically to ARM's UseTempRegister. However, it is renamed
3145 // to discourage its use in ARM64, since in most cases it is better to
3146 // allocate a temporary register for the Lithium instruction.
3147 MUST_USE_RESULT LOperand* UseRegisterAndClobber(HValue* value);
3149 // The operand created by UseRegisterAtStart is guaranteed to be live only at
3150 // instruction start. The register allocator is free to assign the same
3151 // register to some other operand used inside instruction (i.e. temporary or
3153 MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
3155 // An input operand in a register or a constant operand.
3156 MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
3157 MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
3159 // A constant operand.
3160 MUST_USE_RESULT LConstantOperand* UseConstant(HValue* value);
3162 // An input operand in register, stack slot or a constant operand.
3163 // Will not be moved to a register even if one is freely available.
3164 virtual MUST_USE_RESULT LOperand* UseAny(HValue* value);
3166 // Temporary operand that must be in a register.
3167 MUST_USE_RESULT LUnallocated* TempRegister();
3169 // Temporary operand that must be in a double register.
3170 MUST_USE_RESULT LUnallocated* TempDoubleRegister();
3172 MUST_USE_RESULT LOperand* FixedTemp(Register reg);
3174 // Temporary operand that must be in a fixed double register.
3175 MUST_USE_RESULT LOperand* FixedTemp(DoubleRegister reg);
3177 // Methods for setting up define-use relationships.
3178 // Return the same instruction that they are passed.
3179 LInstruction* Define(LTemplateResultInstruction<1>* instr,
3180 LUnallocated* result);
3181 LInstruction* DefineAsRegister(LTemplateResultInstruction<1>* instr);
3182 LInstruction* DefineAsSpilled(LTemplateResultInstruction<1>* instr,
3185 LInstruction* DefineSameAsFirst(LTemplateResultInstruction<1>* instr);
3186 LInstruction* DefineFixed(LTemplateResultInstruction<1>* instr,
3188 LInstruction* DefineFixedDouble(LTemplateResultInstruction<1>* instr,
3189 DoubleRegister reg);
3191 enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };
3193 // By default we assume that instruction sequences generated for calls
3194 // cannot deoptimize eagerly and we do not attach environment to this
3196 LInstruction* MarkAsCall(
3197 LInstruction* instr,
3198 HInstruction* hinstr,
3199 CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
3201 LInstruction* AssignPointerMap(LInstruction* instr);
3202 LInstruction* AssignEnvironment(LInstruction* instr);
3204 void VisitInstruction(HInstruction* current);
3205 void AddInstruction(LInstruction* instr, HInstruction* current);
3206 void DoBasicBlock(HBasicBlock* block);
3208 int JSShiftAmountFromHConstant(HValue* constant) {
3209 return HConstant::cast(constant)->Integer32Value() & 0x1f;
3211 bool LikelyFitsImmField(HInstruction* instr, int imm) {
3212 if (instr->IsAdd() || instr->IsSub()) {
3213 return Assembler::IsImmAddSub(imm) || Assembler::IsImmAddSub(-imm);
3215 DCHECK(instr->IsBitwise());
3216 unsigned unused_n, unused_imm_s, unused_imm_r;
3217 return Assembler::IsImmLogical(imm, kWRegSizeInBits,
3218 &unused_n, &unused_imm_s, &unused_imm_r);
3222 // Indicates if a sequence of the form
3225 // can be replaced with:
3226 // add x0, x1, x9 LSL #imm
3227 // If this is not possible, the function returns NULL. Otherwise it returns a
3228 // pointer to the shift instruction that would be optimized away.
3229 HBitwiseBinaryOperation* CanTransformToShiftedOp(HValue* val,
3230 HValue** left = NULL);
3231 // Checks if all uses of the shift operation can optimize it away.
3232 bool ShiftCanBeOptimizedAway(HBitwiseBinaryOperation* shift);
3233 // Attempts to merge the binary operation and an eventual previous shift
3234 // operation into a single operation. Returns the merged instruction on
3235 // success, and NULL otherwise.
3236 LInstruction* TryDoOpWithShiftedRightOperand(HBinaryOperation* op);
3237 LInstruction* DoShiftedBinaryOp(HBinaryOperation* instr,
3239 HBitwiseBinaryOperation* shift);
3241 LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr);
3242 LInstruction* DoArithmeticD(Token::Value op,
3243 HArithmeticBinaryOperation* instr);
3244 LInstruction* DoArithmeticT(Token::Value op,
3245 HBinaryOperation* instr);
3247 HInstruction* current_instruction_;
3248 HBasicBlock* current_block_;
3249 LAllocator* allocator_;
3251 DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
3254 #undef DECLARE_HYDROGEN_ACCESSOR
3255 #undef DECLARE_CONCRETE_INSTRUCTION
3257 } } // namespace v8::internal
3259 #endif // V8_ARM64_LITHIUM_ARM64_H_