Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: src/arm64/lithium-arm64.h

Issue 1405363003: Move Hydrogen and Lithium to src/crankshaft/ (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/arm64/delayed-masm-arm64-inl.h ('k') | src/arm64/lithium-arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #ifndef V8_ARM64_LITHIUM_ARM64_H_
6 #define V8_ARM64_LITHIUM_ARM64_H_
7
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"
13
14 namespace v8 {
15 namespace internal {
16
17 // Forward declarations.
18 class LCodeGen;
19
20 #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
21 V(AccessArgumentsAt) \
22 V(AddE) \
23 V(AddI) \
24 V(AddS) \
25 V(Allocate) \
26 V(AllocateBlockContext) \
27 V(ApplyArguments) \
28 V(ArgumentsElements) \
29 V(ArgumentsLength) \
30 V(ArithmeticD) \
31 V(ArithmeticT) \
32 V(BitI) \
33 V(BitS) \
34 V(BoundsCheck) \
35 V(Branch) \
36 V(CallFunction) \
37 V(CallJSFunction) \
38 V(CallNew) \
39 V(CallNewArray) \
40 V(CallRuntime) \
41 V(CallStub) \
42 V(CallWithDescriptor) \
43 V(CheckArrayBufferNotNeutered) \
44 V(CheckInstanceType) \
45 V(CheckMapValue) \
46 V(CheckMaps) \
47 V(CheckNonSmi) \
48 V(CheckSmi) \
49 V(CheckValue) \
50 V(ClampDToUint8) \
51 V(ClampIToUint8) \
52 V(ClampTToUint8) \
53 V(ClassOfTestAndBranch) \
54 V(CmpHoleAndBranchD) \
55 V(CmpHoleAndBranchT) \
56 V(CmpMapAndBranch) \
57 V(CmpObjectEqAndBranch) \
58 V(CmpT) \
59 V(CompareMinusZeroAndBranch) \
60 V(CompareNumericAndBranch) \
61 V(ConstantD) \
62 V(ConstantE) \
63 V(ConstantI) \
64 V(ConstantS) \
65 V(ConstantT) \
66 V(ConstructDouble) \
67 V(Context) \
68 V(DateField) \
69 V(DebugBreak) \
70 V(DeclareGlobals) \
71 V(Deoptimize) \
72 V(DivByConstI) \
73 V(DivByPowerOf2I) \
74 V(DivI) \
75 V(DoubleBits) \
76 V(DoubleToIntOrSmi) \
77 V(Drop) \
78 V(Dummy) \
79 V(DummyUse) \
80 V(FlooringDivByConstI) \
81 V(FlooringDivByPowerOf2I) \
82 V(FlooringDivI) \
83 V(ForInCacheArray) \
84 V(ForInPrepareMap) \
85 V(GetCachedArrayIndex) \
86 V(Goto) \
87 V(HasCachedArrayIndexAndBranch) \
88 V(HasInPrototypeChainAndBranch) \
89 V(HasInstanceTypeAndBranch) \
90 V(InnerAllocatedObject) \
91 V(InstanceOf) \
92 V(InstructionGap) \
93 V(Integer32ToDouble) \
94 V(InvokeFunction) \
95 V(IsConstructCallAndBranch) \
96 V(IsSmiAndBranch) \
97 V(IsStringAndBranch) \
98 V(IsUndetectableAndBranch) \
99 V(Label) \
100 V(LazyBailout) \
101 V(LoadContextSlot) \
102 V(LoadFieldByIndex) \
103 V(LoadFunctionPrototype) \
104 V(LoadGlobalGeneric) \
105 V(LoadGlobalViaContext) \
106 V(LoadKeyedExternal) \
107 V(LoadKeyedFixed) \
108 V(LoadKeyedFixedDouble) \
109 V(LoadKeyedGeneric) \
110 V(LoadNamedField) \
111 V(LoadNamedGeneric) \
112 V(LoadRoot) \
113 V(MapEnumLength) \
114 V(MathAbs) \
115 V(MathAbsTagged) \
116 V(MathClz32) \
117 V(MathExp) \
118 V(MathFloorD) \
119 V(MathFloorI) \
120 V(MathFround) \
121 V(MathLog) \
122 V(MathMinMax) \
123 V(MathPowHalf) \
124 V(MathRoundD) \
125 V(MathRoundI) \
126 V(MathSqrt) \
127 V(MaybeGrowElements) \
128 V(ModByConstI) \
129 V(ModByPowerOf2I) \
130 V(ModI) \
131 V(MulConstIS) \
132 V(MulI) \
133 V(MulS) \
134 V(NumberTagD) \
135 V(NumberTagU) \
136 V(NumberUntagD) \
137 V(OsrEntry) \
138 V(Parameter) \
139 V(Power) \
140 V(Prologue) \
141 V(PreparePushArguments) \
142 V(PushArguments) \
143 V(RegExpLiteral) \
144 V(Return) \
145 V(SeqStringGetChar) \
146 V(SeqStringSetChar) \
147 V(ShiftI) \
148 V(ShiftS) \
149 V(SmiTag) \
150 V(SmiUntag) \
151 V(StackCheck) \
152 V(StoreCodeEntry) \
153 V(StoreContextSlot) \
154 V(StoreFrameContext) \
155 V(StoreGlobalViaContext) \
156 V(StoreKeyedExternal) \
157 V(StoreKeyedFixed) \
158 V(StoreKeyedFixedDouble) \
159 V(StoreKeyedGeneric) \
160 V(StoreNamedField) \
161 V(StoreNamedGeneric) \
162 V(StringAdd) \
163 V(StringCharCodeAt) \
164 V(StringCharFromCode) \
165 V(StringCompareAndBranch) \
166 V(SubI) \
167 V(SubS) \
168 V(TaggedToI) \
169 V(ThisFunction) \
170 V(ToFastProperties) \
171 V(TransitionElementsKind) \
172 V(TrapAllocationMemento) \
173 V(TruncateDoubleToIntOrSmi) \
174 V(Typeof) \
175 V(TypeofIsAndBranch) \
176 V(Uint32ToDouble) \
177 V(UnknownOSRValue) \
178 V(WrapReceiver)
179
180
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); \
188 }
189
190
191 #define DECLARE_HYDROGEN_ACCESSOR(type) \
192 H##type* hydrogen() const { \
193 return H##type::cast(this->hydrogen_value()); \
194 }
195
196
197 class LInstruction : public ZoneObject {
198 public:
199 LInstruction()
200 : environment_(NULL),
201 hydrogen_value_(NULL),
202 bit_field_(IsCallBits::encode(false)) { }
203
204 virtual ~LInstruction() { }
205
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);
211
212 enum Opcode {
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
218 };
219
220 virtual Opcode opcode() const = 0;
221
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
227
228 // Declare virtual predicates for instructions that don't have
229 // an opcode.
230 virtual bool IsGap() const { return false; }
231
232 virtual bool IsControl() const { return false; }
233
234 // Try deleting this instruction if possible.
235 virtual bool TryDelete() { return false; }
236
237 void set_environment(LEnvironment* env) { environment_ = env; }
238 LEnvironment* environment() const { return environment_; }
239 bool HasEnvironment() const { return environment_ != NULL; }
240
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(); }
244
245 void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
246 HValue* hydrogen_value() const { return hydrogen_value_; }
247
248 void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
249 bool IsCall() const { return IsCallBits::decode(bit_field_); }
250
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 {
255 return IsCall();
256 }
257 bool IsMarkedAsCall() const { return IsCall(); }
258
259 virtual bool HasResult() const = 0;
260 virtual LOperand* result() const = 0;
261
262 virtual int InputCount() = 0;
263 virtual LOperand* InputAt(int i) = 0;
264 virtual int TempCount() = 0;
265 virtual LOperand* TempAt(int i) = 0;
266
267 LOperand* FirstInput() { return InputAt(0); }
268 LOperand* Output() { return HasResult() ? result() : NULL; }
269
270 virtual bool HasInterestingComment(LCodeGen* gen) const { return true; }
271
272 #ifdef DEBUG
273 void VerifyCall();
274 #endif
275
276 private:
277 class IsCallBits: public BitField<bool, 0, 1> {};
278
279 LEnvironment* environment_;
280 SetOncePointer<LPointerMap> pointer_map_;
281 HValue* hydrogen_value_;
282 int32_t bit_field_;
283 };
284
285
286 // R = number of result operands (0 or 1).
287 template<int R>
288 class LTemplateResultInstruction : public LInstruction {
289 public:
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]; }
295
296 protected:
297 EmbeddedContainer<LOperand*, R> results_;
298 };
299
300
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> {
306 protected:
307 EmbeddedContainer<LOperand*, I> inputs_;
308 EmbeddedContainer<LOperand*, T> temps_;
309
310 private:
311 // Iterator support.
312 int InputCount() final { return I; }
313 LOperand* InputAt(int i) final { return inputs_[i]; }
314
315 int TempCount() final { return T; }
316 LOperand* TempAt(int i) final { return temps_[i]; }
317 };
318
319
320 class LUnknownOSRValue final : public LTemplateInstruction<1, 0, 0> {
321 public:
322 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
323 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
324 };
325
326
327 template<int I, int T>
328 class LControlInstruction : public LTemplateInstruction<0, I, T> {
329 public:
330 LControlInstruction() : false_label_(NULL), true_label_(NULL) { }
331
332 bool IsControl() const final { return true; }
333
334 int SuccessorCount() { return hydrogen()->SuccessorCount(); }
335 HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
336
337 int TrueDestination(LChunk* chunk) {
338 return chunk->LookupDestination(true_block_id());
339 }
340
341 int FalseDestination(LChunk* chunk) {
342 return chunk->LookupDestination(false_block_id());
343 }
344
345 Label* TrueLabel(LChunk* chunk) {
346 if (true_label_ == NULL) {
347 true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk));
348 }
349 return true_label_;
350 }
351
352 Label* FalseLabel(LChunk* chunk) {
353 if (false_label_ == NULL) {
354 false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk));
355 }
356 return false_label_;
357 }
358
359 protected:
360 int true_block_id() { return SuccessorAt(0)->block_id(); }
361 int false_block_id() { return SuccessorAt(1)->block_id(); }
362
363 private:
364 DECLARE_HYDROGEN_ACCESSOR(ControlInstruction);
365
366 Label* false_label_;
367 Label* true_label_;
368 };
369
370
371 class LGap : public LTemplateInstruction<0, 0, 0> {
372 public:
373 explicit LGap(HBasicBlock* block)
374 : block_(block) {
375 parallel_moves_[BEFORE] = NULL;
376 parallel_moves_[START] = NULL;
377 parallel_moves_[END] = NULL;
378 parallel_moves_[AFTER] = NULL;
379 }
380
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);
387 }
388
389 bool IsRedundant() const;
390
391 HBasicBlock* block() const { return block_; }
392
393 enum InnerPosition {
394 BEFORE,
395 START,
396 END,
397 AFTER,
398 FIRST_INNER_POSITION = BEFORE,
399 LAST_INNER_POSITION = AFTER
400 };
401
402 LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) {
403 if (parallel_moves_[pos] == NULL) {
404 parallel_moves_[pos] = new(zone) LParallelMove(zone);
405 }
406 return parallel_moves_[pos];
407 }
408
409 LParallelMove* GetParallelMove(InnerPosition pos) {
410 return parallel_moves_[pos];
411 }
412
413 private:
414 LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
415 HBasicBlock* block_;
416 };
417
418
419 class LInstructionGap final : public LGap {
420 public:
421 explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
422
423 bool HasInterestingComment(LCodeGen* gen) const override {
424 return !IsRedundant();
425 }
426
427 DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
428 };
429
430
431 class LDrop final : public LTemplateInstruction<0, 0, 0> {
432 public:
433 explicit LDrop(int count) : count_(count) { }
434
435 int count() const { return count_; }
436
437 DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")
438
439 private:
440 int count_;
441 };
442
443
444 class LDummy final : public LTemplateInstruction<1, 0, 0> {
445 public:
446 LDummy() {}
447 DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
448 };
449
450
451 class LDummyUse final : public LTemplateInstruction<1, 1, 0> {
452 public:
453 explicit LDummyUse(LOperand* value) {
454 inputs_[0] = value;
455 }
456 DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
457 };
458
459
460 class LGoto final : public LTemplateInstruction<0, 0, 0> {
461 public:
462 explicit LGoto(HBasicBlock* block) : block_(block) { }
463
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; }
468
469 int block_id() const { return block_->block_id(); }
470
471 private:
472 HBasicBlock* block_;
473 };
474
475
476 class LPrologue final : public LTemplateInstruction<0, 0, 0> {
477 public:
478 DECLARE_CONCRETE_INSTRUCTION(Prologue, "prologue")
479 };
480
481
482 class LLazyBailout final : public LTemplateInstruction<0, 0, 0> {
483 public:
484 LLazyBailout() : gap_instructions_size_(0) { }
485
486 DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
487
488 void set_gap_instructions_size(int gap_instructions_size) {
489 gap_instructions_size_ = gap_instructions_size;
490 }
491 int gap_instructions_size() { return gap_instructions_size_; }
492
493 private:
494 int gap_instructions_size_;
495 };
496
497
498 class LLabel final : public LGap {
499 public:
500 explicit LLabel(HBasicBlock* block)
501 : LGap(block), replacement_(NULL) { }
502
503 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
504 DECLARE_CONCRETE_INSTRUCTION(Label, "label")
505
506 void PrintDataTo(StringStream* stream) override;
507
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; }
515
516 private:
517 Label label_;
518 LLabel* replacement_;
519 };
520
521
522 class LOsrEntry final : public LTemplateInstruction<0, 0, 0> {
523 public:
524 LOsrEntry() {}
525
526 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
527 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
528 };
529
530
531 class LAccessArgumentsAt final : public LTemplateInstruction<1, 3, 0> {
532 public:
533 LAccessArgumentsAt(LOperand* arguments,
534 LOperand* length,
535 LOperand* index) {
536 inputs_[0] = arguments;
537 inputs_[1] = length;
538 inputs_[2] = index;
539 }
540
541 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
542
543 LOperand* arguments() { return inputs_[0]; }
544 LOperand* length() { return inputs_[1]; }
545 LOperand* index() { return inputs_[2]; }
546
547 void PrintDataTo(StringStream* stream) override;
548 };
549
550
551 class LAddE final : public LTemplateInstruction<1, 2, 0> {
552 public:
553 LAddE(LOperand* left, LOperand* right) {
554 inputs_[0] = left;
555 inputs_[1] = right;
556 }
557
558 LOperand* left() { return inputs_[0]; }
559 LOperand* right() { return inputs_[1]; }
560
561 DECLARE_CONCRETE_INSTRUCTION(AddE, "add-e")
562 DECLARE_HYDROGEN_ACCESSOR(Add)
563 };
564
565
566 class LAddI final : public LTemplateInstruction<1, 2, 0> {
567 public:
568 LAddI(LOperand* left, LOperand* right)
569 : shift_(NO_SHIFT), shift_amount_(0) {
570 inputs_[0] = left;
571 inputs_[1] = right;
572 }
573
574 LAddI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
575 : shift_(shift), shift_amount_(shift_amount) {
576 inputs_[0] = left;
577 inputs_[1] = right;
578 }
579
580 LOperand* left() { return inputs_[0]; }
581 LOperand* right() { return inputs_[1]; }
582
583 Shift shift() const { return shift_; }
584 LOperand* shift_amount() const { return shift_amount_; }
585
586 DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
587 DECLARE_HYDROGEN_ACCESSOR(Add)
588
589 protected:
590 Shift shift_;
591 LOperand* shift_amount_;
592 };
593
594
595 class LAddS final : public LTemplateInstruction<1, 2, 0> {
596 public:
597 LAddS(LOperand* left, LOperand* right) {
598 inputs_[0] = left;
599 inputs_[1] = right;
600 }
601
602 LOperand* left() { return inputs_[0]; }
603 LOperand* right() { return inputs_[1]; }
604
605 DECLARE_CONCRETE_INSTRUCTION(AddS, "add-s")
606 DECLARE_HYDROGEN_ACCESSOR(Add)
607 };
608
609
610 class LAllocate final : public LTemplateInstruction<1, 2, 3> {
611 public:
612 LAllocate(LOperand* context,
613 LOperand* size,
614 LOperand* temp1,
615 LOperand* temp2,
616 LOperand* temp3) {
617 inputs_[0] = context;
618 inputs_[1] = size;
619 temps_[0] = temp1;
620 temps_[1] = temp2;
621 temps_[2] = temp3;
622 }
623
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]; }
629
630 DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
631 DECLARE_HYDROGEN_ACCESSOR(Allocate)
632 };
633
634
635 class LApplyArguments final : public LTemplateInstruction<1, 4, 0> {
636 public:
637 LApplyArguments(LOperand* function,
638 LOperand* receiver,
639 LOperand* length,
640 LOperand* elements) {
641 inputs_[0] = function;
642 inputs_[1] = receiver;
643 inputs_[2] = length;
644 inputs_[3] = elements;
645 }
646
647 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
648
649 LOperand* function() { return inputs_[0]; }
650 LOperand* receiver() { return inputs_[1]; }
651 LOperand* length() { return inputs_[2]; }
652 LOperand* elements() { return inputs_[3]; }
653 };
654
655
656 class LArgumentsElements final : public LTemplateInstruction<1, 0, 1> {
657 public:
658 explicit LArgumentsElements(LOperand* temp) {
659 temps_[0] = temp;
660 }
661
662 LOperand* temp() { return temps_[0]; }
663
664 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
665 DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements)
666 };
667
668
669 class LArgumentsLength final : public LTemplateInstruction<1, 1, 0> {
670 public:
671 explicit LArgumentsLength(LOperand* elements) {
672 inputs_[0] = elements;
673 }
674
675 LOperand* elements() { return inputs_[0]; }
676
677 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
678 };
679
680
681 class LArithmeticD final : public LTemplateInstruction<1, 2, 0> {
682 public:
683 LArithmeticD(Token::Value op,
684 LOperand* left,
685 LOperand* right)
686 : op_(op) {
687 inputs_[0] = left;
688 inputs_[1] = right;
689 }
690
691 Token::Value op() const { return op_; }
692 LOperand* left() { return inputs_[0]; }
693 LOperand* right() { return inputs_[1]; }
694
695 Opcode opcode() const override { return LInstruction::kArithmeticD; }
696 void CompileToNative(LCodeGen* generator) override;
697 const char* Mnemonic() const override;
698
699 private:
700 Token::Value op_;
701 };
702
703
704 class LArithmeticT final : public LTemplateInstruction<1, 3, 0> {
705 public:
706 LArithmeticT(Token::Value op,
707 LOperand* context,
708 LOperand* left,
709 LOperand* right)
710 : op_(op) {
711 inputs_[0] = context;
712 inputs_[1] = left;
713 inputs_[2] = right;
714 }
715
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_; }
720
721 Opcode opcode() const override { return LInstruction::kArithmeticT; }
722 void CompileToNative(LCodeGen* generator) override;
723 const char* Mnemonic() const override;
724
725 DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
726
727 Strength strength() { return hydrogen()->strength(); }
728
729 private:
730 Token::Value op_;
731 };
732
733
734 class LBoundsCheck final : public LTemplateInstruction<0, 2, 0> {
735 public:
736 explicit LBoundsCheck(LOperand* index, LOperand* length) {
737 inputs_[0] = index;
738 inputs_[1] = length;
739 }
740
741 LOperand* index() { return inputs_[0]; }
742 LOperand* length() { return inputs_[1]; }
743
744 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
745 DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
746 };
747
748
749 class LBitI final : public LTemplateInstruction<1, 2, 0> {
750 public:
751 LBitI(LOperand* left, LOperand* right)
752 : shift_(NO_SHIFT), shift_amount_(0) {
753 inputs_[0] = left;
754 inputs_[1] = right;
755 }
756
757 LBitI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
758 : shift_(shift), shift_amount_(shift_amount) {
759 inputs_[0] = left;
760 inputs_[1] = right;
761 }
762
763 LOperand* left() { return inputs_[0]; }
764 LOperand* right() { return inputs_[1]; }
765
766 Shift shift() const { return shift_; }
767 LOperand* shift_amount() const { return shift_amount_; }
768
769 Token::Value op() const { return hydrogen()->op(); }
770
771 DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
772 DECLARE_HYDROGEN_ACCESSOR(Bitwise)
773
774 protected:
775 Shift shift_;
776 LOperand* shift_amount_;
777 };
778
779
780 class LBitS final : public LTemplateInstruction<1, 2, 0> {
781 public:
782 LBitS(LOperand* left, LOperand* right) {
783 inputs_[0] = left;
784 inputs_[1] = right;
785 }
786
787 LOperand* left() { return inputs_[0]; }
788 LOperand* right() { return inputs_[1]; }
789
790 Token::Value op() const { return hydrogen()->op(); }
791
792 DECLARE_CONCRETE_INSTRUCTION(BitS, "bit-s")
793 DECLARE_HYDROGEN_ACCESSOR(Bitwise)
794 };
795
796
797 class LBranch final : public LControlInstruction<1, 2> {
798 public:
799 explicit LBranch(LOperand* value, LOperand *temp1, LOperand *temp2) {
800 inputs_[0] = value;
801 temps_[0] = temp1;
802 temps_[1] = temp2;
803 }
804
805 LOperand* value() { return inputs_[0]; }
806 LOperand* temp1() { return temps_[0]; }
807 LOperand* temp2() { return temps_[1]; }
808
809 DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
810 DECLARE_HYDROGEN_ACCESSOR(Branch)
811
812 void PrintDataTo(StringStream* stream) override;
813 };
814
815
816 class LCallJSFunction final : public LTemplateInstruction<1, 1, 0> {
817 public:
818 explicit LCallJSFunction(LOperand* function) {
819 inputs_[0] = function;
820 }
821
822 LOperand* function() { return inputs_[0]; }
823
824 DECLARE_CONCRETE_INSTRUCTION(CallJSFunction, "call-js-function")
825 DECLARE_HYDROGEN_ACCESSOR(CallJSFunction)
826
827 void PrintDataTo(StringStream* stream) override;
828
829 int arity() const { return hydrogen()->argument_count() - 1; }
830 };
831
832
833 class LCallFunction final : public LTemplateInstruction<1, 2, 2> {
834 public:
835 LCallFunction(LOperand* context, LOperand* function, LOperand* slot,
836 LOperand* vector) {
837 inputs_[0] = context;
838 inputs_[1] = function;
839 temps_[0] = slot;
840 temps_[1] = vector;
841 }
842
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]; }
847
848 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
849 DECLARE_HYDROGEN_ACCESSOR(CallFunction)
850
851 int arity() const { return hydrogen()->argument_count() - 1; }
852 void PrintDataTo(StringStream* stream) override;
853 };
854
855
856 class LCallNew final : public LTemplateInstruction<1, 2, 0> {
857 public:
858 LCallNew(LOperand* context, LOperand* constructor) {
859 inputs_[0] = context;
860 inputs_[1] = constructor;
861 }
862
863 LOperand* context() { return inputs_[0]; }
864 LOperand* constructor() { return inputs_[1]; }
865
866 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
867 DECLARE_HYDROGEN_ACCESSOR(CallNew)
868
869 void PrintDataTo(StringStream* stream) override;
870
871 int arity() const { return hydrogen()->argument_count() - 1; }
872 };
873
874
875 class LCallNewArray final : public LTemplateInstruction<1, 2, 0> {
876 public:
877 LCallNewArray(LOperand* context, LOperand* constructor) {
878 inputs_[0] = context;
879 inputs_[1] = constructor;
880 }
881
882 LOperand* context() { return inputs_[0]; }
883 LOperand* constructor() { return inputs_[1]; }
884
885 DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
886 DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
887
888 void PrintDataTo(StringStream* stream) override;
889
890 int arity() const { return hydrogen()->argument_count() - 1; }
891 };
892
893
894 class LCallRuntime final : public LTemplateInstruction<1, 1, 0> {
895 public:
896 explicit LCallRuntime(LOperand* context) {
897 inputs_[0] = context;
898 }
899
900 LOperand* context() { return inputs_[0]; }
901
902 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
903 DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
904
905 bool ClobbersDoubleRegisters(Isolate* isolate) const override {
906 return save_doubles() == kDontSaveFPRegs;
907 }
908
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(); }
912 };
913
914
915 class LCallStub final : public LTemplateInstruction<1, 1, 0> {
916 public:
917 explicit LCallStub(LOperand* context) {
918 inputs_[0] = context;
919 }
920
921 LOperand* context() { return inputs_[0]; }
922
923 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
924 DECLARE_HYDROGEN_ACCESSOR(CallStub)
925 };
926
927
928 class LCheckArrayBufferNotNeutered final
929 : public LTemplateInstruction<0, 1, 0> {
930 public:
931 explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; }
932
933 LOperand* view() { return inputs_[0]; }
934
935 DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
936 "check-array-buffer-not-neutered")
937 DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
938 };
939
940
941 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 1> {
942 public:
943 explicit LCheckInstanceType(LOperand* value, LOperand* temp) {
944 inputs_[0] = value;
945 temps_[0] = temp;
946 }
947
948 LOperand* value() { return inputs_[0]; }
949 LOperand* temp() { return temps_[0]; }
950
951 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
952 DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
953 };
954
955
956 class LCheckMaps final : public LTemplateInstruction<0, 1, 1> {
957 public:
958 explicit LCheckMaps(LOperand* value = NULL, LOperand* temp = NULL) {
959 inputs_[0] = value;
960 temps_[0] = temp;
961 }
962
963 LOperand* value() { return inputs_[0]; }
964 LOperand* temp() { return temps_[0]; }
965
966 DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
967 DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
968 };
969
970
971 class LCheckNonSmi final : public LTemplateInstruction<0, 1, 0> {
972 public:
973 explicit LCheckNonSmi(LOperand* value) {
974 inputs_[0] = value;
975 }
976
977 LOperand* value() { return inputs_[0]; }
978
979 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
980 DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject)
981 };
982
983
984 class LCheckSmi final : public LTemplateInstruction<1, 1, 0> {
985 public:
986 explicit LCheckSmi(LOperand* value) {
987 inputs_[0] = value;
988 }
989
990 LOperand* value() { return inputs_[0]; }
991
992 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
993 };
994
995
996 class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
997 public:
998 explicit LCheckValue(LOperand* value) {
999 inputs_[0] = value;
1000 }
1001
1002 LOperand* value() { return inputs_[0]; }
1003
1004 DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value")
1005 DECLARE_HYDROGEN_ACCESSOR(CheckValue)
1006 };
1007
1008
1009 class LClampDToUint8 final : public LTemplateInstruction<1, 1, 0> {
1010 public:
1011 explicit LClampDToUint8(LOperand* unclamped) {
1012 inputs_[0] = unclamped;
1013 }
1014
1015 LOperand* unclamped() { return inputs_[0]; }
1016
1017 DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
1018 };
1019
1020
1021 class LClampIToUint8 final : public LTemplateInstruction<1, 1, 0> {
1022 public:
1023 explicit LClampIToUint8(LOperand* unclamped) {
1024 inputs_[0] = unclamped;
1025 }
1026
1027 LOperand* unclamped() { return inputs_[0]; }
1028
1029 DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
1030 };
1031
1032
1033 class LClampTToUint8 final : public LTemplateInstruction<1, 1, 1> {
1034 public:
1035 LClampTToUint8(LOperand* unclamped, LOperand* temp1) {
1036 inputs_[0] = unclamped;
1037 temps_[0] = temp1;
1038 }
1039
1040 LOperand* unclamped() { return inputs_[0]; }
1041 LOperand* temp1() { return temps_[0]; }
1042
1043 DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
1044 };
1045
1046
1047 class LDoubleBits final : public LTemplateInstruction<1, 1, 0> {
1048 public:
1049 explicit LDoubleBits(LOperand* value) {
1050 inputs_[0] = value;
1051 }
1052
1053 LOperand* value() { return inputs_[0]; }
1054
1055 DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
1056 DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
1057 };
1058
1059
1060 class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
1061 public:
1062 LConstructDouble(LOperand* hi, LOperand* lo) {
1063 inputs_[0] = hi;
1064 inputs_[1] = lo;
1065 }
1066
1067 LOperand* hi() { return inputs_[0]; }
1068 LOperand* lo() { return inputs_[1]; }
1069
1070 DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
1071 };
1072
1073
1074 class LClassOfTestAndBranch final : public LControlInstruction<1, 2> {
1075 public:
1076 LClassOfTestAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
1077 inputs_[0] = value;
1078 temps_[0] = temp1;
1079 temps_[1] = temp2;
1080 }
1081
1082 LOperand* value() { return inputs_[0]; }
1083 LOperand* temp1() { return temps_[0]; }
1084 LOperand* temp2() { return temps_[1]; }
1085
1086 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
1087 "class-of-test-and-branch")
1088 DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
1089
1090 void PrintDataTo(StringStream* stream) override;
1091 };
1092
1093
1094 class LCmpHoleAndBranchD final : public LControlInstruction<1, 1> {
1095 public:
1096 explicit LCmpHoleAndBranchD(LOperand* object, LOperand* temp) {
1097 inputs_[0] = object;
1098 temps_[0] = temp;
1099 }
1100
1101 LOperand* object() { return inputs_[0]; }
1102 LOperand* temp() { return temps_[0]; }
1103
1104 DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchD, "cmp-hole-and-branch-d")
1105 DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
1106 };
1107
1108
1109 class LCmpHoleAndBranchT final : public LControlInstruction<1, 0> {
1110 public:
1111 explicit LCmpHoleAndBranchT(LOperand* object) {
1112 inputs_[0] = object;
1113 }
1114
1115 LOperand* object() { return inputs_[0]; }
1116
1117 DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchT, "cmp-hole-and-branch-t")
1118 DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
1119 };
1120
1121
1122 class LCmpMapAndBranch final : public LControlInstruction<1, 1> {
1123 public:
1124 LCmpMapAndBranch(LOperand* value, LOperand* temp) {
1125 inputs_[0] = value;
1126 temps_[0] = temp;
1127 }
1128
1129 LOperand* value() { return inputs_[0]; }
1130 LOperand* temp() { return temps_[0]; }
1131
1132 DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
1133 DECLARE_HYDROGEN_ACCESSOR(CompareMap)
1134
1135 Handle<Map> map() const { return hydrogen()->map().handle(); }
1136 };
1137
1138
1139 class LCmpObjectEqAndBranch final : public LControlInstruction<2, 0> {
1140 public:
1141 LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
1142 inputs_[0] = left;
1143 inputs_[1] = right;
1144 }
1145
1146 LOperand* left() { return inputs_[0]; }
1147 LOperand* right() { return inputs_[1]; }
1148
1149 DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
1150 DECLARE_HYDROGEN_ACCESSOR(CompareObjectEqAndBranch)
1151 };
1152
1153
1154 class LCmpT final : public LTemplateInstruction<1, 3, 0> {
1155 public:
1156 LCmpT(LOperand* context, LOperand* left, LOperand* right) {
1157 inputs_[0] = context;
1158 inputs_[1] = left;
1159 inputs_[2] = right;
1160 }
1161
1162 LOperand* context() { return inputs_[0]; }
1163 LOperand* left() { return inputs_[1]; }
1164 LOperand* right() { return inputs_[2]; }
1165
1166 DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
1167 DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
1168
1169 Strength strength() { return hydrogen()->strength(); }
1170
1171 Token::Value op() const { return hydrogen()->token(); }
1172 };
1173
1174
1175 class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 1> {
1176 public:
1177 LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
1178 inputs_[0] = value;
1179 temps_[0] = temp;
1180 }
1181
1182 LOperand* value() { return inputs_[0]; }
1183 LOperand* temp() { return temps_[0]; }
1184
1185 DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
1186 "cmp-minus-zero-and-branch")
1187 DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
1188 };
1189
1190
1191 class LCompareNumericAndBranch final : public LControlInstruction<2, 0> {
1192 public:
1193 LCompareNumericAndBranch(LOperand* left, LOperand* right) {
1194 inputs_[0] = left;
1195 inputs_[1] = right;
1196 }
1197
1198 LOperand* left() { return inputs_[0]; }
1199 LOperand* right() { return inputs_[1]; }
1200
1201 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
1202 "compare-numeric-and-branch")
1203 DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
1204
1205 Token::Value op() const { return hydrogen()->token(); }
1206 bool is_double() const {
1207 return hydrogen()->representation().IsDouble();
1208 }
1209
1210 void PrintDataTo(StringStream* stream) override;
1211 };
1212
1213
1214 class LConstantD final : public LTemplateInstruction<1, 0, 0> {
1215 public:
1216 DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
1217 DECLARE_HYDROGEN_ACCESSOR(Constant)
1218
1219 double value() const { return hydrogen()->DoubleValue(); }
1220 };
1221
1222
1223 class LConstantE final : public LTemplateInstruction<1, 0, 0> {
1224 public:
1225 DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
1226 DECLARE_HYDROGEN_ACCESSOR(Constant)
1227
1228 ExternalReference value() const {
1229 return hydrogen()->ExternalReferenceValue();
1230 }
1231 };
1232
1233
1234 class LConstantI final : public LTemplateInstruction<1, 0, 0> {
1235 public:
1236 DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
1237 DECLARE_HYDROGEN_ACCESSOR(Constant)
1238
1239 int32_t value() const { return hydrogen()->Integer32Value(); }
1240 };
1241
1242
1243 class LConstantS final : public LTemplateInstruction<1, 0, 0> {
1244 public:
1245 DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
1246 DECLARE_HYDROGEN_ACCESSOR(Constant)
1247
1248 Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
1249 };
1250
1251
1252 class LConstantT final : public LTemplateInstruction<1, 0, 0> {
1253 public:
1254 DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
1255 DECLARE_HYDROGEN_ACCESSOR(Constant)
1256
1257 Handle<Object> value(Isolate* isolate) const {
1258 return hydrogen()->handle(isolate);
1259 }
1260 };
1261
1262
1263 class LContext final : public LTemplateInstruction<1, 0, 0> {
1264 public:
1265 DECLARE_CONCRETE_INSTRUCTION(Context, "context")
1266 DECLARE_HYDROGEN_ACCESSOR(Context)
1267 };
1268
1269
1270 class LDateField final : public LTemplateInstruction<1, 1, 0> {
1271 public:
1272 LDateField(LOperand* date, Smi* index) : index_(index) {
1273 inputs_[0] = date;
1274 }
1275
1276 LOperand* date() { return inputs_[0]; }
1277 Smi* index() const { return index_; }
1278
1279 DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
1280 DECLARE_HYDROGEN_ACCESSOR(DateField)
1281
1282 private:
1283 Smi* index_;
1284 };
1285
1286
1287 class LDebugBreak final : public LTemplateInstruction<0, 0, 0> {
1288 public:
1289 DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break")
1290 };
1291
1292
1293 class LDeclareGlobals final : public LTemplateInstruction<0, 1, 0> {
1294 public:
1295 explicit LDeclareGlobals(LOperand* context) {
1296 inputs_[0] = context;
1297 }
1298
1299 LOperand* context() { return inputs_[0]; }
1300
1301 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
1302 DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
1303 };
1304
1305
1306 class LDeoptimize final : public LTemplateInstruction<0, 0, 0> {
1307 public:
1308 bool IsControl() const override { return true; }
1309 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
1310 DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
1311 };
1312
1313
1314 class LDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
1315 public:
1316 LDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
1317 inputs_[0] = dividend;
1318 divisor_ = divisor;
1319 }
1320
1321 LOperand* dividend() { return inputs_[0]; }
1322 int32_t divisor() const { return divisor_; }
1323
1324 DECLARE_CONCRETE_INSTRUCTION(DivByPowerOf2I, "div-by-power-of-2-i")
1325 DECLARE_HYDROGEN_ACCESSOR(Div)
1326
1327 private:
1328 int32_t divisor_;
1329 };
1330
1331
1332 class LDivByConstI final : public LTemplateInstruction<1, 1, 1> {
1333 public:
1334 LDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
1335 inputs_[0] = dividend;
1336 divisor_ = divisor;
1337 temps_[0] = temp;
1338 }
1339
1340 LOperand* dividend() { return inputs_[0]; }
1341 int32_t divisor() const { return divisor_; }
1342 LOperand* temp() { return temps_[0]; }
1343
1344 DECLARE_CONCRETE_INSTRUCTION(DivByConstI, "div-by-const-i")
1345 DECLARE_HYDROGEN_ACCESSOR(Div)
1346
1347 private:
1348 int32_t divisor_;
1349 };
1350
1351
1352 class LDivI final : public LTemplateInstruction<1, 2, 1> {
1353 public:
1354 LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
1355 inputs_[0] = dividend;
1356 inputs_[1] = divisor;
1357 temps_[0] = temp;
1358 }
1359
1360 LOperand* dividend() { return inputs_[0]; }
1361 LOperand* divisor() { return inputs_[1]; }
1362 LOperand* temp() { return temps_[0]; }
1363
1364 DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
1365 DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
1366 };
1367
1368
1369 class LDoubleToIntOrSmi final : public LTemplateInstruction<1, 1, 0> {
1370 public:
1371 explicit LDoubleToIntOrSmi(LOperand* value) {
1372 inputs_[0] = value;
1373 }
1374
1375 LOperand* value() { return inputs_[0]; }
1376
1377 DECLARE_CONCRETE_INSTRUCTION(DoubleToIntOrSmi, "double-to-int-or-smi")
1378 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
1379
1380 bool tag_result() { return hydrogen()->representation().IsSmi(); }
1381 };
1382
1383
1384 class LForInCacheArray final : public LTemplateInstruction<1, 1, 0> {
1385 public:
1386 explicit LForInCacheArray(LOperand* map) {
1387 inputs_[0] = map;
1388 }
1389
1390 LOperand* map() { return inputs_[0]; }
1391
1392 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
1393
1394 int idx() {
1395 return HForInCacheArray::cast(this->hydrogen_value())->idx();
1396 }
1397 };
1398
1399
1400 class LForInPrepareMap final : public LTemplateInstruction<1, 2, 0> {
1401 public:
1402 LForInPrepareMap(LOperand* context, LOperand* object) {
1403 inputs_[0] = context;
1404 inputs_[1] = object;
1405 }
1406
1407 LOperand* context() { return inputs_[0]; }
1408 LOperand* object() { return inputs_[1]; }
1409
1410 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
1411 };
1412
1413
1414 class LGetCachedArrayIndex final : public LTemplateInstruction<1, 1, 0> {
1415 public:
1416 explicit LGetCachedArrayIndex(LOperand* value) {
1417 inputs_[0] = value;
1418 }
1419
1420 LOperand* value() { return inputs_[0]; }
1421
1422 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
1423 DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
1424 };
1425
1426
1427 class LHasCachedArrayIndexAndBranch final : public LControlInstruction<1, 1> {
1428 public:
1429 LHasCachedArrayIndexAndBranch(LOperand* value, LOperand* temp) {
1430 inputs_[0] = value;
1431 temps_[0] = temp;
1432 }
1433
1434 LOperand* value() { return inputs_[0]; }
1435 LOperand* temp() { return temps_[0]; }
1436
1437 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
1438 "has-cached-array-index-and-branch")
1439 DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndexAndBranch)
1440
1441 void PrintDataTo(StringStream* stream) override;
1442 };
1443
1444
1445 class LHasInstanceTypeAndBranch final : public LControlInstruction<1, 1> {
1446 public:
1447 LHasInstanceTypeAndBranch(LOperand* value, LOperand* temp) {
1448 inputs_[0] = value;
1449 temps_[0] = temp;
1450 }
1451
1452 LOperand* value() { return inputs_[0]; }
1453 LOperand* temp() { return temps_[0]; }
1454
1455 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
1456 "has-instance-type-and-branch")
1457 DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
1458
1459 void PrintDataTo(StringStream* stream) override;
1460 };
1461
1462
1463 class LInnerAllocatedObject final : public LTemplateInstruction<1, 2, 0> {
1464 public:
1465 LInnerAllocatedObject(LOperand* base_object, LOperand* offset) {
1466 inputs_[0] = base_object;
1467 inputs_[1] = offset;
1468 }
1469
1470 LOperand* base_object() const { return inputs_[0]; }
1471 LOperand* offset() const { return inputs_[1]; }
1472
1473 void PrintDataTo(StringStream* stream) override;
1474
1475 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object")
1476 };
1477
1478
1479 class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
1480 public:
1481 LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
1482 inputs_[0] = context;
1483 inputs_[1] = left;
1484 inputs_[2] = right;
1485 }
1486
1487 LOperand* context() const { return inputs_[0]; }
1488 LOperand* left() const { return inputs_[1]; }
1489 LOperand* right() const { return inputs_[2]; }
1490
1491 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
1492 };
1493
1494
1495 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 1> {
1496 public:
1497 LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype,
1498 LOperand* scratch) {
1499 inputs_[0] = object;
1500 inputs_[1] = prototype;
1501 temps_[0] = scratch;
1502 }
1503
1504 LOperand* object() const { return inputs_[0]; }
1505 LOperand* prototype() const { return inputs_[1]; }
1506 LOperand* scratch() const { return temps_[0]; }
1507
1508 DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch,
1509 "has-in-prototype-chain-and-branch")
1510 DECLARE_HYDROGEN_ACCESSOR(HasInPrototypeChainAndBranch)
1511 };
1512
1513
1514 class LInteger32ToDouble final : public LTemplateInstruction<1, 1, 0> {
1515 public:
1516 explicit LInteger32ToDouble(LOperand* value) {
1517 inputs_[0] = value;
1518 }
1519
1520 LOperand* value() { return inputs_[0]; }
1521
1522 DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
1523 };
1524
1525
1526 class LCallWithDescriptor final : public LTemplateResultInstruction<1> {
1527 public:
1528 LCallWithDescriptor(CallInterfaceDescriptor descriptor,
1529 const ZoneList<LOperand*>& operands, Zone* zone)
1530 : descriptor_(descriptor),
1531 inputs_(descriptor.GetRegisterParameterCount() +
1532 kImplicitRegisterParameterCount,
1533 zone) {
1534 DCHECK(descriptor.GetRegisterParameterCount() +
1535 kImplicitRegisterParameterCount ==
1536 operands.length());
1537 inputs_.AddAll(operands, zone);
1538 }
1539
1540 LOperand* target() const { return inputs_[0]; }
1541
1542 CallInterfaceDescriptor descriptor() { return descriptor_; }
1543
1544 DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)
1545
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;
1549
1550 private:
1551 DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
1552
1553 void PrintDataTo(StringStream* stream) override;
1554
1555 int arity() const { return hydrogen()->argument_count() - 1; }
1556
1557 CallInterfaceDescriptor descriptor_;
1558 ZoneList<LOperand*> inputs_;
1559
1560 // Iterator support.
1561 int InputCount() final { return inputs_.length(); }
1562 LOperand* InputAt(int i) final { return inputs_[i]; }
1563
1564 int TempCount() final { return 0; }
1565 LOperand* TempAt(int i) final { return NULL; }
1566 };
1567
1568
1569 class LInvokeFunction final : public LTemplateInstruction<1, 2, 0> {
1570 public:
1571 LInvokeFunction(LOperand* context, LOperand* function) {
1572 inputs_[0] = context;
1573 inputs_[1] = function;
1574 }
1575
1576 LOperand* context() { return inputs_[0]; }
1577 LOperand* function() { return inputs_[1]; }
1578
1579 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
1580 DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
1581
1582 void PrintDataTo(StringStream* stream) override;
1583
1584 int arity() const { return hydrogen()->argument_count() - 1; }
1585 };
1586
1587
1588 class LIsConstructCallAndBranch final : public LControlInstruction<0, 2> {
1589 public:
1590 LIsConstructCallAndBranch(LOperand* temp1, LOperand* temp2) {
1591 temps_[0] = temp1;
1592 temps_[1] = temp2;
1593 }
1594
1595 LOperand* temp1() { return temps_[0]; }
1596 LOperand* temp2() { return temps_[1]; }
1597
1598 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
1599 "is-construct-call-and-branch")
1600 };
1601
1602
1603 class LIsStringAndBranch final : public LControlInstruction<1, 1> {
1604 public:
1605 LIsStringAndBranch(LOperand* value, LOperand* temp) {
1606 inputs_[0] = value;
1607 temps_[0] = temp;
1608 }
1609
1610 LOperand* value() { return inputs_[0]; }
1611 LOperand* temp() { return temps_[0]; }
1612
1613 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
1614 DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
1615
1616 void PrintDataTo(StringStream* stream) override;
1617 };
1618
1619
1620 class LIsSmiAndBranch final : public LControlInstruction<1, 0> {
1621 public:
1622 explicit LIsSmiAndBranch(LOperand* value) {
1623 inputs_[0] = value;
1624 }
1625
1626 LOperand* value() { return inputs_[0]; }
1627
1628 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
1629 DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
1630
1631 void PrintDataTo(StringStream* stream) override;
1632 };
1633
1634
1635 class LIsUndetectableAndBranch final : public LControlInstruction<1, 1> {
1636 public:
1637 explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
1638 inputs_[0] = value;
1639 temps_[0] = temp;
1640 }
1641
1642 LOperand* value() { return inputs_[0]; }
1643 LOperand* temp() { return temps_[0]; }
1644
1645 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
1646 "is-undetectable-and-branch")
1647 DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
1648
1649 void PrintDataTo(StringStream* stream) override;
1650 };
1651
1652
1653 class LLoadGlobalViaContext final : public LTemplateInstruction<1, 1, 1> {
1654 public:
1655 explicit LLoadGlobalViaContext(LOperand* context) { inputs_[0] = context; }
1656
1657 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalViaContext, "load-global-via-context")
1658 DECLARE_HYDROGEN_ACCESSOR(LoadGlobalViaContext)
1659
1660 void PrintDataTo(StringStream* stream) override;
1661
1662 LOperand* context() { return inputs_[0]; }
1663
1664 int depth() const { return hydrogen()->depth(); }
1665 int slot_index() const { return hydrogen()->slot_index(); }
1666 };
1667
1668
1669 class LLoadContextSlot final : public LTemplateInstruction<1, 1, 0> {
1670 public:
1671 explicit LLoadContextSlot(LOperand* context) {
1672 inputs_[0] = context;
1673 }
1674
1675 LOperand* context() { return inputs_[0]; }
1676
1677 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
1678 DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
1679
1680 int slot_index() const { return hydrogen()->slot_index(); }
1681
1682 void PrintDataTo(StringStream* stream) override;
1683 };
1684
1685
1686 class LLoadNamedField final : public LTemplateInstruction<1, 1, 0> {
1687 public:
1688 explicit LLoadNamedField(LOperand* object) {
1689 inputs_[0] = object;
1690 }
1691
1692 LOperand* object() { return inputs_[0]; }
1693
1694 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
1695 DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
1696 };
1697
1698
1699 class LLoadFunctionPrototype final : public LTemplateInstruction<1, 1, 1> {
1700 public:
1701 LLoadFunctionPrototype(LOperand* function, LOperand* temp) {
1702 inputs_[0] = function;
1703 temps_[0] = temp;
1704 }
1705
1706 LOperand* function() { return inputs_[0]; }
1707 LOperand* temp() { return temps_[0]; }
1708
1709 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
1710 DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
1711 };
1712
1713
1714 class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
1715 public:
1716 LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
1717 LOperand* vector) {
1718 inputs_[0] = context;
1719 inputs_[1] = global_object;
1720 temps_[0] = vector;
1721 }
1722
1723 LOperand* context() { return inputs_[0]; }
1724 LOperand* global_object() { return inputs_[1]; }
1725 LOperand* temp_vector() { return temps_[0]; }
1726
1727 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
1728 DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
1729
1730 Handle<Object> name() const { return hydrogen()->name(); }
1731 TypeofMode typeof_mode() const { return hydrogen()->typeof_mode(); }
1732 };
1733
1734
1735 template<int T>
1736 class LLoadKeyed : public LTemplateInstruction<1, 2, T> {
1737 public:
1738 LLoadKeyed(LOperand* elements, LOperand* key) {
1739 this->inputs_[0] = elements;
1740 this->inputs_[1] = key;
1741 }
1742
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();
1747 }
1748 bool is_external() const {
1749 return this->hydrogen()->is_external();
1750 }
1751 bool is_fixed_typed_array() const {
1752 return hydrogen()->is_fixed_typed_array();
1753 }
1754 bool is_typed_elements() const {
1755 return is_external() || is_fixed_typed_array();
1756 }
1757 uint32_t base_offset() const {
1758 return this->hydrogen()->base_offset();
1759 }
1760 void PrintDataTo(StringStream* stream) override {
1761 this->elements()->PrintTo(stream);
1762 stream->Add("[");
1763 this->key()->PrintTo(stream);
1764 if (this->base_offset() != 0) {
1765 stream->Add(" + %d]", this->base_offset());
1766 } else {
1767 stream->Add("]");
1768 }
1769 }
1770
1771 DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
1772 };
1773
1774
1775 class LLoadKeyedExternal: public LLoadKeyed<1> {
1776 public:
1777 LLoadKeyedExternal(LOperand* elements, LOperand* key, LOperand* temp) :
1778 LLoadKeyed<1>(elements, key) {
1779 temps_[0] = temp;
1780 }
1781
1782 LOperand* temp() { return temps_[0]; }
1783
1784 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedExternal, "load-keyed-external");
1785 };
1786
1787
1788 class LLoadKeyedFixed: public LLoadKeyed<1> {
1789 public:
1790 LLoadKeyedFixed(LOperand* elements, LOperand* key, LOperand* temp) :
1791 LLoadKeyed<1>(elements, key) {
1792 temps_[0] = temp;
1793 }
1794
1795 LOperand* temp() { return temps_[0]; }
1796
1797 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixed, "load-keyed-fixed");
1798 };
1799
1800
1801 class LLoadKeyedFixedDouble: public LLoadKeyed<1> {
1802 public:
1803 LLoadKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* temp) :
1804 LLoadKeyed<1>(elements, key) {
1805 temps_[0] = temp;
1806 }
1807
1808 LOperand* temp() { return temps_[0]; }
1809
1810 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixedDouble, "load-keyed-fixed-double");
1811 };
1812
1813
1814 class LLoadKeyedGeneric final : public LTemplateInstruction<1, 3, 1> {
1815 public:
1816 LLoadKeyedGeneric(LOperand* context, LOperand* object, LOperand* key,
1817 LOperand* vector) {
1818 inputs_[0] = context;
1819 inputs_[1] = object;
1820 inputs_[2] = key;
1821 temps_[0] = vector;
1822 }
1823
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]; }
1828
1829 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
1830 DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
1831 };
1832
1833
1834 class LLoadNamedGeneric final : public LTemplateInstruction<1, 2, 1> {
1835 public:
1836 LLoadNamedGeneric(LOperand* context, LOperand* object, LOperand* vector) {
1837 inputs_[0] = context;
1838 inputs_[1] = object;
1839 temps_[0] = vector;
1840 }
1841
1842 LOperand* context() { return inputs_[0]; }
1843 LOperand* object() { return inputs_[1]; }
1844 LOperand* temp_vector() { return temps_[0]; }
1845
1846 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
1847 DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
1848
1849 Handle<Object> name() const { return hydrogen()->name(); }
1850 };
1851
1852
1853 class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
1854 public:
1855 DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root")
1856 DECLARE_HYDROGEN_ACCESSOR(LoadRoot)
1857
1858 Heap::RootListIndex index() const { return hydrogen()->index(); }
1859 };
1860
1861
1862 class LMapEnumLength final : public LTemplateInstruction<1, 1, 0> {
1863 public:
1864 explicit LMapEnumLength(LOperand* value) {
1865 inputs_[0] = value;
1866 }
1867
1868 LOperand* value() { return inputs_[0]; }
1869
1870 DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length")
1871 };
1872
1873
1874 template<int T>
1875 class LUnaryMathOperation : public LTemplateInstruction<1, 1, T> {
1876 public:
1877 explicit LUnaryMathOperation(LOperand* value) {
1878 this->inputs_[0] = value;
1879 }
1880
1881 LOperand* value() { return this->inputs_[0]; }
1882 BuiltinFunctionId op() const { return this->hydrogen()->op(); }
1883
1884 void PrintDataTo(StringStream* stream) override;
1885
1886 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
1887 };
1888
1889
1890 class LMathAbs final : public LUnaryMathOperation<0> {
1891 public:
1892 explicit LMathAbs(LOperand* value) : LUnaryMathOperation<0>(value) {}
1893
1894 DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs")
1895 };
1896
1897
1898 class LMathAbsTagged: public LTemplateInstruction<1, 2, 3> {
1899 public:
1900 LMathAbsTagged(LOperand* context, LOperand* value,
1901 LOperand* temp1, LOperand* temp2, LOperand* temp3) {
1902 inputs_[0] = context;
1903 inputs_[1] = value;
1904 temps_[0] = temp1;
1905 temps_[1] = temp2;
1906 temps_[2] = temp3;
1907 }
1908
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]; }
1914
1915 DECLARE_CONCRETE_INSTRUCTION(MathAbsTagged, "math-abs-tagged")
1916 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
1917 };
1918
1919
1920 class LMathExp final : public LUnaryMathOperation<4> {
1921 public:
1922 LMathExp(LOperand* value,
1923 LOperand* double_temp1,
1924 LOperand* temp1,
1925 LOperand* temp2,
1926 LOperand* temp3)
1927 : LUnaryMathOperation<4>(value) {
1928 temps_[0] = double_temp1;
1929 temps_[1] = temp1;
1930 temps_[2] = temp2;
1931 temps_[3] = temp3;
1932 ExternalReference::InitializeMathExpData();
1933 }
1934
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]; }
1939
1940 DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
1941 };
1942
1943
1944 // Math.floor with a double result.
1945 class LMathFloorD final : public LUnaryMathOperation<0> {
1946 public:
1947 explicit LMathFloorD(LOperand* value) : LUnaryMathOperation<0>(value) { }
1948 DECLARE_CONCRETE_INSTRUCTION(MathFloorD, "math-floor-d")
1949 };
1950
1951
1952 // Math.floor with an integer result.
1953 class LMathFloorI final : public LUnaryMathOperation<0> {
1954 public:
1955 explicit LMathFloorI(LOperand* value) : LUnaryMathOperation<0>(value) { }
1956 DECLARE_CONCRETE_INSTRUCTION(MathFloorI, "math-floor-i")
1957 };
1958
1959
1960 class LFlooringDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
1961 public:
1962 LFlooringDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
1963 inputs_[0] = dividend;
1964 divisor_ = divisor;
1965 }
1966
1967 LOperand* dividend() { return inputs_[0]; }
1968 int32_t divisor() const { return divisor_; }
1969
1970 DECLARE_CONCRETE_INSTRUCTION(FlooringDivByPowerOf2I,
1971 "flooring-div-by-power-of-2-i")
1972 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
1973
1974 private:
1975 int32_t divisor_;
1976 };
1977
1978
1979 class LFlooringDivByConstI final : public LTemplateInstruction<1, 1, 2> {
1980 public:
1981 LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
1982 inputs_[0] = dividend;
1983 divisor_ = divisor;
1984 temps_[0] = temp;
1985 }
1986
1987 LOperand* dividend() { return inputs_[0]; }
1988 int32_t divisor() const { return divisor_; }
1989 LOperand* temp() { return temps_[0]; }
1990
1991 DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
1992 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
1993
1994 private:
1995 int32_t divisor_;
1996 };
1997
1998
1999 class LFlooringDivI final : public LTemplateInstruction<1, 2, 1> {
2000 public:
2001 LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
2002 inputs_[0] = dividend;
2003 inputs_[1] = divisor;
2004 temps_[0] = temp;
2005 }
2006
2007 LOperand* dividend() { return inputs_[0]; }
2008 LOperand* divisor() { return inputs_[1]; }
2009 LOperand* temp() { return temps_[0]; }
2010
2011 DECLARE_CONCRETE_INSTRUCTION(FlooringDivI, "flooring-div-i")
2012 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
2013 };
2014
2015
2016 class LMathLog final : public LUnaryMathOperation<0> {
2017 public:
2018 explicit LMathLog(LOperand* value) : LUnaryMathOperation<0>(value) { }
2019 DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
2020 };
2021
2022
2023 class LMathClz32 final : public LUnaryMathOperation<0> {
2024 public:
2025 explicit LMathClz32(LOperand* value) : LUnaryMathOperation<0>(value) { }
2026 DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
2027 };
2028
2029
2030 class LMathMinMax final : public LTemplateInstruction<1, 2, 0> {
2031 public:
2032 LMathMinMax(LOperand* left, LOperand* right) {
2033 inputs_[0] = left;
2034 inputs_[1] = right;
2035 }
2036
2037 LOperand* left() { return inputs_[0]; }
2038 LOperand* right() { return inputs_[1]; }
2039
2040 DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max")
2041 DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
2042 };
2043
2044
2045 class LMathPowHalf final : public LUnaryMathOperation<0> {
2046 public:
2047 explicit LMathPowHalf(LOperand* value) : LUnaryMathOperation<0>(value) { }
2048 DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half")
2049 };
2050
2051
2052 // Math.round with an integer result.
2053 class LMathRoundD final : public LUnaryMathOperation<0> {
2054 public:
2055 explicit LMathRoundD(LOperand* value)
2056 : LUnaryMathOperation<0>(value) {
2057 }
2058
2059 DECLARE_CONCRETE_INSTRUCTION(MathRoundD, "math-round-d")
2060 };
2061
2062
2063 // Math.round with an integer result.
2064 class LMathRoundI final : public LUnaryMathOperation<1> {
2065 public:
2066 LMathRoundI(LOperand* value, LOperand* temp1)
2067 : LUnaryMathOperation<1>(value) {
2068 temps_[0] = temp1;
2069 }
2070
2071 LOperand* temp1() { return temps_[0]; }
2072
2073 DECLARE_CONCRETE_INSTRUCTION(MathRoundI, "math-round-i")
2074 };
2075
2076
2077 class LMathFround final : public LUnaryMathOperation<0> {
2078 public:
2079 explicit LMathFround(LOperand* value) : LUnaryMathOperation<0>(value) {}
2080
2081 DECLARE_CONCRETE_INSTRUCTION(MathFround, "math-fround")
2082 };
2083
2084
2085 class LMathSqrt final : public LUnaryMathOperation<0> {
2086 public:
2087 explicit LMathSqrt(LOperand* value) : LUnaryMathOperation<0>(value) { }
2088 DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt")
2089 };
2090
2091
2092 class LModByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
2093 public:
2094 LModByPowerOf2I(LOperand* dividend, int32_t divisor) {
2095 inputs_[0] = dividend;
2096 divisor_ = divisor;
2097 }
2098
2099 LOperand* dividend() { return inputs_[0]; }
2100 int32_t divisor() const { return divisor_; }
2101
2102 DECLARE_CONCRETE_INSTRUCTION(ModByPowerOf2I, "mod-by-power-of-2-i")
2103 DECLARE_HYDROGEN_ACCESSOR(Mod)
2104
2105 private:
2106 int32_t divisor_;
2107 };
2108
2109
2110 class LModByConstI final : public LTemplateInstruction<1, 1, 1> {
2111 public:
2112 LModByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
2113 inputs_[0] = dividend;
2114 divisor_ = divisor;
2115 temps_[0] = temp;
2116 }
2117
2118 LOperand* dividend() { return inputs_[0]; }
2119 int32_t divisor() const { return divisor_; }
2120 LOperand* temp() { return temps_[0]; }
2121
2122 DECLARE_CONCRETE_INSTRUCTION(ModByConstI, "mod-by-const-i")
2123 DECLARE_HYDROGEN_ACCESSOR(Mod)
2124
2125 private:
2126 int32_t divisor_;
2127 };
2128
2129
2130 class LModI final : public LTemplateInstruction<1, 2, 0> {
2131 public:
2132 LModI(LOperand* left, LOperand* right) {
2133 inputs_[0] = left;
2134 inputs_[1] = right;
2135 }
2136
2137 LOperand* left() { return inputs_[0]; }
2138 LOperand* right() { return inputs_[1]; }
2139
2140 DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
2141 DECLARE_HYDROGEN_ACCESSOR(Mod)
2142 };
2143
2144
2145 class LMulConstIS final : public LTemplateInstruction<1, 2, 0> {
2146 public:
2147 LMulConstIS(LOperand* left, LConstantOperand* right) {
2148 inputs_[0] = left;
2149 inputs_[1] = right;
2150 }
2151
2152 LOperand* left() { return inputs_[0]; }
2153 LConstantOperand* right() { return LConstantOperand::cast(inputs_[1]); }
2154
2155 DECLARE_CONCRETE_INSTRUCTION(MulConstIS, "mul-const-i-s")
2156 DECLARE_HYDROGEN_ACCESSOR(Mul)
2157 };
2158
2159
2160 class LMulI final : public LTemplateInstruction<1, 2, 0> {
2161 public:
2162 LMulI(LOperand* left, LOperand* right) {
2163 inputs_[0] = left;
2164 inputs_[1] = right;
2165 }
2166
2167 LOperand* left() { return inputs_[0]; }
2168 LOperand* right() { return inputs_[1]; }
2169
2170 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
2171 DECLARE_HYDROGEN_ACCESSOR(Mul)
2172 };
2173
2174
2175 class LMulS final : public LTemplateInstruction<1, 2, 0> {
2176 public:
2177 LMulS(LOperand* left, LOperand* right) {
2178 inputs_[0] = left;
2179 inputs_[1] = right;
2180 }
2181
2182 LOperand* left() { return inputs_[0]; }
2183 LOperand* right() { return inputs_[1]; }
2184
2185 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-s")
2186 DECLARE_HYDROGEN_ACCESSOR(Mul)
2187 };
2188
2189
2190 class LNumberTagD final : public LTemplateInstruction<1, 1, 2> {
2191 public:
2192 LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2) {
2193 inputs_[0] = value;
2194 temps_[0] = temp1;
2195 temps_[1] = temp2;
2196 }
2197
2198 LOperand* value() { return inputs_[0]; }
2199 LOperand* temp1() { return temps_[0]; }
2200 LOperand* temp2() { return temps_[1]; }
2201
2202 DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
2203 DECLARE_HYDROGEN_ACCESSOR(Change)
2204 };
2205
2206
2207 class LNumberTagU final : public LTemplateInstruction<1, 1, 2> {
2208 public:
2209 explicit LNumberTagU(LOperand* value,
2210 LOperand* temp1,
2211 LOperand* temp2) {
2212 inputs_[0] = value;
2213 temps_[0] = temp1;
2214 temps_[1] = temp2;
2215 }
2216
2217 LOperand* value() { return inputs_[0]; }
2218 LOperand* temp1() { return temps_[0]; }
2219 LOperand* temp2() { return temps_[1]; }
2220
2221 DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
2222 };
2223
2224
2225 class LNumberUntagD final : public LTemplateInstruction<1, 1, 1> {
2226 public:
2227 LNumberUntagD(LOperand* value, LOperand* temp) {
2228 inputs_[0] = value;
2229 temps_[0] = temp;
2230 }
2231
2232 LOperand* value() { return inputs_[0]; }
2233
2234 LOperand* temp() { return temps_[0]; }
2235
2236 DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
2237 DECLARE_HYDROGEN_ACCESSOR(Change)
2238 };
2239
2240
2241 class LParameter final : public LTemplateInstruction<1, 0, 0> {
2242 public:
2243 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
2244 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2245 };
2246
2247
2248 class LPower final : public LTemplateInstruction<1, 2, 0> {
2249 public:
2250 LPower(LOperand* left, LOperand* right) {
2251 inputs_[0] = left;
2252 inputs_[1] = right;
2253 }
2254
2255 LOperand* left() { return inputs_[0]; }
2256 LOperand* right() { return inputs_[1]; }
2257
2258 DECLARE_CONCRETE_INSTRUCTION(Power, "power")
2259 DECLARE_HYDROGEN_ACCESSOR(Power)
2260 };
2261
2262
2263 class LPreparePushArguments final : public LTemplateInstruction<0, 0, 0> {
2264 public:
2265 explicit LPreparePushArguments(int argc) : argc_(argc) {}
2266
2267 inline int argc() const { return argc_; }
2268
2269 DECLARE_CONCRETE_INSTRUCTION(PreparePushArguments, "prepare-push-arguments")
2270
2271 protected:
2272 int argc_;
2273 };
2274
2275
2276 class LPushArguments final : public LTemplateResultInstruction<0> {
2277 public:
2278 explicit LPushArguments(Zone* zone,
2279 int capacity = kRecommendedMaxPushedArgs)
2280 : zone_(zone), inputs_(capacity, zone) {}
2281
2282 LOperand* argument(int i) { return inputs_[i]; }
2283 int ArgumentCount() const { return inputs_.length(); }
2284
2285 void AddArgument(LOperand* arg) { inputs_.Add(arg, zone_); }
2286
2287 DECLARE_CONCRETE_INSTRUCTION(PushArguments, "push-arguments")
2288
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;
2294 }
2295
2296 protected:
2297 Zone* zone_;
2298 ZoneList<LOperand*> inputs_;
2299
2300 private:
2301 // Iterator support.
2302 int InputCount() final { return inputs_.length(); }
2303 LOperand* InputAt(int i) final { return inputs_[i]; }
2304
2305 int TempCount() final { return 0; }
2306 LOperand* TempAt(int i) final { return NULL; }
2307 };
2308
2309
2310 class LRegExpLiteral final : public LTemplateInstruction<1, 1, 0> {
2311 public:
2312 explicit LRegExpLiteral(LOperand* context) {
2313 inputs_[0] = context;
2314 }
2315
2316 LOperand* context() { return inputs_[0]; }
2317
2318 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
2319 DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
2320 };
2321
2322
2323 class LReturn final : public LTemplateInstruction<0, 3, 0> {
2324 public:
2325 LReturn(LOperand* value, LOperand* context, LOperand* parameter_count) {
2326 inputs_[0] = value;
2327 inputs_[1] = context;
2328 inputs_[2] = parameter_count;
2329 }
2330
2331 LOperand* value() { return inputs_[0]; }
2332 LOperand* parameter_count() { return inputs_[2]; }
2333
2334 bool has_constant_parameter_count() {
2335 return parameter_count()->IsConstantOperand();
2336 }
2337 LConstantOperand* constant_parameter_count() {
2338 DCHECK(has_constant_parameter_count());
2339 return LConstantOperand::cast(parameter_count());
2340 }
2341
2342 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
2343 };
2344
2345
2346 class LSeqStringGetChar final : public LTemplateInstruction<1, 2, 1> {
2347 public:
2348 LSeqStringGetChar(LOperand* string,
2349 LOperand* index,
2350 LOperand* temp) {
2351 inputs_[0] = string;
2352 inputs_[1] = index;
2353 temps_[0] = temp;
2354 }
2355
2356 LOperand* string() { return inputs_[0]; }
2357 LOperand* index() { return inputs_[1]; }
2358 LOperand* temp() { return temps_[0]; }
2359
2360 DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char")
2361 DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar)
2362 };
2363
2364
2365 class LSeqStringSetChar final : public LTemplateInstruction<1, 4, 1> {
2366 public:
2367 LSeqStringSetChar(LOperand* context,
2368 LOperand* string,
2369 LOperand* index,
2370 LOperand* value,
2371 LOperand* temp) {
2372 inputs_[0] = context;
2373 inputs_[1] = string;
2374 inputs_[2] = index;
2375 inputs_[3] = value;
2376 temps_[0] = temp;
2377 }
2378
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]; }
2384
2385 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
2386 DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
2387 };
2388
2389
2390 class LSmiTag final : public LTemplateInstruction<1, 1, 0> {
2391 public:
2392 explicit LSmiTag(LOperand* value) {
2393 inputs_[0] = value;
2394 }
2395
2396 LOperand* value() { return inputs_[0]; }
2397
2398 DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
2399 DECLARE_HYDROGEN_ACCESSOR(Change)
2400 };
2401
2402
2403 class LSmiUntag final : public LTemplateInstruction<1, 1, 0> {
2404 public:
2405 LSmiUntag(LOperand* value, bool needs_check)
2406 : needs_check_(needs_check) {
2407 inputs_[0] = value;
2408 }
2409
2410 LOperand* value() { return inputs_[0]; }
2411 bool needs_check() const { return needs_check_; }
2412
2413 DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
2414
2415 private:
2416 bool needs_check_;
2417 };
2418
2419
2420 class LStackCheck final : public LTemplateInstruction<0, 1, 0> {
2421 public:
2422 explicit LStackCheck(LOperand* context) {
2423 inputs_[0] = context;
2424 }
2425
2426 LOperand* context() { return inputs_[0]; }
2427
2428 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
2429 DECLARE_HYDROGEN_ACCESSOR(StackCheck)
2430
2431 Label* done_label() { return &done_label_; }
2432
2433 private:
2434 Label done_label_;
2435 };
2436
2437
2438 class LStoreGlobalViaContext final : public LTemplateInstruction<0, 2, 0> {
2439 public:
2440 LStoreGlobalViaContext(LOperand* context, LOperand* value) {
2441 inputs_[0] = context;
2442 inputs_[1] = value;
2443 }
2444
2445 LOperand* context() { return inputs_[0]; }
2446 LOperand* value() { return inputs_[1]; }
2447
2448 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalViaContext,
2449 "store-global-via-context")
2450 DECLARE_HYDROGEN_ACCESSOR(StoreGlobalViaContext)
2451
2452 void PrintDataTo(StringStream* stream) override;
2453
2454 int depth() { return hydrogen()->depth(); }
2455 int slot_index() { return hydrogen()->slot_index(); }
2456 LanguageMode language_mode() { return hydrogen()->language_mode(); }
2457 };
2458
2459
2460 template<int T>
2461 class LStoreKeyed : public LTemplateInstruction<0, 3, T> {
2462 public:
2463 LStoreKeyed(LOperand* elements, LOperand* key, LOperand* value) {
2464 this->inputs_[0] = elements;
2465 this->inputs_[1] = key;
2466 this->inputs_[2] = value;
2467 }
2468
2469 bool is_external() const { return this->hydrogen()->is_external(); }
2470 bool is_fixed_typed_array() const {
2471 return hydrogen()->is_fixed_typed_array();
2472 }
2473 bool is_typed_elements() const {
2474 return is_external() || is_fixed_typed_array();
2475 }
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();
2481 }
2482
2483 bool NeedsCanonicalization() {
2484 if (hydrogen()->value()->IsAdd() || hydrogen()->value()->IsSub() ||
2485 hydrogen()->value()->IsMul() || hydrogen()->value()->IsDiv()) {
2486 return false;
2487 }
2488 return this->hydrogen()->NeedsCanonicalization();
2489 }
2490 uint32_t base_offset() const { return this->hydrogen()->base_offset(); }
2491
2492 void PrintDataTo(StringStream* stream) override {
2493 this->elements()->PrintTo(stream);
2494 stream->Add("[");
2495 this->key()->PrintTo(stream);
2496 if (this->base_offset() != 0) {
2497 stream->Add(" + %d] <-", this->base_offset());
2498 } else {
2499 stream->Add("] <- ");
2500 }
2501
2502 if (this->value() == NULL) {
2503 DCHECK(hydrogen()->IsConstantHoleStore() &&
2504 hydrogen()->value()->representation().IsDouble());
2505 stream->Add("<the hole(nan)>");
2506 } else {
2507 this->value()->PrintTo(stream);
2508 }
2509 }
2510
2511 DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
2512 };
2513
2514
2515 class LStoreKeyedExternal final : public LStoreKeyed<1> {
2516 public:
2517 LStoreKeyedExternal(LOperand* elements, LOperand* key, LOperand* value,
2518 LOperand* temp) :
2519 LStoreKeyed<1>(elements, key, value) {
2520 temps_[0] = temp;
2521 }
2522
2523 LOperand* temp() { return temps_[0]; }
2524
2525 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedExternal, "store-keyed-external")
2526 };
2527
2528
2529 class LStoreKeyedFixed final : public LStoreKeyed<1> {
2530 public:
2531 LStoreKeyedFixed(LOperand* elements, LOperand* key, LOperand* value,
2532 LOperand* temp) :
2533 LStoreKeyed<1>(elements, key, value) {
2534 temps_[0] = temp;
2535 }
2536
2537 LOperand* temp() { return temps_[0]; }
2538
2539 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixed, "store-keyed-fixed")
2540 };
2541
2542
2543 class LStoreKeyedFixedDouble final : public LStoreKeyed<1> {
2544 public:
2545 LStoreKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* value,
2546 LOperand* temp) :
2547 LStoreKeyed<1>(elements, key, value) {
2548 temps_[0] = temp;
2549 }
2550
2551 LOperand* temp() { return temps_[0]; }
2552
2553 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixedDouble,
2554 "store-keyed-fixed-double")
2555 };
2556
2557
2558 class LStoreKeyedGeneric final : public LTemplateInstruction<0, 4, 2> {
2559 public:
2560 LStoreKeyedGeneric(LOperand* context, LOperand* object, LOperand* key,
2561 LOperand* value, LOperand* slot, LOperand* vector) {
2562 inputs_[0] = context;
2563 inputs_[1] = object;
2564 inputs_[2] = key;
2565 inputs_[3] = value;
2566 temps_[0] = slot;
2567 temps_[1] = vector;
2568 }
2569
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]; }
2576
2577 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
2578 DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
2579
2580 void PrintDataTo(StringStream* stream) override;
2581
2582 LanguageMode language_mode() { return hydrogen()->language_mode(); }
2583 };
2584
2585
2586 class LStoreNamedField final : public LTemplateInstruction<0, 2, 2> {
2587 public:
2588 LStoreNamedField(LOperand* object, LOperand* value,
2589 LOperand* temp0, LOperand* temp1) {
2590 inputs_[0] = object;
2591 inputs_[1] = value;
2592 temps_[0] = temp0;
2593 temps_[1] = temp1;
2594 }
2595
2596 LOperand* object() { return inputs_[0]; }
2597 LOperand* value() { return inputs_[1]; }
2598 LOperand* temp0() { return temps_[0]; }
2599 LOperand* temp1() { return temps_[1]; }
2600
2601 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
2602 DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
2603
2604 void PrintDataTo(StringStream* stream) override;
2605
2606 Representation representation() const {
2607 return hydrogen()->field_representation();
2608 }
2609 };
2610
2611
2612 class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
2613 public:
2614 LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value,
2615 LOperand* slot, LOperand* vector) {
2616 inputs_[0] = context;
2617 inputs_[1] = object;
2618 inputs_[2] = value;
2619 temps_[0] = slot;
2620 temps_[1] = vector;
2621 }
2622
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]; }
2628
2629 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
2630 DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
2631
2632 void PrintDataTo(StringStream* stream) override;
2633
2634 Handle<Object> name() const { return hydrogen()->name(); }
2635 LanguageMode language_mode() { return hydrogen()->language_mode(); }
2636 };
2637
2638
2639 class LMaybeGrowElements final : public LTemplateInstruction<1, 5, 0> {
2640 public:
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;
2646 inputs_[3] = key;
2647 inputs_[4] = current_capacity;
2648 }
2649
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]; }
2655
2656 DECLARE_HYDROGEN_ACCESSOR(MaybeGrowElements)
2657 DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements, "maybe-grow-elements")
2658 };
2659
2660
2661 class LStringAdd final : public LTemplateInstruction<1, 3, 0> {
2662 public:
2663 LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
2664 inputs_[0] = context;
2665 inputs_[1] = left;
2666 inputs_[2] = right;
2667 }
2668
2669 LOperand* context() { return inputs_[0]; }
2670 LOperand* left() { return inputs_[1]; }
2671 LOperand* right() { return inputs_[2]; }
2672
2673 DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
2674 DECLARE_HYDROGEN_ACCESSOR(StringAdd)
2675 };
2676
2677
2678 class LStringCharCodeAt final : public LTemplateInstruction<1, 3, 0> {
2679 public:
2680 LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
2681 inputs_[0] = context;
2682 inputs_[1] = string;
2683 inputs_[2] = index;
2684 }
2685
2686 LOperand* context() { return inputs_[0]; }
2687 LOperand* string() { return inputs_[1]; }
2688 LOperand* index() { return inputs_[2]; }
2689
2690 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
2691 DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
2692 };
2693
2694
2695 class LStringCharFromCode final : public LTemplateInstruction<1, 2, 0> {
2696 public:
2697 LStringCharFromCode(LOperand* context, LOperand* char_code) {
2698 inputs_[0] = context;
2699 inputs_[1] = char_code;
2700 }
2701
2702 LOperand* context() { return inputs_[0]; }
2703 LOperand* char_code() { return inputs_[1]; }
2704
2705 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
2706 DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
2707 };
2708
2709
2710 class LStringCompareAndBranch final : public LControlInstruction<3, 0> {
2711 public:
2712 LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) {
2713 inputs_[0] = context;
2714 inputs_[1] = left;
2715 inputs_[2] = right;
2716 }
2717
2718 LOperand* context() { return inputs_[0]; }
2719 LOperand* left() { return inputs_[1]; }
2720 LOperand* right() { return inputs_[2]; }
2721
2722 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
2723 "string-compare-and-branch")
2724 DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
2725
2726 Token::Value op() const { return hydrogen()->token(); }
2727
2728 void PrintDataTo(StringStream* stream) override;
2729 };
2730
2731
2732 // Truncating conversion from a tagged value to an int32.
2733 class LTaggedToI final : public LTemplateInstruction<1, 1, 2> {
2734 public:
2735 explicit LTaggedToI(LOperand* value, LOperand* temp1, LOperand* temp2) {
2736 inputs_[0] = value;
2737 temps_[0] = temp1;
2738 temps_[1] = temp2;
2739 }
2740
2741 LOperand* value() { return inputs_[0]; }
2742 LOperand* temp1() { return temps_[0]; }
2743 LOperand* temp2() { return temps_[1]; }
2744
2745 DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
2746 DECLARE_HYDROGEN_ACCESSOR(Change)
2747
2748 bool truncating() { return hydrogen()->CanTruncateToInt32(); }
2749 };
2750
2751
2752 class LShiftI final : public LTemplateInstruction<1, 2, 0> {
2753 public:
2754 LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
2755 : op_(op), can_deopt_(can_deopt) {
2756 inputs_[0] = left;
2757 inputs_[1] = right;
2758 }
2759
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_; }
2764
2765 DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")
2766
2767 private:
2768 Token::Value op_;
2769 bool can_deopt_;
2770 };
2771
2772
2773 class LShiftS final : public LTemplateInstruction<1, 2, 0> {
2774 public:
2775 LShiftS(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
2776 : op_(op), can_deopt_(can_deopt) {
2777 inputs_[0] = left;
2778 inputs_[1] = right;
2779 }
2780
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_; }
2785
2786 DECLARE_CONCRETE_INSTRUCTION(ShiftS, "shift-s")
2787
2788 private:
2789 Token::Value op_;
2790 bool can_deopt_;
2791 };
2792
2793
2794 class LStoreCodeEntry final : public LTemplateInstruction<0, 2, 1> {
2795 public:
2796 LStoreCodeEntry(LOperand* function, LOperand* code_object,
2797 LOperand* temp) {
2798 inputs_[0] = function;
2799 inputs_[1] = code_object;
2800 temps_[0] = temp;
2801 }
2802
2803 LOperand* function() { return inputs_[0]; }
2804 LOperand* code_object() { return inputs_[1]; }
2805 LOperand* temp() { return temps_[0]; }
2806
2807 void PrintDataTo(StringStream* stream) override;
2808
2809 DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
2810 DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
2811 };
2812
2813
2814 class LStoreContextSlot final : public LTemplateInstruction<0, 2, 1> {
2815 public:
2816 LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
2817 inputs_[0] = context;
2818 inputs_[1] = value;
2819 temps_[0] = temp;
2820 }
2821
2822 LOperand* context() { return inputs_[0]; }
2823 LOperand* value() { return inputs_[1]; }
2824 LOperand* temp() { return temps_[0]; }
2825
2826 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
2827 DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
2828
2829 int slot_index() { return hydrogen()->slot_index(); }
2830
2831 void PrintDataTo(StringStream* stream) override;
2832 };
2833
2834
2835 class LSubI final : public LTemplateInstruction<1, 2, 0> {
2836 public:
2837 LSubI(LOperand* left, LOperand* right)
2838 : shift_(NO_SHIFT), shift_amount_(0) {
2839 inputs_[0] = left;
2840 inputs_[1] = right;
2841 }
2842
2843 LSubI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
2844 : shift_(shift), shift_amount_(shift_amount) {
2845 inputs_[0] = left;
2846 inputs_[1] = right;
2847 }
2848
2849 LOperand* left() { return inputs_[0]; }
2850 LOperand* right() { return inputs_[1]; }
2851
2852 Shift shift() const { return shift_; }
2853 LOperand* shift_amount() const { return shift_amount_; }
2854
2855 DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
2856 DECLARE_HYDROGEN_ACCESSOR(Sub)
2857
2858 protected:
2859 Shift shift_;
2860 LOperand* shift_amount_;
2861 };
2862
2863
2864 class LSubS: public LTemplateInstruction<1, 2, 0> {
2865 public:
2866 LSubS(LOperand* left, LOperand* right) {
2867 inputs_[0] = left;
2868 inputs_[1] = right;
2869 }
2870
2871 LOperand* left() { return inputs_[0]; }
2872 LOperand* right() { return inputs_[1]; }
2873
2874 DECLARE_CONCRETE_INSTRUCTION(SubS, "sub-s")
2875 DECLARE_HYDROGEN_ACCESSOR(Sub)
2876 };
2877
2878
2879 class LThisFunction final : public LTemplateInstruction<1, 0, 0> {
2880 public:
2881 DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
2882 DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
2883 };
2884
2885
2886 class LToFastProperties final : public LTemplateInstruction<1, 1, 0> {
2887 public:
2888 explicit LToFastProperties(LOperand* value) {
2889 inputs_[0] = value;
2890 }
2891
2892 LOperand* value() { return inputs_[0]; }
2893
2894 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
2895 DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
2896 };
2897
2898
2899 class LTransitionElementsKind final : public LTemplateInstruction<0, 2, 2> {
2900 public:
2901 LTransitionElementsKind(LOperand* object,
2902 LOperand* context,
2903 LOperand* temp1,
2904 LOperand* temp2) {
2905 inputs_[0] = object;
2906 inputs_[1] = context;
2907 temps_[0] = temp1;
2908 temps_[1] = temp2;
2909 }
2910
2911 LOperand* object() { return inputs_[0]; }
2912 LOperand* context() { return inputs_[1]; }
2913 LOperand* temp1() { return temps_[0]; }
2914 LOperand* temp2() { return temps_[1]; }
2915
2916 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
2917 "transition-elements-kind")
2918 DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
2919
2920 void PrintDataTo(StringStream* stream) override;
2921
2922 Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
2923 Handle<Map> transitioned_map() {
2924 return hydrogen()->transitioned_map().handle();
2925 }
2926 ElementsKind from_kind() const { return hydrogen()->from_kind(); }
2927 ElementsKind to_kind() const { return hydrogen()->to_kind(); }
2928 };
2929
2930
2931 class LTrapAllocationMemento final : public LTemplateInstruction<0, 1, 2> {
2932 public:
2933 LTrapAllocationMemento(LOperand* object, LOperand* temp1, LOperand* temp2) {
2934 inputs_[0] = object;
2935 temps_[0] = temp1;
2936 temps_[1] = temp2;
2937 }
2938
2939 LOperand* object() { return inputs_[0]; }
2940 LOperand* temp1() { return temps_[0]; }
2941 LOperand* temp2() { return temps_[1]; }
2942
2943 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento, "trap-allocation-memento")
2944 };
2945
2946
2947 class LTruncateDoubleToIntOrSmi final : public LTemplateInstruction<1, 1, 0> {
2948 public:
2949 explicit LTruncateDoubleToIntOrSmi(LOperand* value) {
2950 inputs_[0] = value;
2951 }
2952
2953 LOperand* value() { return inputs_[0]; }
2954
2955 DECLARE_CONCRETE_INSTRUCTION(TruncateDoubleToIntOrSmi,
2956 "truncate-double-to-int-or-smi")
2957 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
2958
2959 bool tag_result() { return hydrogen()->representation().IsSmi(); }
2960 };
2961
2962
2963 class LTypeof final : public LTemplateInstruction<1, 2, 0> {
2964 public:
2965 LTypeof(LOperand* context, LOperand* value) {
2966 inputs_[0] = context;
2967 inputs_[1] = value;
2968 }
2969
2970 LOperand* context() { return inputs_[0]; }
2971 LOperand* value() { return inputs_[1]; }
2972
2973 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
2974 };
2975
2976
2977 class LTypeofIsAndBranch final : public LControlInstruction<1, 2> {
2978 public:
2979 LTypeofIsAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
2980 inputs_[0] = value;
2981 temps_[0] = temp1;
2982 temps_[1] = temp2;
2983 }
2984
2985 LOperand* value() { return inputs_[0]; }
2986 LOperand* temp1() { return temps_[0]; }
2987 LOperand* temp2() { return temps_[1]; }
2988
2989 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
2990 DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
2991
2992 Handle<String> type_literal() const { return hydrogen()->type_literal(); }
2993
2994 void PrintDataTo(StringStream* stream) override;
2995 };
2996
2997
2998 class LUint32ToDouble final : public LTemplateInstruction<1, 1, 0> {
2999 public:
3000 explicit LUint32ToDouble(LOperand* value) {
3001 inputs_[0] = value;
3002 }
3003
3004 LOperand* value() { return inputs_[0]; }
3005
3006 DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
3007 };
3008
3009
3010 class LCheckMapValue final : public LTemplateInstruction<0, 2, 1> {
3011 public:
3012 LCheckMapValue(LOperand* value, LOperand* map, LOperand* temp) {
3013 inputs_[0] = value;
3014 inputs_[1] = map;
3015 temps_[0] = temp;
3016 }
3017
3018 LOperand* value() { return inputs_[0]; }
3019 LOperand* map() { return inputs_[1]; }
3020 LOperand* temp() { return temps_[0]; }
3021
3022 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
3023 };
3024
3025
3026 class LLoadFieldByIndex final : public LTemplateInstruction<1, 2, 0> {
3027 public:
3028 LLoadFieldByIndex(LOperand* object, LOperand* index) {
3029 inputs_[0] = object;
3030 inputs_[1] = index;
3031 }
3032
3033 LOperand* object() { return inputs_[0]; }
3034 LOperand* index() { return inputs_[1]; }
3035
3036 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
3037 };
3038
3039
3040 class LStoreFrameContext: public LTemplateInstruction<0, 1, 0> {
3041 public:
3042 explicit LStoreFrameContext(LOperand* context) {
3043 inputs_[0] = context;
3044 }
3045
3046 LOperand* context() { return inputs_[0]; }
3047
3048 DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext, "store-frame-context")
3049 };
3050
3051
3052 class LAllocateBlockContext: public LTemplateInstruction<1, 2, 0> {
3053 public:
3054 LAllocateBlockContext(LOperand* context, LOperand* function) {
3055 inputs_[0] = context;
3056 inputs_[1] = function;
3057 }
3058
3059 LOperand* context() { return inputs_[0]; }
3060 LOperand* function() { return inputs_[1]; }
3061
3062 Handle<ScopeInfo> scope_info() { return hydrogen()->scope_info(); }
3063
3064 DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext, "allocate-block-context")
3065 DECLARE_HYDROGEN_ACCESSOR(AllocateBlockContext)
3066 };
3067
3068
3069 class LWrapReceiver final : public LTemplateInstruction<1, 2, 0> {
3070 public:
3071 LWrapReceiver(LOperand* receiver, LOperand* function) {
3072 inputs_[0] = receiver;
3073 inputs_[1] = function;
3074 }
3075
3076 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
3077 DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
3078
3079 LOperand* receiver() { return inputs_[0]; }
3080 LOperand* function() { return inputs_[1]; }
3081 };
3082
3083
3084 class LChunkBuilder;
3085 class LPlatformChunk final : public LChunk {
3086 public:
3087 LPlatformChunk(CompilationInfo* info, HGraph* graph)
3088 : LChunk(info, graph) { }
3089
3090 int GetNextSpillIndex();
3091 LOperand* GetNextSpillSlot(RegisterKind kind);
3092 };
3093
3094
3095 class LChunkBuilder final : public LChunkBuilderBase {
3096 public:
3097 LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
3098 : LChunkBuilderBase(info, graph),
3099 current_instruction_(NULL),
3100 current_block_(NULL),
3101 allocator_(allocator) {}
3102
3103 // Build the sequence for the graph.
3104 LPlatformChunk* Build();
3105
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)
3109 #undef DECLARE_DO
3110
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);
3120
3121 static bool HasMagicNumberForDivision(int32_t divisor);
3122
3123 private:
3124 // Methods for getting operands for Use / Define / Temp.
3125 LUnallocated* ToUnallocated(Register reg);
3126 LUnallocated* ToUnallocated(DoubleRegister reg);
3127
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);
3133
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);
3139
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.
3143 //
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);
3148
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
3152 // output).
3153 MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
3154
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);
3158
3159 // A constant operand.
3160 MUST_USE_RESULT LConstantOperand* UseConstant(HValue* value);
3161
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);
3165
3166 // Temporary operand that must be in a register.
3167 MUST_USE_RESULT LUnallocated* TempRegister();
3168
3169 // Temporary operand that must be in a double register.
3170 MUST_USE_RESULT LUnallocated* TempDoubleRegister();
3171
3172 MUST_USE_RESULT LOperand* FixedTemp(Register reg);
3173
3174 // Temporary operand that must be in a fixed double register.
3175 MUST_USE_RESULT LOperand* FixedTemp(DoubleRegister reg);
3176
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,
3183 int index);
3184
3185 LInstruction* DefineSameAsFirst(LTemplateResultInstruction<1>* instr);
3186 LInstruction* DefineFixed(LTemplateResultInstruction<1>* instr,
3187 Register reg);
3188 LInstruction* DefineFixedDouble(LTemplateResultInstruction<1>* instr,
3189 DoubleRegister reg);
3190
3191 enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };
3192
3193 // By default we assume that instruction sequences generated for calls
3194 // cannot deoptimize eagerly and we do not attach environment to this
3195 // instruction.
3196 LInstruction* MarkAsCall(
3197 LInstruction* instr,
3198 HInstruction* hinstr,
3199 CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
3200
3201 LInstruction* AssignPointerMap(LInstruction* instr);
3202 LInstruction* AssignEnvironment(LInstruction* instr);
3203
3204 void VisitInstruction(HInstruction* current);
3205 void AddInstruction(LInstruction* instr, HInstruction* current);
3206 void DoBasicBlock(HBasicBlock* block);
3207
3208 int JSShiftAmountFromHConstant(HValue* constant) {
3209 return HConstant::cast(constant)->Integer32Value() & 0x1f;
3210 }
3211 bool LikelyFitsImmField(HInstruction* instr, int imm) {
3212 if (instr->IsAdd() || instr->IsSub()) {
3213 return Assembler::IsImmAddSub(imm) || Assembler::IsImmAddSub(-imm);
3214 } else {
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);
3219 }
3220 }
3221
3222 // Indicates if a sequence of the form
3223 // lsl x8, x9, #imm
3224 // add x0, x1, x8
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,
3238 HValue* left,
3239 HBitwiseBinaryOperation* shift);
3240
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);
3246
3247 HInstruction* current_instruction_;
3248 HBasicBlock* current_block_;
3249 LAllocator* allocator_;
3250
3251 DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
3252 };
3253
3254 #undef DECLARE_HYDROGEN_ACCESSOR
3255 #undef DECLARE_CONCRETE_INSTRUCTION
3256
3257 } // namespace internal
3258 } // namespace v8
3259
3260 #endif // V8_ARM64_LITHIUM_ARM64_H_
OLDNEW
« no previous file with comments | « src/arm64/delayed-masm-arm64-inl.h ('k') | src/arm64/lithium-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698