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