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

Side by Side Diff: src/hydrogen-instructions.h

Issue 6529055: [Isolates] Merge crankshaft (r5922 from bleeding_edge). (Closed)
Patch Set: Win32 port Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/hydrogen.cc ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_
29 #define V8_HYDROGEN_INSTRUCTIONS_H_
30
31 #include "v8.h"
32 #include "code-stubs.h"
33 #include "string-stream.h"
34 #include "zone.h"
35
36 namespace v8 {
37 namespace internal {
38
39 // Forward declarations.
40 class HBasicBlock;
41 class HEnvironment;
42 class HInstruction;
43 class HLoopInformation;
44 class HValue;
45 class LInstruction;
46 class LChunkBuilder;
47
48
49 // Type hierarchy:
50 //
51 // HValue
52 // HInstruction
53 // HAccessArgumentsAt
54 // HApplyArguments
55 // HArgumentsElements
56 // HArgumentsLength
57 // HArgumentsObject
58 // HBinaryOperation
59 // HArithmeticBinaryOperation
60 // HAdd
61 // HDiv
62 // HMod
63 // HMul
64 // HSub
65 // HBitwiseBinaryOperation
66 // HBitAnd
67 // HBitOr
68 // HBitXor
69 // HSar
70 // HShl
71 // HShr
72 // HBoundsCheck
73 // HCompare
74 // HCompareJSObjectEq
75 // HInstanceOf
76 // HLoadKeyed
77 // HLoadKeyedFastElement
78 // HLoadKeyedGeneric
79 // HLoadNamedGeneric
80 // HStoreNamed
81 // HStoreNamedField
82 // HStoreNamedGeneric
83 // HBlockEntry
84 // HCall
85 // HCallConstantFunction
86 // HCallFunction
87 // HCallGlobal
88 // HCallKeyed
89 // HCallKnownGlobal
90 // HCallNamed
91 // HCallNew
92 // HCallRuntime
93 // HCallStub
94 // HConstant
95 // HControlInstruction
96 // HGoto
97 // HUnaryControlInstruction
98 // HBranch
99 // HCompareMapAndBranch
100 // HReturn
101 // HThrow
102 // HDeoptimize
103 // HEnterInlined
104 // HFunctionLiteral
105 // HGlobalObject
106 // HGlobalReceiver
107 // HLeaveInlined
108 // HLoadGlobal
109 // HMaterializedLiteral
110 // HArrayLiteral
111 // HObjectLiteral
112 // HRegExpLiteral
113 // HOsrEntry
114 // HParameter
115 // HSimulate
116 // HStackCheck
117 // HStoreKeyed
118 // HStoreKeyedFastElement
119 // HStoreKeyedGeneric
120 // HUnaryOperation
121 // HArrayLength
122 // HBitNot
123 // HChange
124 // HCheckFunction
125 // HCheckInstanceType
126 // HCheckMap
127 // HCheckNonSmi
128 // HCheckPrototypeMaps
129 // HCheckSmi
130 // HDeleteProperty
131 // HLoadElements
132 // HTypeofIs
133 // HLoadNamedField
134 // HPushArgument
135 // HTypeof
136 // HUnaryMathOperation
137 // HUnaryPredicate
138 // HClassOfTest
139 // HHasCachedArrayIndex
140 // HHasInstanceType
141 // HIsNull
142 // HIsSmi
143 // HValueOf
144 // HUnknownOSRValue
145 // HPhi
146
147 #define HYDROGEN_ALL_INSTRUCTION_LIST(V) \
148 V(ArithmeticBinaryOperation) \
149 V(BinaryOperation) \
150 V(BitwiseBinaryOperation) \
151 V(Call) \
152 V(ControlInstruction) \
153 V(Instruction) \
154 V(LoadKeyed) \
155 V(MaterializedLiteral) \
156 V(Phi) \
157 V(StoreKeyed) \
158 V(StoreNamed) \
159 V(UnaryControlInstruction) \
160 V(UnaryOperation) \
161 HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
162
163
164 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
165 V(AccessArgumentsAt) \
166 V(Add) \
167 V(ApplyArguments) \
168 V(ArgumentsElements) \
169 V(ArgumentsLength) \
170 V(ArgumentsObject) \
171 V(ArrayLength) \
172 V(ArrayLiteral) \
173 V(BitAnd) \
174 V(BitNot) \
175 V(BitOr) \
176 V(BitXor) \
177 V(BlockEntry) \
178 V(BoundsCheck) \
179 V(Branch) \
180 V(CallConstantFunction) \
181 V(CallFunction) \
182 V(CallGlobal) \
183 V(CallKeyed) \
184 V(CallKnownGlobal) \
185 V(CallNamed) \
186 V(CallNew) \
187 V(CallRuntime) \
188 V(CallStub) \
189 V(Change) \
190 V(CheckFunction) \
191 V(CheckInstanceType) \
192 V(CheckMap) \
193 V(CheckNonSmi) \
194 V(CheckPrototypeMaps) \
195 V(CheckSmi) \
196 V(Compare) \
197 V(CompareJSObjectEq) \
198 V(CompareMapAndBranch) \
199 V(Constant) \
200 V(DeleteProperty) \
201 V(Deoptimize) \
202 V(Div) \
203 V(EnterInlined) \
204 V(FunctionLiteral) \
205 V(GlobalObject) \
206 V(GlobalReceiver) \
207 V(Goto) \
208 V(InstanceOf) \
209 V(IsNull) \
210 V(IsSmi) \
211 V(HasInstanceType) \
212 V(HasCachedArrayIndex) \
213 V(ClassOfTest) \
214 V(LeaveInlined) \
215 V(LoadElements) \
216 V(LoadGlobal) \
217 V(LoadKeyedFastElement) \
218 V(LoadKeyedGeneric) \
219 V(LoadNamedField) \
220 V(LoadNamedGeneric) \
221 V(Mod) \
222 V(Mul) \
223 V(ObjectLiteral) \
224 V(OsrEntry) \
225 V(Parameter) \
226 V(PushArgument) \
227 V(RegExpLiteral) \
228 V(Return) \
229 V(Sar) \
230 V(Shl) \
231 V(Shr) \
232 V(Simulate) \
233 V(StackCheck) \
234 V(StoreGlobal) \
235 V(StoreKeyedFastElement) \
236 V(StoreKeyedGeneric) \
237 V(StoreNamedField) \
238 V(StoreNamedGeneric) \
239 V(Sub) \
240 V(Throw) \
241 V(Typeof) \
242 V(TypeofIs) \
243 V(UnaryMathOperation) \
244 V(UnknownOSRValue) \
245 V(ValueOf)
246
247 #define GVN_FLAG_LIST(V) \
248 V(Calls) \
249 V(InobjectFields) \
250 V(BackingStoreFields) \
251 V(ArrayElements) \
252 V(GlobalVars) \
253 V(Maps) \
254 V(ArrayLengths) \
255 V(OsrEntries)
256
257 #define DECLARE_INSTRUCTION(type) \
258 virtual bool Is##type() const { return true; } \
259 static H##type* cast(HValue* value) { \
260 ASSERT(value->Is##type()); \
261 return reinterpret_cast<H##type*>(value); \
262 } \
263 Opcode opcode() const { return HValue::k##type; }
264
265
266 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
267 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
268 virtual const char* Mnemonic() const { return mnemonic; } \
269 DECLARE_INSTRUCTION(type)
270
271
272
273 template<int kSize>
274 class HOperandVector : public EmbeddedVector<HValue*, kSize> {
275 public:
276 HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
277 };
278
279
280 class Range: public ZoneObject {
281 public:
282 Range() : lower_(kMinInt),
283 upper_(kMaxInt),
284 next_(NULL),
285 can_be_minus_zero_(false) { }
286
287 Range(int32_t lower, int32_t upper)
288 : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
289
290 bool IsInSmiRange() const {
291 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
292 }
293 void KeepOrder();
294 void Verify() const;
295 int32_t upper() const { return upper_; }
296 int32_t lower() const { return lower_; }
297 Range* next() const { return next_; }
298 Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
299 Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
300 void ClearLower() { lower_ = kMinInt; }
301 void ClearUpper() { upper_ = kMaxInt; }
302 Range* Copy() const { return new Range(lower_, upper_); }
303 bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
304 int32_t Mask() const;
305 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
306 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
307 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
308 bool CanBeNegative() const { return lower_ < 0; }
309 bool Includes(int value) const {
310 return lower_ <= value && upper_ >= value;
311 }
312
313 void Sar(int32_t value) {
314 int32_t bits = value & 0x1F;
315 lower_ = lower_ >> bits;
316 upper_ = upper_ >> bits;
317 set_can_be_minus_zero(false);
318 }
319
320 void Shl(int32_t value) {
321 int32_t bits = value & 0x1F;
322 int old_lower = lower_;
323 int old_upper = upper_;
324 lower_ = lower_ << bits;
325 upper_ = upper_ << bits;
326 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
327 upper_ = kMaxInt;
328 lower_ = kMinInt;
329 }
330 set_can_be_minus_zero(false);
331 }
332
333 void StackUpon(Range* other) {
334 Intersect(other);
335 next_ = other;
336 }
337
338 void Intersect(Range* other) {
339 upper_ = Min(upper_, other->upper_);
340 lower_ = Max(lower_, other->lower_);
341 bool b = CanBeMinusZero() && other->CanBeMinusZero();
342 set_can_be_minus_zero(b);
343 }
344
345 void Union(Range* other) {
346 upper_ = Max(upper_, other->upper_);
347 lower_ = Min(lower_, other->lower_);
348 bool b = CanBeMinusZero() || other->CanBeMinusZero();
349 set_can_be_minus_zero(b);
350 }
351
352 void Add(int32_t value);
353 bool AddAndCheckOverflow(Range* other);
354 bool SubAndCheckOverflow(Range* other);
355 bool MulAndCheckOverflow(Range* other);
356
357 private:
358 int32_t lower_;
359 int32_t upper_;
360 Range* next_;
361 bool can_be_minus_zero_;
362 };
363
364
365 class Representation {
366 public:
367 enum Kind {
368 kNone,
369 kTagged,
370 kDouble,
371 kInteger32,
372 kNumRepresentations
373 };
374
375 Representation() : kind_(kNone) { }
376
377 static Representation None() { return Representation(kNone); }
378 static Representation Tagged() { return Representation(kTagged); }
379 static Representation Integer32() { return Representation(kInteger32); }
380 static Representation Double() { return Representation(kDouble); }
381
382 bool Equals(const Representation& other) const {
383 return kind_ == other.kind_;
384 }
385
386 Kind kind() const { return kind_; }
387 bool IsNone() const { return kind_ == kNone; }
388 bool IsTagged() const { return kind_ == kTagged; }
389 bool IsInteger32() const { return kind_ == kInteger32; }
390 bool IsDouble() const { return kind_ == kDouble; }
391 bool IsSpecialization() const {
392 return kind_ == kInteger32 || kind_ == kDouble;
393 }
394 const char* Mnemonic() const;
395
396 private:
397 explicit Representation(Kind k) : kind_(k) { }
398
399 Kind kind_;
400 };
401
402
403 class HType {
404 public:
405 HType() : type_(kUninitialized) { }
406
407 static HType Tagged() { return HType(kTagged); }
408 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
409 static HType TaggedNumber() { return HType(kTaggedNumber); }
410 static HType Smi() { return HType(kSmi); }
411 static HType HeapNumber() { return HType(kHeapNumber); }
412 static HType String() { return HType(kString); }
413 static HType Boolean() { return HType(kBoolean); }
414 static HType NonPrimitive() { return HType(kNonPrimitive); }
415 static HType JSArray() { return HType(kJSArray); }
416 static HType JSObject() { return HType(kJSObject); }
417 static HType Uninitialized() { return HType(kUninitialized); }
418
419 // Return the weakest (least precise) common type.
420 HType Combine(HType other) {
421 return HType(static_cast<Type>(type_ & other.type_));
422 }
423
424 bool Equals(const HType& other) {
425 return type_ == other.type_;
426 }
427
428 bool IsSubtypeOf(const HType& other) {
429 return Combine(other).Equals(other);
430 }
431
432 bool IsTagged() {
433 ASSERT(type_ != kUninitialized);
434 return ((type_ & kTagged) == kTagged);
435 }
436
437 bool IsTaggedPrimitive() {
438 ASSERT(type_ != kUninitialized);
439 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
440 }
441
442 bool IsTaggedNumber() {
443 ASSERT(type_ != kUninitialized);
444 return ((type_ & kTaggedNumber) == kTaggedNumber);
445 }
446
447 bool IsSmi() {
448 ASSERT(type_ != kUninitialized);
449 return ((type_ & kSmi) == kSmi);
450 }
451
452 bool IsHeapNumber() {
453 ASSERT(type_ != kUninitialized);
454 return ((type_ & kHeapNumber) == kHeapNumber);
455 }
456
457 bool IsString() {
458 ASSERT(type_ != kUninitialized);
459 return ((type_ & kString) == kString);
460 }
461
462 bool IsBoolean() {
463 ASSERT(type_ != kUninitialized);
464 return ((type_ & kBoolean) == kBoolean);
465 }
466
467 bool IsNonPrimitive() {
468 ASSERT(type_ != kUninitialized);
469 return ((type_ & kNonPrimitive) == kNonPrimitive);
470 }
471
472 bool IsJSArray() {
473 ASSERT(type_ != kUninitialized);
474 return ((type_ & kJSArray) == kJSArray);
475 }
476
477 bool IsJSObject() {
478 ASSERT(type_ != kUninitialized);
479 return ((type_ & kJSObject) == kJSObject);
480 }
481
482 bool IsUninitialized() {
483 return type_ == kUninitialized;
484 }
485
486 static HType TypeFromValue(Handle<Object> value);
487
488 const char* ToString();
489 const char* ToShortString();
490
491 private:
492 enum Type {
493 kTagged = 0x1, // 0000 0000 0000 0001
494 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
495 kTaggedNumber = 0xd, // 0000 0000 0000 1101
496 kSmi = 0x1d, // 0000 0000 0001 1101
497 kHeapNumber = 0x2d, // 0000 0000 0010 1101
498 kString = 0x45, // 0000 0000 0100 0101
499 kBoolean = 0x85, // 0000 0000 1000 0101
500 kNonPrimitive = 0x101, // 0000 0001 0000 0001
501 kJSObject = 0x301, // 0000 0011 0000 0001
502 kJSArray = 0x701, // 0000 0111 1000 0001
503 kUninitialized = 0x1fff // 0001 1111 1111 1111
504 };
505
506 explicit HType(Type t) : type_(t) { }
507
508 Type type_;
509 };
510
511
512 class HValue: public ZoneObject {
513 public:
514 static const int kNoNumber = -1;
515
516 // There must be one corresponding kDepends flag for every kChanges flag and
517 // the order of the kChanges flags must be exactly the same as of the kDepends
518 // flags.
519 enum Flag {
520 // Declare global value numbering flags.
521 #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
522 GVN_FLAG_LIST(DECLARE_DO)
523 #undef DECLARE_DO
524 kFlexibleRepresentation,
525 kUseGVN,
526 kCanOverflow,
527 kBailoutOnMinusZero,
528 kCanBeDivByZero,
529 kIsArguments,
530 kTruncatingToInt32,
531 kLastFlag = kTruncatingToInt32
532 };
533
534 STATIC_ASSERT(kLastFlag < kBitsPerInt);
535
536 static const int kChangesToDependsFlagsLeftShift = 1;
537
538 static int ChangesFlagsMask() {
539 int result = 0;
540 // Create changes mask.
541 #define DECLARE_DO(type) result |= (1 << kChanges##type);
542 GVN_FLAG_LIST(DECLARE_DO)
543 #undef DECLARE_DO
544 return result;
545 }
546
547 static int DependsFlagsMask() {
548 return ConvertChangesToDependsFlags(ChangesFlagsMask());
549 }
550
551 static int ConvertChangesToDependsFlags(int flags) {
552 return flags << kChangesToDependsFlagsLeftShift;
553 }
554
555 // A flag mask to mark an instruction as having arbitrary side effects.
556 static int AllSideEffects() {
557 return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
558 }
559
560 static HValue* cast(HValue* value) { return value; }
561
562 enum Opcode {
563 // Declare a unique enum value for each hydrogen instruction.
564 #define DECLARE_DO(type) k##type,
565 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
566 #undef DECLARE_DO
567 kMaxInstructionClass
568 };
569
570 HValue() : block_(NULL),
571 id_(kNoNumber),
572 uses_(2),
573 type_(HType::Tagged()),
574 range_(NULL),
575 flags_(0) {}
576 virtual ~HValue() {}
577
578 HBasicBlock* block() const { return block_; }
579 void SetBlock(HBasicBlock* block);
580
581 int id() const { return id_; }
582 void set_id(int id) { id_ = id; }
583
584 const ZoneList<HValue*>* uses() const { return &uses_; }
585
586 virtual bool EmitAtUses() const { return false; }
587 Representation representation() const { return representation_; }
588 void ChangeRepresentation(Representation r) {
589 // Representation was already set and is allowed to be changed.
590 ASSERT(!representation_.IsNone());
591 ASSERT(!r.IsNone());
592 ASSERT(CheckFlag(kFlexibleRepresentation));
593 RepresentationChanged(r);
594 representation_ = r;
595 }
596
597 HType type() const { return type_; }
598 void set_type(HType type) {
599 ASSERT(uses_.length() == 0);
600 type_ = type;
601 }
602
603 // An operation needs to override this function iff:
604 // 1) it can produce an int32 output.
605 // 2) the true value of its output can potentially be minus zero.
606 // The implementation must set a flag so that it bails out in the case where
607 // it would otherwise output what should be a minus zero as an int32 zero.
608 // If the operation also exists in a form that takes int32 and outputs int32
609 // then the operation should return its input value so that we can propagate
610 // back. There are two operations that need to propagate back to more than
611 // one input. They are phi and binary add. They always return NULL and
612 // expect the caller to take care of things.
613 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
614 visited->Add(id());
615 return NULL;
616 }
617
618 bool HasSideEffects() const {
619 return (flags_ & AllSideEffects()) != 0;
620 }
621 bool IsDefinedAfter(HBasicBlock* other) const;
622
623 // Operands.
624 virtual int OperandCount() const { return 0; }
625 virtual HValue* OperandAt(int index) const {
626 UNREACHABLE();
627 return NULL;
628 }
629 void SetOperandAt(int index, HValue* value);
630
631 int LookupOperandIndex(int occurrence_index, HValue* op) const;
632 bool UsesMultipleTimes(HValue* op) const;
633
634 void ReplaceAndDelete(HValue* other);
635 void ReplaceValue(HValue* other);
636 void ReplaceAtUse(HValue* use, HValue* other);
637 void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
638 bool HasNoUses() const { return uses_.is_empty(); }
639 void ClearOperands();
640 void Delete();
641
642 int flags() const { return flags_; }
643 void SetFlagMask(int mask) { flags_ |= mask; }
644 void SetFlag(Flag f) { SetFlagMask(1 << f); }
645 void ClearFlagMask(int mask) { flags_ &= ~mask; }
646 void ClearFlag(Flag f) { ClearFlagMask(1 << f); }
647 bool CheckFlag(Flag f) const { return CheckFlagMask(1 << f); }
648 bool CheckFlagMask(int mask) const { return (flags_ & mask) != 0; }
649
650 Range* range() const { return range_; }
651 bool HasRange() const { return range_ != NULL; }
652 void AddNewRange(Range* r);
653 void RemoveLastAddedRange();
654 void ComputeInitialRange();
655
656 // Representation helpers.
657 virtual Representation RequiredInputRepresentation(int index) const {
658 return Representation::None();
659 }
660 virtual Representation InferredRepresentation() const {
661 return representation();
662 }
663
664 // This gives the instruction an opportunity to replace itself with an
665 // instruction that does the same in some better way. To replace an
666 // instruction with a new one, first add the new instruction to the graph,
667 // then return it. Return NULL to have the instruction deleted.
668 virtual HValue* Canonicalize() { return this; }
669
670 // Declare virtual type testers.
671 #define DECLARE_DO(type) virtual bool Is##type() const { return false; }
672 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
673 #undef DECLARE_DO
674
675 bool Equals(HValue* other) const;
676 virtual intptr_t Hashcode() const;
677
678 // Printing support.
679 virtual void PrintTo(StringStream* stream) const = 0;
680 void PrintNameTo(StringStream* stream);
681 static void PrintTypeTo(HType type, StringStream* stream);
682
683 virtual const char* Mnemonic() const = 0;
684 virtual Opcode opcode() const = 0;
685
686 // Updated the inferred type of this instruction and returns true if
687 // it has changed.
688 bool UpdateInferredType();
689
690 virtual HType CalculateInferredType() const;
691
692 // Helper for type conversions used by normal and phi instructions.
693 void InsertInputConversion(HInstruction* previous, int index, HType type);
694
695 #ifdef DEBUG
696 virtual void Verify() const = 0;
697 #endif
698
699 protected:
700 virtual bool DataEquals(HValue* other) const { return true; }
701 virtual void RepresentationChanged(Representation to) { }
702 virtual Range* InferRange();
703 virtual void DeleteFromGraph() = 0;
704 virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
705 void clear_block() {
706 ASSERT(block_ != NULL);
707 block_ = NULL;
708 }
709
710 void set_representation(Representation r) {
711 // Representation is set-once.
712 ASSERT(representation_.IsNone() && !r.IsNone());
713 representation_ = r;
714 }
715
716 private:
717 void InternalReplaceAtUse(HValue* use, HValue* other);
718 void RegisterUse(int index, HValue* new_value);
719
720 HBasicBlock* block_;
721
722 // The id of this instruction in the hydrogen graph, assigned when first
723 // added to the graph. Reflects creation order.
724 int id_;
725
726 Representation representation_;
727 ZoneList<HValue*> uses_;
728 HType type_;
729 Range* range_;
730 int flags_;
731
732 DISALLOW_COPY_AND_ASSIGN(HValue);
733 };
734
735
736 class HInstruction: public HValue {
737 public:
738 HInstruction* next() const { return next_; }
739 HInstruction* previous() const { return previous_; }
740
741 void PrintTo(StringStream* stream) const;
742 virtual void PrintDataTo(StringStream* stream) const {}
743
744 bool IsLinked() const { return block() != NULL; }
745 void Unlink();
746 void InsertBefore(HInstruction* next);
747 void InsertAfter(HInstruction* previous);
748
749 int position() const { return position_; }
750 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
751 void set_position(int position) { position_ = position; }
752
753 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
754
755 #ifdef DEBUG
756 virtual void Verify() const;
757 #endif
758
759 DECLARE_INSTRUCTION(Instruction)
760
761 protected:
762 HInstruction()
763 : next_(NULL),
764 previous_(NULL),
765 position_(RelocInfo::kNoPosition) {
766 SetFlag(kDependsOnOsrEntries);
767 }
768
769 virtual void DeleteFromGraph() { Unlink(); }
770
771 private:
772 void InitializeAsFirst(HBasicBlock* block) {
773 ASSERT(!IsLinked());
774 SetBlock(block);
775 }
776
777 HInstruction* next_;
778 HInstruction* previous_;
779 int position_;
780
781 friend class HBasicBlock;
782 };
783
784
785 class HBlockEntry: public HInstruction {
786 public:
787 DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
788 };
789
790
791 class HControlInstruction: public HInstruction {
792 public:
793 virtual HBasicBlock* FirstSuccessor() const { return NULL; }
794 virtual HBasicBlock* SecondSuccessor() const { return NULL; }
795
796 DECLARE_INSTRUCTION(ControlInstruction)
797 };
798
799
800 class HDeoptimize: public HControlInstruction {
801 public:
802 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
803 };
804
805
806 class HGoto: public HControlInstruction {
807 public:
808 explicit HGoto(HBasicBlock* destination)
809 : destination_(destination),
810 include_stack_check_(false) {}
811
812 virtual HBasicBlock* FirstSuccessor() const { return destination_; }
813 void set_include_stack_check(bool include_stack_check) {
814 include_stack_check_ = include_stack_check;
815 }
816 bool include_stack_check() const { return include_stack_check_; }
817
818 virtual void PrintDataTo(StringStream* stream) const;
819
820 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
821
822 private:
823 HBasicBlock* destination_;
824 bool include_stack_check_;
825 };
826
827
828 class HUnaryControlInstruction: public HControlInstruction {
829 public:
830 explicit HUnaryControlInstruction(HValue* value) {
831 SetOperandAt(0, value);
832 }
833
834 virtual Representation RequiredInputRepresentation(int index) const {
835 return Representation::Tagged();
836 }
837
838 HValue* value() const { return OperandAt(0); }
839 virtual int OperandCount() const { return 1; }
840 virtual HValue* OperandAt(int index) const { return operands_[index]; }
841
842 DECLARE_INSTRUCTION(UnaryControlInstruction)
843
844 protected:
845 virtual void InternalSetOperandAt(int index, HValue* value) {
846 operands_[index] = value;
847 }
848
849 private:
850 HOperandVector<1> operands_;
851 };
852
853
854 class HBranch: public HUnaryControlInstruction {
855 public:
856 HBranch(HBasicBlock* true_destination,
857 HBasicBlock* false_destination,
858 HValue* boolean_value)
859 : HUnaryControlInstruction(boolean_value),
860 true_destination_(true_destination),
861 false_destination_(false_destination) {
862 ASSERT(true_destination != NULL && false_destination != NULL);
863 }
864
865 virtual Representation RequiredInputRepresentation(int index) const {
866 return Representation::None();
867 }
868
869 virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
870 virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
871
872 virtual void PrintDataTo(StringStream* stream) const;
873
874 DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
875
876 private:
877 HBasicBlock* true_destination_;
878 HBasicBlock* false_destination_;
879 };
880
881
882 class HCompareMapAndBranch: public HUnaryControlInstruction {
883 public:
884 HCompareMapAndBranch(HValue* result,
885 Handle<Map> map,
886 HBasicBlock* true_destination,
887 HBasicBlock* false_destination)
888 : HUnaryControlInstruction(result),
889 map_(map),
890 true_destination_(true_destination),
891 false_destination_(false_destination) {
892 ASSERT(true_destination != NULL);
893 ASSERT(false_destination != NULL);
894 ASSERT(!map.is_null());
895 }
896
897 virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
898 virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
899
900 Handle<Map> map() const { return map_; }
901
902 DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch")
903
904 private:
905 Handle<Map> map_;
906 HBasicBlock* true_destination_;
907 HBasicBlock* false_destination_;
908 };
909
910
911 class HReturn: public HUnaryControlInstruction {
912 public:
913 explicit HReturn(HValue* result) : HUnaryControlInstruction(result) { }
914
915 virtual void PrintDataTo(StringStream* stream) const;
916
917 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
918 };
919
920
921 class HThrow: public HUnaryControlInstruction {
922 public:
923 explicit HThrow(HValue* value) : HUnaryControlInstruction(value) { }
924
925 virtual void PrintDataTo(StringStream* stream) const;
926
927 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
928 };
929
930
931 class HUnaryOperation: public HInstruction {
932 public:
933 explicit HUnaryOperation(HValue* value) {
934 SetOperandAt(0, value);
935 }
936
937 HValue* value() const { return OperandAt(0); }
938 virtual void PrintDataTo(StringStream* stream) const;
939 virtual int OperandCount() const { return 1; }
940 virtual HValue* OperandAt(int index) const { return operands_[index]; }
941
942 DECLARE_INSTRUCTION(UnaryOperation)
943
944 protected:
945 virtual void InternalSetOperandAt(int index, HValue* value) {
946 operands_[index] = value;
947 }
948
949 private:
950 HOperandVector<1> operands_;
951 };
952
953
954 class HChange: public HUnaryOperation {
955 public:
956 HChange(HValue* value,
957 Representation from,
958 Representation to)
959 : HUnaryOperation(value), from_(from), to_(to) {
960 ASSERT(!from.IsNone() && !to.IsNone());
961 ASSERT(!from.Equals(to));
962 set_representation(to);
963 SetFlag(kUseGVN);
964
965 if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
966 value->range()->IsInSmiRange()) {
967 set_type(HType::Smi());
968 }
969 }
970
971 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
972
973 Representation from() const { return from_; }
974 Representation to() const { return to_; }
975 virtual Representation RequiredInputRepresentation(int index) const {
976 return from_;
977 }
978
979 bool CanTruncateToInt32() const {
980 for (int i = 0; i < uses()->length(); ++i) {
981 if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
982 }
983 return true;
984 }
985
986 virtual void PrintDataTo(StringStream* stream) const;
987
988 DECLARE_CONCRETE_INSTRUCTION(Change,
989 CanTruncateToInt32() ? "truncate" : "change")
990
991 protected:
992 virtual bool DataEquals(HValue* other) const {
993 if (!other->IsChange()) return false;
994 HChange* change = HChange::cast(other);
995 return value() == change->value()
996 && to().Equals(change->to())
997 && CanTruncateToInt32() == change->CanTruncateToInt32();
998 }
999
1000 private:
1001 Representation from_;
1002 Representation to_;
1003 };
1004
1005
1006 class HSimulate: public HInstruction {
1007 public:
1008 HSimulate(int ast_id, int pop_count, int environment_height)
1009 : ast_id_(ast_id),
1010 pop_count_(pop_count),
1011 environment_height_(environment_height),
1012 values_(2),
1013 assigned_indexes_(2) {}
1014 virtual ~HSimulate() {}
1015
1016 virtual void PrintDataTo(StringStream* stream) const;
1017
1018 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
1019 int ast_id() const { return ast_id_; }
1020 void set_ast_id(int id) {
1021 ASSERT(!HasAstId());
1022 ast_id_ = id;
1023 }
1024
1025 int environment_height() const { return environment_height_; }
1026 int pop_count() const { return pop_count_; }
1027 const ZoneList<HValue*>* values() const { return &values_; }
1028 int GetAssignedIndexAt(int index) const {
1029 ASSERT(HasAssignedIndexAt(index));
1030 return assigned_indexes_[index];
1031 }
1032 bool HasAssignedIndexAt(int index) const {
1033 return assigned_indexes_[index] != kNoIndex;
1034 }
1035 void AddAssignedValue(int index, HValue* value) {
1036 AddValue(index, value);
1037 }
1038 void AddPushedValue(HValue* value) {
1039 AddValue(kNoIndex, value);
1040 }
1041 virtual int OperandCount() const { return values_.length(); }
1042 virtual HValue* OperandAt(int index) const { return values_[index]; }
1043
1044 DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
1045
1046 #ifdef DEBUG
1047 virtual void Verify() const;
1048 #endif
1049
1050 protected:
1051 virtual void InternalSetOperandAt(int index, HValue* value) {
1052 values_[index] = value;
1053 }
1054
1055 private:
1056 static const int kNoIndex = -1;
1057 void AddValue(int index, HValue* value) {
1058 assigned_indexes_.Add(index);
1059 // Resize the list of pushed values.
1060 values_.Add(NULL);
1061 // Set the operand through the base method in HValue to make sure that the
1062 // use lists are correctly updated.
1063 SetOperandAt(values_.length() - 1, value);
1064 }
1065 int ast_id_;
1066 int pop_count_;
1067 int environment_height_;
1068 ZoneList<HValue*> values_;
1069 ZoneList<int> assigned_indexes_;
1070 };
1071
1072
1073 class HStackCheck: public HInstruction {
1074 public:
1075 HStackCheck() { }
1076
1077 DECLARE_CONCRETE_INSTRUCTION(Throw, "stack_check")
1078 };
1079
1080
1081 class HEnterInlined: public HInstruction {
1082 public:
1083 HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
1084 : closure_(closure), function_(function) {
1085 }
1086
1087 virtual void PrintDataTo(StringStream* stream) const;
1088
1089 Handle<JSFunction> closure() const { return closure_; }
1090 FunctionLiteral* function() const { return function_; }
1091
1092 DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
1093
1094 private:
1095 Handle<JSFunction> closure_;
1096 FunctionLiteral* function_;
1097 };
1098
1099
1100 class HLeaveInlined: public HInstruction {
1101 public:
1102 HLeaveInlined() {}
1103
1104 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
1105 };
1106
1107
1108 class HPushArgument: public HUnaryOperation {
1109 public:
1110 explicit HPushArgument(HValue* value)
1111 : HUnaryOperation(value), argument_index_(-1) {
1112 set_representation(Representation::Tagged());
1113 }
1114
1115 virtual Representation RequiredInputRepresentation(int index) const {
1116 return Representation::Tagged();
1117 }
1118
1119 virtual void PrintDataTo(StringStream* stream) const;
1120 HValue* argument() const { return OperandAt(0); }
1121 int argument_index() const { return argument_index_; }
1122 void set_argument_index(int index) {
1123 ASSERT(argument_index_ == -1 || index == argument_index_);
1124 argument_index_ = index;
1125 }
1126
1127 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
1128
1129 private:
1130 int argument_index_;
1131 };
1132
1133
1134 class HGlobalObject: public HInstruction {
1135 public:
1136 HGlobalObject() {
1137 set_representation(Representation::Tagged());
1138 SetFlag(kUseGVN);
1139 SetFlag(kDependsOnCalls);
1140 }
1141
1142 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
1143 };
1144
1145
1146 class HGlobalReceiver: public HInstruction {
1147 public:
1148 HGlobalReceiver() {
1149 set_representation(Representation::Tagged());
1150 SetFlag(kUseGVN);
1151 SetFlag(kDependsOnCalls);
1152 }
1153
1154 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
1155 };
1156
1157
1158 class HCall: public HInstruction {
1159 public:
1160 // Construct a call with uninitialized arguments. The argument count
1161 // includes the receiver.
1162 explicit HCall(int count);
1163
1164 virtual HType CalculateInferredType() const { return HType::Tagged(); }
1165
1166 // TODO(3190496): This needs a cleanup. We don't want the arguments
1167 // be operands of the call instruction. This results in bad code quality.
1168 virtual int argument_count() const { return arguments_.length(); }
1169 virtual int OperandCount() const { return argument_count(); }
1170 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1171 virtual HPushArgument* PushArgumentAt(int index) const {
1172 return HPushArgument::cast(OperandAt(index));
1173 }
1174 virtual HValue* ArgumentAt(int index) const {
1175 return PushArgumentAt(index)->argument();
1176 }
1177 virtual void SetArgumentAt(int index, HPushArgument* push_argument);
1178
1179 virtual void PrintDataTo(StringStream* stream) const;
1180
1181 DECLARE_INSTRUCTION(Call)
1182
1183 protected:
1184 virtual void InternalSetOperandAt(int index, HValue* value) {
1185 arguments_[index] = value;
1186 }
1187
1188 int argument_count_;
1189 Vector<HValue*> arguments_;
1190 };
1191
1192
1193 class HCallConstantFunction: public HCall {
1194 public:
1195 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1196 : HCall(argument_count), function_(function) { }
1197
1198 Handle<JSFunction> function() const { return function_; }
1199 bool IsApplyFunction() const {
1200 return function_->code() ==
1201 Isolate::Current()->builtins()->builtin(Builtins::FunctionApply);
1202 }
1203
1204 virtual void PrintDataTo(StringStream* stream) const;
1205
1206 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
1207
1208 private:
1209 Handle<JSFunction> function_;
1210 };
1211
1212
1213 class HCallKeyed: public HCall {
1214 public:
1215 HCallKeyed(HValue* key, int argument_count)
1216 : HCall(argument_count + 1) {
1217 SetOperandAt(0, key);
1218 }
1219
1220 virtual Representation RequiredInputRepresentation(int index) const {
1221 return Representation::Tagged();
1222 }
1223
1224 // TODO(3190496): This is a hack to get an additional operand that
1225 // is not an argument to work with the current setup. This _needs_ a cleanup.
1226 // (see HCall)
1227 virtual void PrintDataTo(StringStream* stream) const;
1228 HValue* key() const { return OperandAt(0); }
1229 virtual int argument_count() const { return arguments_.length() - 1; }
1230 virtual int OperandCount() const { return arguments_.length(); }
1231 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1232 virtual HPushArgument* PushArgumentAt(int index) const {
1233 return HPushArgument::cast(OperandAt(index + 1));
1234 }
1235 virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
1236 HCall::SetArgumentAt(index + 1, push_argument);
1237 }
1238
1239 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
1240 };
1241
1242
1243 class HCallNamed: public HCall {
1244 public:
1245 HCallNamed(Handle<String> name, int argument_count)
1246 : HCall(argument_count), name_(name) { }
1247 virtual void PrintDataTo(StringStream* stream) const;
1248
1249 Handle<String> name() const { return name_; }
1250
1251 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
1252
1253 private:
1254 Handle<String> name_;
1255 };
1256
1257
1258 class HCallFunction: public HCall {
1259 public:
1260 explicit HCallFunction(int argument_count) : HCall(argument_count) { }
1261
1262 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
1263 };
1264
1265
1266 class HCallGlobal: public HCall {
1267 public:
1268 HCallGlobal(Handle<String> name, int argument_count)
1269 : HCall(argument_count), name_(name) { }
1270
1271 virtual void PrintDataTo(StringStream* stream) const;
1272
1273 Handle<String> name() const { return name_; }
1274
1275 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
1276
1277 private:
1278 Handle<String> name_;
1279 };
1280
1281
1282 class HCallKnownGlobal: public HCall {
1283 public:
1284 HCallKnownGlobal(Handle<JSFunction> target,
1285 int argument_count)
1286 : HCall(argument_count), target_(target) { }
1287
1288 Handle<JSFunction> target() const { return target_; }
1289
1290 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
1291
1292 private:
1293 Handle<JSFunction> target_;
1294 };
1295
1296
1297 class HCallNew: public HCall {
1298 public:
1299 explicit HCallNew(int argument_count) : HCall(argument_count) { }
1300
1301 virtual Representation RequiredInputRepresentation(int index) const {
1302 return Representation::Tagged();
1303 }
1304
1305 HValue* constructor() const { return ArgumentAt(0); }
1306
1307 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
1308 };
1309
1310
1311 class HCallRuntime: public HCall {
1312 public:
1313 HCallRuntime(Handle<String> name,
1314 const Runtime::Function* c_function,
1315 int argument_count)
1316 : HCall(argument_count), c_function_(c_function), name_(name) { }
1317 virtual void PrintDataTo(StringStream* stream) const;
1318
1319 const Runtime::Function* function() const { return c_function_; }
1320 Handle<String> name() const { return name_; }
1321
1322 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
1323
1324 private:
1325 const Runtime::Function* c_function_;
1326 Handle<String> name_;
1327 };
1328
1329
1330 class HArrayLength: public HUnaryOperation {
1331 public:
1332 explicit HArrayLength(HValue* value) : HUnaryOperation(value) {
1333 // The length of an array is stored as a tagged value in the array
1334 // object. It is guaranteed to be 32 bit integer, but it can be
1335 // represented as either a smi or heap number.
1336 set_representation(Representation::Tagged());
1337 SetFlag(kDependsOnArrayLengths);
1338 SetFlag(kUseGVN);
1339 }
1340
1341 virtual Representation RequiredInputRepresentation(int index) const {
1342 return Representation::Tagged();
1343 }
1344
1345 DECLARE_CONCRETE_INSTRUCTION(ArrayLength, "array_length")
1346 };
1347
1348
1349 class HBitNot: public HUnaryOperation {
1350 public:
1351 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1352 set_representation(Representation::Integer32());
1353 SetFlag(kUseGVN);
1354 SetFlag(kTruncatingToInt32);
1355 }
1356
1357 virtual Representation RequiredInputRepresentation(int index) const {
1358 return Representation::Integer32();
1359 }
1360 virtual HType CalculateInferredType() const;
1361
1362 DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
1363 };
1364
1365
1366 class HUnaryMathOperation: public HUnaryOperation {
1367 public:
1368 HUnaryMathOperation(HValue* value, MathFunctionId op)
1369 : HUnaryOperation(value), op_(op) {
1370 switch (op) {
1371 case kMathFloor:
1372 case kMathRound:
1373 case kMathCeil:
1374 set_representation(Representation::Integer32());
1375 break;
1376 case kMathAbs:
1377 set_representation(Representation::Tagged());
1378 SetFlag(kFlexibleRepresentation);
1379 break;
1380 case kMathSqrt:
1381 default:
1382 set_representation(Representation::Double());
1383 }
1384 SetFlag(kUseGVN);
1385 }
1386
1387 virtual void PrintDataTo(StringStream* stream) const;
1388
1389 virtual HType CalculateInferredType() const;
1390
1391 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1392
1393 virtual Representation RequiredInputRepresentation(int index) const {
1394 switch (op_) {
1395 case kMathFloor:
1396 case kMathRound:
1397 case kMathCeil:
1398 case kMathSqrt:
1399 return Representation::Double();
1400 break;
1401 case kMathAbs:
1402 return representation();
1403 break;
1404 default:
1405 return Representation::None();
1406 }
1407 }
1408
1409 virtual HValue* Canonicalize() {
1410 // If the input is integer32 then we replace the floor instruction
1411 // with its inputs. This happens before the representation changes are
1412 // introduced.
1413 if (op() == kMathFloor) {
1414 if (value()->representation().IsInteger32()) return value();
1415 }
1416 return this;
1417 }
1418
1419 MathFunctionId op() const { return op_; }
1420 const char* OpName() const;
1421
1422 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
1423
1424 private:
1425 MathFunctionId op_;
1426 };
1427
1428
1429 class HLoadElements: public HUnaryOperation {
1430 public:
1431 explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1432 set_representation(Representation::Tagged());
1433 SetFlag(kUseGVN);
1434 SetFlag(kDependsOnMaps);
1435 }
1436
1437 virtual Representation RequiredInputRepresentation(int index) const {
1438 return Representation::Tagged();
1439 }
1440
1441 DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
1442 };
1443
1444
1445 class HCheckMap: public HUnaryOperation {
1446 public:
1447 HCheckMap(HValue* value, Handle<Map> map)
1448 : HUnaryOperation(value), map_(map) {
1449 set_representation(Representation::Tagged());
1450 SetFlag(kUseGVN);
1451 SetFlag(kDependsOnMaps);
1452 }
1453
1454 virtual Representation RequiredInputRepresentation(int index) const {
1455 return Representation::Tagged();
1456 }
1457 virtual void PrintDataTo(StringStream* stream) const;
1458 virtual HType CalculateInferredType() const;
1459
1460 #ifdef DEBUG
1461 virtual void Verify() const;
1462 #endif
1463
1464 Handle<Map> map() const { return map_; }
1465
1466 DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
1467
1468 protected:
1469 virtual bool DataEquals(HValue* other) const {
1470 HCheckMap* b = HCheckMap::cast(other);
1471 return map_.is_identical_to(b->map());
1472 }
1473
1474 private:
1475 Handle<Map> map_;
1476 };
1477
1478
1479 class HCheckFunction: public HUnaryOperation {
1480 public:
1481 HCheckFunction(HValue* value, Handle<JSFunction> function)
1482 : HUnaryOperation(value), target_(function) {
1483 set_representation(Representation::Tagged());
1484 SetFlag(kUseGVN);
1485 }
1486
1487 virtual Representation RequiredInputRepresentation(int index) const {
1488 return Representation::Tagged();
1489 }
1490 virtual void PrintDataTo(StringStream* stream) const;
1491 virtual HType CalculateInferredType() const;
1492
1493 #ifdef DEBUG
1494 virtual void Verify() const;
1495 #endif
1496
1497 Handle<JSFunction> target() const { return target_; }
1498
1499 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
1500
1501 protected:
1502 virtual bool DataEquals(HValue* other) const {
1503 HCheckFunction* b = HCheckFunction::cast(other);
1504 return target_.is_identical_to(b->target());
1505 }
1506
1507 private:
1508 Handle<JSFunction> target_;
1509 };
1510
1511
1512 class HCheckInstanceType: public HUnaryOperation {
1513 public:
1514 // Check that the instance type is in the range [first, last] where
1515 // both first and last are included.
1516 HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
1517 : HUnaryOperation(value), first_(first), last_(last) {
1518 ASSERT(first <= last);
1519 set_representation(Representation::Tagged());
1520 SetFlag(kUseGVN);
1521 }
1522
1523 virtual Representation RequiredInputRepresentation(int index) const {
1524 return Representation::Tagged();
1525 }
1526
1527 #ifdef DEBUG
1528 virtual void Verify() const;
1529 #endif
1530
1531 static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
1532
1533 InstanceType first() const { return first_; }
1534 InstanceType last() const { return last_; }
1535
1536 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")
1537
1538 protected:
1539 // TODO(ager): It could be nice to allow the ommision of instance
1540 // type checks if we have already performed an instance type check
1541 // with a larger range.
1542 virtual bool DataEquals(HValue* other) const {
1543 HCheckInstanceType* b = HCheckInstanceType::cast(other);
1544 return (first_ == b->first()) && (last_ == b->last());
1545 }
1546
1547 private:
1548 InstanceType first_;
1549 InstanceType last_;
1550 };
1551
1552
1553 class HCheckNonSmi: public HUnaryOperation {
1554 public:
1555 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
1556 set_representation(Representation::Tagged());
1557 SetFlag(kUseGVN);
1558 }
1559
1560 virtual Representation RequiredInputRepresentation(int index) const {
1561 return Representation::Tagged();
1562 }
1563
1564 virtual HType CalculateInferredType() const;
1565
1566 #ifdef DEBUG
1567 virtual void Verify() const;
1568 #endif
1569
1570 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
1571 };
1572
1573
1574 class HCheckPrototypeMaps: public HUnaryOperation {
1575 public:
1576 HCheckPrototypeMaps(HValue* value,
1577 Handle<JSObject> holder,
1578 Handle<Map> receiver_map)
1579 : HUnaryOperation(value),
1580 holder_(holder),
1581 receiver_map_(receiver_map) {
1582 set_representation(Representation::Tagged());
1583 SetFlag(kUseGVN);
1584 SetFlag(kDependsOnMaps);
1585 }
1586
1587 virtual Representation RequiredInputRepresentation(int index) const {
1588 return Representation::Tagged();
1589 }
1590
1591 #ifdef DEBUG
1592 virtual void Verify() const;
1593 #endif
1594
1595 Handle<JSObject> holder() const { return holder_; }
1596 Handle<Map> receiver_map() const { return receiver_map_; }
1597
1598 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
1599
1600 protected:
1601 virtual bool DataEquals(HValue* other) const {
1602 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
1603 return holder_.is_identical_to(b->holder()) &&
1604 receiver_map_.is_identical_to(b->receiver_map());
1605 }
1606
1607 private:
1608 Handle<JSObject> holder_;
1609 Handle<Map> receiver_map_;
1610 };
1611
1612
1613 class HCheckSmi: public HUnaryOperation {
1614 public:
1615 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
1616 set_representation(Representation::Tagged());
1617 SetFlag(kUseGVN);
1618 }
1619
1620 virtual Representation RequiredInputRepresentation(int index) const {
1621 return Representation::Tagged();
1622 }
1623 virtual HType CalculateInferredType() const;
1624
1625 #ifdef DEBUG
1626 virtual void Verify() const;
1627 #endif
1628
1629 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
1630 };
1631
1632
1633 class HPhi: public HValue {
1634 public:
1635 explicit HPhi(int merged_index)
1636 : inputs_(2),
1637 merged_index_(merged_index),
1638 phi_id_(-1) {
1639 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1640 non_phi_uses_[i] = 0;
1641 indirect_uses_[i] = 0;
1642 }
1643 ASSERT(merged_index >= 0);
1644 set_representation(Representation::Tagged());
1645 SetFlag(kFlexibleRepresentation);
1646 }
1647
1648 virtual Representation InferredRepresentation() const {
1649 bool double_occurred = false;
1650 bool int32_occurred = false;
1651 for (int i = 0; i < OperandCount(); ++i) {
1652 HValue* value = OperandAt(i);
1653 if (value->representation().IsDouble()) double_occurred = true;
1654 if (value->representation().IsInteger32()) int32_occurred = true;
1655 if (value->representation().IsTagged()) return Representation::Tagged();
1656 }
1657
1658 if (double_occurred) return Representation::Double();
1659 if (int32_occurred) return Representation::Integer32();
1660 return Representation::None();
1661 }
1662
1663 virtual Range* InferRange();
1664 virtual Representation RequiredInputRepresentation(int index) const {
1665 return representation();
1666 }
1667 virtual HType CalculateInferredType() const;
1668 virtual int OperandCount() const { return inputs_.length(); }
1669 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
1670 HValue* GetRedundantReplacement() const;
1671 void AddInput(HValue* value);
1672
1673 bool HasReceiverOperand();
1674
1675 int merged_index() const { return merged_index_; }
1676
1677 virtual const char* Mnemonic() const { return "phi"; }
1678
1679 virtual void PrintTo(StringStream* stream) const;
1680
1681 #ifdef DEBUG
1682 virtual void Verify() const;
1683 #endif
1684
1685 DECLARE_INSTRUCTION(Phi)
1686
1687 void InitRealUses(int id);
1688 void AddNonPhiUsesFrom(HPhi* other);
1689 void AddIndirectUsesTo(int* use_count);
1690
1691 int tagged_non_phi_uses() const {
1692 return non_phi_uses_[Representation::kTagged];
1693 }
1694 int int32_non_phi_uses() const {
1695 return non_phi_uses_[Representation::kInteger32];
1696 }
1697 int double_non_phi_uses() const {
1698 return non_phi_uses_[Representation::kDouble];
1699 }
1700 int tagged_indirect_uses() const {
1701 return indirect_uses_[Representation::kTagged];
1702 }
1703 int int32_indirect_uses() const {
1704 return indirect_uses_[Representation::kInteger32];
1705 }
1706 int double_indirect_uses() const {
1707 return indirect_uses_[Representation::kDouble];
1708 }
1709 int phi_id() { return phi_id_; }
1710
1711 protected:
1712 virtual void DeleteFromGraph();
1713 virtual void InternalSetOperandAt(int index, HValue* value) {
1714 inputs_[index] = value;
1715 }
1716
1717 private:
1718 ZoneList<HValue*> inputs_;
1719 int merged_index_;
1720
1721 int non_phi_uses_[Representation::kNumRepresentations];
1722 int indirect_uses_[Representation::kNumRepresentations];
1723 int phi_id_;
1724 };
1725
1726
1727 class HArgumentsObject: public HInstruction {
1728 public:
1729 HArgumentsObject() {
1730 set_representation(Representation::Tagged());
1731 SetFlag(kIsArguments);
1732 }
1733
1734 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
1735 };
1736
1737
1738 class HConstant: public HInstruction {
1739 public:
1740 HConstant(Handle<Object> handle, Representation r);
1741
1742 Handle<Object> handle() const { return handle_; }
1743
1744 virtual bool EmitAtUses() const { return !representation().IsDouble(); }
1745 virtual void PrintDataTo(StringStream* stream) const;
1746 virtual HType CalculateInferredType() const;
1747 bool IsInteger() const { return handle_->IsSmi(); }
1748 HConstant* CopyToRepresentation(Representation r) const;
1749 HConstant* CopyToTruncatedInt32() const;
1750 bool HasInteger32Value() const { return has_int32_value_; }
1751 int32_t Integer32Value() const {
1752 ASSERT(HasInteger32Value());
1753 return int32_value_;
1754 }
1755 bool HasDoubleValue() const { return has_double_value_; }
1756 double DoubleValue() const {
1757 ASSERT(HasDoubleValue());
1758 return double_value_;
1759 }
1760 bool HasStringValue() const { return handle_->IsString(); }
1761
1762 virtual intptr_t Hashcode() const {
1763 ASSERT(!HEAP->allow_allocation(false));
1764 return reinterpret_cast<intptr_t>(*handle());
1765 }
1766
1767 #ifdef DEBUG
1768 virtual void Verify() const { }
1769 #endif
1770
1771 DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
1772
1773 protected:
1774 virtual Range* InferRange();
1775
1776 virtual bool DataEquals(HValue* other) const {
1777 HConstant* other_constant = HConstant::cast(other);
1778 return handle().is_identical_to(other_constant->handle());
1779 }
1780
1781 private:
1782 Handle<Object> handle_;
1783 HType constant_type_;
1784
1785 // The following two values represent the int32 and the double value of the
1786 // given constant if there is a lossless conversion between the constant
1787 // and the specific representation.
1788 bool has_int32_value_;
1789 int32_t int32_value_;
1790 bool has_double_value_;
1791 double double_value_;
1792 };
1793
1794
1795 class HBinaryOperation: public HInstruction {
1796 public:
1797 HBinaryOperation(HValue* left, HValue* right) {
1798 ASSERT(left != NULL && right != NULL);
1799 SetOperandAt(0, left);
1800 SetOperandAt(1, right);
1801 }
1802
1803 HValue* left() const { return OperandAt(0); }
1804 HValue* right() const { return OperandAt(1); }
1805
1806 // TODO(kasperl): Move these helpers to the IA-32 Lithium
1807 // instruction sequence builder.
1808 HValue* LeastConstantOperand() const {
1809 if (IsCommutative() && left()->IsConstant()) return right();
1810 return left();
1811 }
1812 HValue* MostConstantOperand() const {
1813 if (IsCommutative() && left()->IsConstant()) return left();
1814 return right();
1815 }
1816
1817 virtual bool IsCommutative() const { return false; }
1818
1819 virtual void PrintDataTo(StringStream* stream) const;
1820 virtual int OperandCount() const { return operands_.length(); }
1821 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1822
1823 DECLARE_INSTRUCTION(BinaryOperation)
1824
1825 protected:
1826 virtual void InternalSetOperandAt(int index, HValue* value) {
1827 operands_[index] = value;
1828 }
1829
1830 private:
1831 HOperandVector<2> operands_;
1832 };
1833
1834
1835 class HApplyArguments: public HInstruction {
1836 public:
1837 HApplyArguments(HValue* function,
1838 HValue* receiver,
1839 HValue* length,
1840 HValue* elements) {
1841 set_representation(Representation::Tagged());
1842 SetOperandAt(0, function);
1843 SetOperandAt(1, receiver);
1844 SetOperandAt(2, length);
1845 SetOperandAt(3, elements);
1846 }
1847
1848 virtual Representation RequiredInputRepresentation(int index) const {
1849 // The length is untagged, all other inputs are tagged.
1850 return (index == 2)
1851 ? Representation::Integer32()
1852 : Representation::Tagged();
1853 }
1854
1855 HValue* function() const { return OperandAt(0); }
1856 HValue* receiver() const { return OperandAt(1); }
1857 HValue* length() const { return OperandAt(2); }
1858 HValue* elements() const { return OperandAt(3); }
1859
1860 virtual int OperandCount() const { return operands_.length(); }
1861 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1862
1863 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
1864
1865
1866
1867 protected:
1868 virtual void InternalSetOperandAt(int index, HValue* value) {
1869 operands_[index] = value;
1870 }
1871
1872 private:
1873 HOperandVector<4> operands_;
1874 };
1875
1876
1877 class HArgumentsElements: public HInstruction {
1878 public:
1879 HArgumentsElements() {
1880 // The value produced by this instruction is a pointer into the stack
1881 // that looks as if it was a smi because of alignment.
1882 set_representation(Representation::Tagged());
1883 SetFlag(kUseGVN);
1884 }
1885
1886 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
1887 };
1888
1889
1890 class HArgumentsLength: public HUnaryOperation {
1891 public:
1892 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
1893 set_representation(Representation::Integer32());
1894 SetFlag(kUseGVN);
1895 }
1896
1897 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
1898 };
1899
1900
1901 class HAccessArgumentsAt: public HInstruction {
1902 public:
1903 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
1904 set_representation(Representation::Tagged());
1905 SetFlag(kUseGVN);
1906 SetOperandAt(0, arguments);
1907 SetOperandAt(1, length);
1908 SetOperandAt(2, index);
1909 }
1910
1911 virtual void PrintDataTo(StringStream* stream) const;
1912
1913 virtual Representation RequiredInputRepresentation(int index) const {
1914 // The arguments elements is considered tagged.
1915 return index == 0
1916 ? Representation::Tagged()
1917 : Representation::Integer32();
1918 }
1919
1920 HValue* arguments() const { return operands_[0]; }
1921 HValue* length() const { return operands_[1]; }
1922 HValue* index() const { return operands_[2]; }
1923
1924 virtual int OperandCount() const { return operands_.length(); }
1925 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1926
1927 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
1928
1929 protected:
1930 virtual void InternalSetOperandAt(int index, HValue* value) {
1931 operands_[index] = value;
1932 }
1933
1934 private:
1935 HOperandVector<3> operands_;
1936 };
1937
1938
1939 class HBoundsCheck: public HBinaryOperation {
1940 public:
1941 HBoundsCheck(HValue* index, HValue* length)
1942 : HBinaryOperation(index, length) {
1943 SetFlag(kUseGVN);
1944 }
1945
1946 virtual Representation RequiredInputRepresentation(int index) const {
1947 return Representation::Integer32();
1948 }
1949
1950 #ifdef DEBUG
1951 virtual void Verify() const;
1952 #endif
1953
1954 HValue* index() const { return left(); }
1955 HValue* length() const { return right(); }
1956
1957 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
1958 };
1959
1960
1961 class HBitwiseBinaryOperation: public HBinaryOperation {
1962 public:
1963 HBitwiseBinaryOperation(HValue* left, HValue* right)
1964 : HBinaryOperation(left, right) {
1965 // Default to truncating, Integer32, UseGVN.
1966 set_representation(Representation::Integer32());
1967 SetFlag(kTruncatingToInt32);
1968 SetFlag(kUseGVN);
1969 }
1970
1971 virtual Representation RequiredInputRepresentation(int index) const {
1972 return Representation::Integer32();
1973 }
1974
1975 DECLARE_INSTRUCTION(BitwiseBinaryOperation)
1976 };
1977
1978
1979 class HArithmeticBinaryOperation: public HBinaryOperation {
1980 public:
1981 HArithmeticBinaryOperation(HValue* left, HValue* right)
1982 : HBinaryOperation(left, right) {
1983 set_representation(Representation::Tagged());
1984 SetFlag(kFlexibleRepresentation);
1985 SetFlagMask(AllSideEffects());
1986 }
1987
1988 virtual void RepresentationChanged(Representation to) {
1989 if (!to.IsTagged()) {
1990 ClearFlagMask(AllSideEffects());
1991 SetFlag(kUseGVN);
1992 }
1993 }
1994
1995 virtual HType CalculateInferredType() const;
1996 virtual Representation RequiredInputRepresentation(int index) const {
1997 return representation();
1998 }
1999 virtual Representation InferredRepresentation() const {
2000 if (left()->representation().Equals(right()->representation())) {
2001 return left()->representation();
2002 }
2003 return HValue::InferredRepresentation();
2004 }
2005
2006 DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
2007 };
2008
2009
2010 class HCompare: public HBinaryOperation {
2011 public:
2012 HCompare(HValue* left, HValue* right, Token::Value token)
2013 : HBinaryOperation(left, right), token_(token) {
2014 ASSERT(Token::IsCompareOp(token));
2015 set_representation(Representation::Tagged());
2016 SetFlagMask(AllSideEffects());
2017 }
2018
2019 void SetInputRepresentation(Representation r);
2020 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2021 virtual Representation RequiredInputRepresentation(int index) const {
2022 return input_representation_;
2023 }
2024 Representation GetInputRepresentation() const {
2025 return input_representation_;
2026 }
2027 Token::Value token() const { return token_; }
2028 virtual void PrintDataTo(StringStream* stream) const;
2029
2030 virtual HType CalculateInferredType() const;
2031
2032 virtual intptr_t Hashcode() const {
2033 return HValue::Hashcode() * 7 + token_;
2034 }
2035
2036 DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
2037
2038 protected:
2039 virtual bool DataEquals(HValue* other) const {
2040 HCompare* comp = HCompare::cast(other);
2041 return token_ == comp->token();
2042 }
2043
2044 private:
2045 Representation input_representation_;
2046 Token::Value token_;
2047 };
2048
2049
2050 class HCompareJSObjectEq: public HBinaryOperation {
2051 public:
2052 HCompareJSObjectEq(HValue* left, HValue* right)
2053 : HBinaryOperation(left, right) {
2054 set_representation(Representation::Tagged());
2055 SetFlag(kUseGVN);
2056 }
2057
2058 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2059 virtual Representation RequiredInputRepresentation(int index) const {
2060 return Representation::Tagged();
2061 }
2062 virtual HType CalculateInferredType() const;
2063
2064 DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
2065 };
2066
2067
2068 class HUnaryPredicate: public HUnaryOperation {
2069 public:
2070 explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
2071 set_representation(Representation::Tagged());
2072 SetFlag(kUseGVN);
2073 }
2074 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2075 virtual Representation RequiredInputRepresentation(int index) const {
2076 return Representation::Tagged();
2077 }
2078 virtual HType CalculateInferredType() const;
2079 };
2080
2081
2082 class HIsNull: public HUnaryPredicate {
2083 public:
2084 HIsNull(HValue* value, bool is_strict)
2085 : HUnaryPredicate(value), is_strict_(is_strict) { }
2086
2087 bool is_strict() const { return is_strict_; }
2088
2089 DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
2090
2091 private:
2092 bool is_strict_;
2093 };
2094
2095
2096 class HIsSmi: public HUnaryPredicate {
2097 public:
2098 explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
2099
2100 DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
2101 };
2102
2103
2104 class HHasInstanceType: public HUnaryPredicate {
2105 public:
2106 HHasInstanceType(HValue* value, InstanceType type)
2107 : HUnaryPredicate(value), from_(type), to_(type) { }
2108 HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
2109 : HUnaryPredicate(value), from_(from), to_(to) {
2110 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
2111 }
2112
2113 InstanceType from() { return from_; }
2114 InstanceType to() { return to_; }
2115
2116 virtual void PrintDataTo(StringStream* stream) const;
2117
2118 DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
2119
2120 private:
2121 InstanceType from_;
2122 InstanceType to_; // Inclusive range, not all combinations work.
2123 };
2124
2125
2126 class HHasCachedArrayIndex: public HUnaryPredicate {
2127 public:
2128 explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
2129
2130 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
2131 };
2132
2133
2134 class HClassOfTest: public HUnaryPredicate {
2135 public:
2136 HClassOfTest(HValue* value, Handle<String> class_name)
2137 : HUnaryPredicate(value), class_name_(class_name) { }
2138
2139 DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
2140
2141 virtual void PrintDataTo(StringStream* stream) const;
2142
2143 Handle<String> class_name() const { return class_name_; }
2144
2145 private:
2146 Handle<String> class_name_;
2147 };
2148
2149
2150 class HTypeofIs: public HUnaryPredicate {
2151 public:
2152 HTypeofIs(HValue* value, Handle<String> type_literal)
2153 : HUnaryPredicate(value), type_literal_(type_literal) { }
2154
2155 Handle<String> type_literal() { return type_literal_; }
2156 virtual void PrintDataTo(StringStream* stream) const;
2157
2158 DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
2159
2160 protected:
2161 virtual bool DataEquals(HValue* other) const {
2162 HTypeofIs* b = HTypeofIs::cast(other);
2163 return type_literal_.is_identical_to(b->type_literal_);
2164 }
2165
2166 private:
2167 Handle<String> type_literal_;
2168 };
2169
2170
2171 class HInstanceOf: public HBinaryOperation {
2172 public:
2173 HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
2174 set_representation(Representation::Tagged());
2175 SetFlagMask(AllSideEffects());
2176 }
2177
2178 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2179
2180 virtual Representation RequiredInputRepresentation(int index) const {
2181 return Representation::Tagged();
2182 }
2183
2184 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
2185 };
2186
2187
2188 class HAdd: public HArithmeticBinaryOperation {
2189 public:
2190 HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2191 SetFlag(kCanOverflow);
2192 }
2193
2194 // Add is only commutative if two integer values are added and not if two
2195 // tagged values are added (because it might be a String concatenation).
2196 virtual bool IsCommutative() const {
2197 return !representation().IsTagged();
2198 }
2199
2200 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2201
2202 virtual HType CalculateInferredType() const;
2203
2204 DECLARE_CONCRETE_INSTRUCTION(Add, "add")
2205
2206 protected:
2207 virtual Range* InferRange();
2208 };
2209
2210
2211 class HSub: public HArithmeticBinaryOperation {
2212 public:
2213 HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2214 SetFlag(kCanOverflow);
2215 }
2216
2217 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2218
2219 DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
2220
2221 protected:
2222 virtual Range* InferRange();
2223 };
2224
2225
2226 class HMul: public HArithmeticBinaryOperation {
2227 public:
2228 HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2229 SetFlag(kCanOverflow);
2230 }
2231
2232 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2233
2234 // Only commutative if it is certain that not two objects are multiplicated.
2235 virtual bool IsCommutative() const {
2236 return !representation().IsTagged();
2237 }
2238
2239 DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
2240
2241 protected:
2242 virtual Range* InferRange();
2243 };
2244
2245
2246 class HMod: public HArithmeticBinaryOperation {
2247 public:
2248 HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2249 SetFlag(kCanBeDivByZero);
2250 }
2251
2252 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2253
2254 DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
2255
2256 protected:
2257 virtual Range* InferRange();
2258 };
2259
2260
2261 class HDiv: public HArithmeticBinaryOperation {
2262 public:
2263 HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2264 SetFlag(kCanBeDivByZero);
2265 SetFlag(kCanOverflow);
2266 }
2267
2268 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2269
2270 DECLARE_CONCRETE_INSTRUCTION(Div, "div")
2271
2272 protected:
2273 virtual Range* InferRange();
2274 };
2275
2276
2277 class HBitAnd: public HBitwiseBinaryOperation {
2278 public:
2279 HBitAnd(HValue* left, HValue* right)
2280 : HBitwiseBinaryOperation(left, right) { }
2281
2282 virtual bool IsCommutative() const { return true; }
2283 virtual HType CalculateInferredType() const;
2284
2285 DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
2286
2287 protected:
2288 virtual Range* InferRange();
2289 };
2290
2291
2292 class HBitXor: public HBitwiseBinaryOperation {
2293 public:
2294 HBitXor(HValue* left, HValue* right)
2295 : HBitwiseBinaryOperation(left, right) { }
2296
2297 virtual bool IsCommutative() const { return true; }
2298 virtual HType CalculateInferredType() const;
2299
2300 DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
2301 };
2302
2303
2304 class HBitOr: public HBitwiseBinaryOperation {
2305 public:
2306 HBitOr(HValue* left, HValue* right)
2307 : HBitwiseBinaryOperation(left, right) { }
2308
2309 virtual bool IsCommutative() const { return true; }
2310 virtual HType CalculateInferredType() const;
2311
2312 DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
2313
2314 protected:
2315 virtual Range* InferRange();
2316 };
2317
2318
2319 class HShl: public HBitwiseBinaryOperation {
2320 public:
2321 HShl(HValue* left, HValue* right)
2322 : HBitwiseBinaryOperation(left, right) { }
2323
2324 virtual Range* InferRange();
2325 virtual HType CalculateInferredType() const;
2326
2327 DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
2328 };
2329
2330
2331 class HShr: public HBitwiseBinaryOperation {
2332 public:
2333 HShr(HValue* left, HValue* right)
2334 : HBitwiseBinaryOperation(left, right) { }
2335
2336 virtual HType CalculateInferredType() const;
2337
2338 DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
2339 };
2340
2341
2342 class HSar: public HBitwiseBinaryOperation {
2343 public:
2344 HSar(HValue* left, HValue* right)
2345 : HBitwiseBinaryOperation(left, right) { }
2346
2347 virtual Range* InferRange();
2348 virtual HType CalculateInferredType() const;
2349
2350 DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
2351 };
2352
2353
2354 class HOsrEntry: public HInstruction {
2355 public:
2356 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
2357 SetFlag(kChangesOsrEntries);
2358 }
2359
2360 int ast_id() const { return ast_id_; }
2361
2362 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
2363
2364 private:
2365 int ast_id_;
2366 };
2367
2368
2369 class HParameter: public HInstruction {
2370 public:
2371 explicit HParameter(unsigned index) : index_(index) {
2372 set_representation(Representation::Tagged());
2373 }
2374
2375 unsigned index() const { return index_; }
2376
2377 virtual void PrintDataTo(StringStream* stream) const;
2378
2379 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2380
2381 private:
2382 unsigned index_;
2383 };
2384
2385
2386 class HCallStub: public HInstruction {
2387 public:
2388 HCallStub(CodeStub::Major major_key, int argument_count)
2389 : major_key_(major_key),
2390 argument_count_(argument_count),
2391 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
2392 set_representation(Representation::Tagged());
2393 SetFlagMask(AllSideEffects());
2394 }
2395
2396 CodeStub::Major major_key() { return major_key_; }
2397 int argument_count() { return argument_count_; }
2398
2399 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
2400 transcendental_type_ = transcendental_type;
2401 }
2402 TranscendentalCache::Type transcendental_type() {
2403 return transcendental_type_;
2404 }
2405 virtual void PrintDataTo(StringStream* stream) const;
2406
2407 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
2408
2409 private:
2410 CodeStub::Major major_key_;
2411 int argument_count_;
2412 TranscendentalCache::Type transcendental_type_;
2413 };
2414
2415
2416 class HUnknownOSRValue: public HInstruction {
2417 public:
2418 HUnknownOSRValue() { set_representation(Representation::Tagged()); }
2419
2420 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
2421 };
2422
2423
2424 class HLoadGlobal: public HInstruction {
2425 public:
2426 HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
2427 : cell_(cell), check_hole_value_(check_hole_value) {
2428 set_representation(Representation::Tagged());
2429 SetFlag(kUseGVN);
2430 SetFlag(kDependsOnGlobalVars);
2431 }
2432
2433 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2434 bool check_hole_value() const { return check_hole_value_; }
2435
2436 virtual Representation RequiredInputRepresentation(int index) const {
2437 return Representation::Tagged();
2438 }
2439 virtual void PrintDataTo(StringStream* stream) const;
2440
2441 virtual intptr_t Hashcode() const {
2442 ASSERT(!HEAP->allow_allocation(false));
2443 return reinterpret_cast<intptr_t>(*cell_);
2444 }
2445
2446 DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
2447
2448 protected:
2449 virtual bool DataEquals(HValue* other) const {
2450 HLoadGlobal* b = HLoadGlobal::cast(other);
2451 return cell_.is_identical_to(b->cell());
2452 }
2453
2454 private:
2455 Handle<JSGlobalPropertyCell> cell_;
2456 bool check_hole_value_;
2457 };
2458
2459
2460 class HStoreGlobal: public HUnaryOperation {
2461 public:
2462 HStoreGlobal(HValue* value, Handle<JSGlobalPropertyCell> cell)
2463 : HUnaryOperation(value), cell_(cell) {
2464 SetFlag(kChangesGlobalVars);
2465 }
2466
2467 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2468
2469 virtual Representation RequiredInputRepresentation(int index) const {
2470 return Representation::Tagged();
2471 }
2472 virtual void PrintDataTo(StringStream* stream) const;
2473
2474 DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
2475
2476 protected:
2477 virtual bool DataEquals(HValue* other) const {
2478 HStoreGlobal* b = HStoreGlobal::cast(other);
2479 return cell_.is_identical_to(b->cell());
2480 }
2481
2482 private:
2483 Handle<JSGlobalPropertyCell> cell_;
2484 };
2485
2486
2487 class HLoadNamedField: public HUnaryOperation {
2488 public:
2489 HLoadNamedField(HValue* object, bool is_in_object, int offset)
2490 : HUnaryOperation(object),
2491 is_in_object_(is_in_object),
2492 offset_(offset) {
2493 set_representation(Representation::Tagged());
2494 SetFlag(kUseGVN);
2495 if (is_in_object) {
2496 SetFlag(kDependsOnInobjectFields);
2497 } else {
2498 SetFlag(kDependsOnBackingStoreFields);
2499 }
2500 }
2501
2502 HValue* object() const { return OperandAt(0); }
2503 bool is_in_object() const { return is_in_object_; }
2504 int offset() const { return offset_; }
2505
2506 virtual Representation RequiredInputRepresentation(int index) const {
2507 return Representation::Tagged();
2508 }
2509 virtual void PrintDataTo(StringStream* stream) const;
2510
2511 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
2512
2513 protected:
2514 virtual bool DataEquals(HValue* other) const {
2515 HLoadNamedField* b = HLoadNamedField::cast(other);
2516 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
2517 }
2518
2519 private:
2520 bool is_in_object_;
2521 int offset_;
2522 };
2523
2524
2525 class HLoadNamedGeneric: public HUnaryOperation {
2526 public:
2527 HLoadNamedGeneric(HValue* object, Handle<Object> name)
2528 : HUnaryOperation(object), name_(name) {
2529 set_representation(Representation::Tagged());
2530 SetFlagMask(AllSideEffects());
2531 }
2532
2533 HValue* object() const { return OperandAt(0); }
2534 Handle<Object> name() const { return name_; }
2535
2536 virtual Representation RequiredInputRepresentation(int index) const {
2537 return Representation::Tagged();
2538 }
2539
2540 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
2541
2542 protected:
2543 virtual bool DataEquals(HValue* other) const {
2544 HLoadNamedGeneric* b = HLoadNamedGeneric::cast(other);
2545 return name_.is_identical_to(b->name_);
2546 }
2547
2548 private:
2549 Handle<Object> name_;
2550 };
2551
2552
2553 class HLoadKeyed: public HBinaryOperation {
2554 public:
2555 HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
2556 set_representation(Representation::Tagged());
2557 }
2558
2559 virtual void PrintDataTo(StringStream* stream) const;
2560
2561 virtual Representation RequiredInputRepresentation(int index) const {
2562 return Representation::Tagged();
2563 }
2564 HValue* object() const { return OperandAt(0); }
2565 HValue* key() const { return OperandAt(1); }
2566
2567 DECLARE_INSTRUCTION(LoadKeyed)
2568 };
2569
2570
2571 class HLoadKeyedFastElement: public HLoadKeyed {
2572 public:
2573 HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2574 SetFlag(kDependsOnArrayElements);
2575 SetFlag(kUseGVN);
2576 }
2577
2578 virtual Representation RequiredInputRepresentation(int index) const {
2579 // The key is supposed to be Integer32.
2580 return (index == 1) ? Representation::Integer32()
2581 : Representation::Tagged();
2582 }
2583
2584 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
2585 "load_keyed_fast_element")
2586 };
2587
2588
2589 class HLoadKeyedGeneric: public HLoadKeyed {
2590 public:
2591 HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2592 SetFlagMask(AllSideEffects());
2593 }
2594
2595 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
2596 };
2597
2598
2599 class HStoreNamed: public HBinaryOperation {
2600 public:
2601 HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
2602 : HBinaryOperation(obj, val), name_(name) {
2603 }
2604
2605 virtual Representation RequiredInputRepresentation(int index) const {
2606 return Representation::Tagged();
2607 }
2608
2609 virtual void PrintDataTo(StringStream* stream) const;
2610
2611 HValue* object() const { return OperandAt(0); }
2612 Handle<Object> name() const { return name_; }
2613 HValue* value() const { return OperandAt(1); }
2614 void set_value(HValue* value) { SetOperandAt(1, value); }
2615
2616 DECLARE_INSTRUCTION(StoreNamed)
2617
2618 protected:
2619 virtual bool DataEquals(HValue* other) const {
2620 HStoreNamed* b = HStoreNamed::cast(other);
2621 return name_.is_identical_to(b->name_);
2622 }
2623
2624 private:
2625 Handle<Object> name_;
2626 };
2627
2628
2629 class HStoreNamedField: public HStoreNamed {
2630 public:
2631 HStoreNamedField(HValue* obj,
2632 Handle<Object> name,
2633 HValue* val,
2634 bool in_object,
2635 int offset)
2636 : HStoreNamed(obj, name, val),
2637 is_in_object_(in_object),
2638 offset_(offset) {
2639 if (is_in_object_) {
2640 SetFlag(kChangesInobjectFields);
2641 } else {
2642 SetFlag(kChangesBackingStoreFields);
2643 }
2644 }
2645
2646 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
2647
2648 virtual Representation RequiredInputRepresentation(int index) const {
2649 return Representation::Tagged();
2650 }
2651 virtual void PrintDataTo(StringStream* stream) const;
2652
2653 bool is_in_object() const { return is_in_object_; }
2654 int offset() const { return offset_; }
2655 Handle<Map> transition() const { return transition_; }
2656 void set_transition(Handle<Map> map) { transition_ = map; }
2657
2658 private:
2659 bool is_in_object_;
2660 int offset_;
2661 Handle<Map> transition_;
2662 };
2663
2664
2665 class HStoreNamedGeneric: public HStoreNamed {
2666 public:
2667 HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
2668 : HStoreNamed(obj, name, val) {
2669 SetFlagMask(AllSideEffects());
2670 }
2671
2672 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
2673 };
2674
2675
2676 class HStoreKeyed: public HInstruction {
2677 public:
2678 HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
2679 SetOperandAt(0, obj);
2680 SetOperandAt(1, key);
2681 SetOperandAt(2, val);
2682 }
2683
2684 virtual void PrintDataTo(StringStream* stream) const;
2685 virtual int OperandCount() const { return operands_.length(); }
2686 virtual HValue* OperandAt(int index) const { return operands_[index]; }
2687
2688 virtual Representation RequiredInputRepresentation(int index) const {
2689 return Representation::Tagged();
2690 }
2691
2692 HValue* object() const { return OperandAt(0); }
2693 HValue* key() const { return OperandAt(1); }
2694 HValue* value() const { return OperandAt(2); }
2695
2696 DECLARE_INSTRUCTION(StoreKeyed)
2697
2698 protected:
2699 virtual void InternalSetOperandAt(int index, HValue* value) {
2700 operands_[index] = value;
2701 }
2702
2703 private:
2704 HOperandVector<3> operands_;
2705 };
2706
2707
2708 class HStoreKeyedFastElement: public HStoreKeyed {
2709 public:
2710 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
2711 : HStoreKeyed(obj, key, val) {
2712 SetFlag(kChangesArrayElements);
2713 }
2714
2715 bool NeedsWriteBarrier() const {
2716 return !value()->type().IsSmi();
2717 }
2718
2719 virtual Representation RequiredInputRepresentation(int index) const {
2720 // The key is supposed to be Integer32.
2721 return (index == 1) ? Representation::Integer32()
2722 : Representation::Tagged();
2723 }
2724
2725 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
2726 "store_keyed_fast_element")
2727 };
2728
2729
2730 class HStoreKeyedGeneric: public HStoreKeyed {
2731 public:
2732 HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
2733 : HStoreKeyed(obj, key, val) {
2734 SetFlagMask(AllSideEffects());
2735 }
2736
2737 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
2738 };
2739
2740
2741 class HMaterializedLiteral: public HInstruction {
2742 public:
2743 HMaterializedLiteral(int index, int depth)
2744 : literal_index_(index), depth_(depth) {
2745 set_representation(Representation::Tagged());
2746 }
2747
2748 int literal_index() const { return literal_index_; }
2749 int depth() const { return depth_; }
2750
2751 DECLARE_INSTRUCTION(MaterializedLiteral)
2752
2753 private:
2754 int literal_index_;
2755 int depth_;
2756 };
2757
2758
2759 class HArrayLiteral: public HMaterializedLiteral {
2760 public:
2761 HArrayLiteral(Handle<FixedArray> constant_elements,
2762 int length,
2763 int literal_index,
2764 int depth)
2765 : HMaterializedLiteral(literal_index, depth),
2766 length_(length),
2767 constant_elements_(constant_elements) {}
2768
2769 Handle<FixedArray> constant_elements() const { return constant_elements_; }
2770 int length() const { return length_; }
2771
2772 bool IsCopyOnWrite() const;
2773
2774 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
2775
2776 private:
2777 int length_;
2778 Handle<FixedArray> constant_elements_;
2779 };
2780
2781
2782 class HObjectLiteral: public HMaterializedLiteral {
2783 public:
2784 HObjectLiteral(Handle<FixedArray> constant_properties,
2785 bool fast_elements,
2786 int literal_index,
2787 int depth)
2788 : HMaterializedLiteral(literal_index, depth),
2789 constant_properties_(constant_properties),
2790 fast_elements_(fast_elements) {}
2791
2792 Handle<FixedArray> constant_properties() const {
2793 return constant_properties_;
2794 }
2795 bool fast_elements() const { return fast_elements_; }
2796
2797 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
2798
2799 private:
2800 Handle<FixedArray> constant_properties_;
2801 bool fast_elements_;
2802 };
2803
2804
2805 class HRegExpLiteral: public HMaterializedLiteral {
2806 public:
2807 HRegExpLiteral(Handle<String> pattern,
2808 Handle<String> flags,
2809 int literal_index)
2810 : HMaterializedLiteral(literal_index, 0),
2811 pattern_(pattern),
2812 flags_(flags) { }
2813
2814 Handle<String> pattern() { return pattern_; }
2815 Handle<String> flags() { return flags_; }
2816
2817 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
2818
2819 private:
2820 Handle<String> pattern_;
2821 Handle<String> flags_;
2822 };
2823
2824
2825 class HFunctionLiteral: public HInstruction {
2826 public:
2827 HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
2828 : shared_info_(shared), pretenure_(pretenure) {
2829 set_representation(Representation::Tagged());
2830 }
2831
2832 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
2833
2834 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
2835 bool pretenure() const { return pretenure_; }
2836
2837 private:
2838 Handle<SharedFunctionInfo> shared_info_;
2839 bool pretenure_;
2840 };
2841
2842
2843 class HTypeof: public HUnaryOperation {
2844 public:
2845 explicit HTypeof(HValue* value) : HUnaryOperation(value) {
2846 set_representation(Representation::Tagged());
2847 }
2848
2849 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
2850 };
2851
2852
2853 class HValueOf: public HUnaryOperation {
2854 public:
2855 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
2856 set_representation(Representation::Tagged());
2857 }
2858
2859 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
2860 };
2861
2862
2863 class HDeleteProperty: public HBinaryOperation {
2864 public:
2865 HDeleteProperty(HValue* obj, HValue* key)
2866 : HBinaryOperation(obj, key) {
2867 set_representation(Representation::Tagged());
2868 SetFlagMask(AllSideEffects());
2869 }
2870
2871 virtual Representation RequiredInputRepresentation(int index) const {
2872 return Representation::Tagged();
2873 }
2874
2875 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
2876
2877 HValue* object() const { return left(); }
2878 HValue* key() const { return right(); }
2879 };
2880
2881 #undef DECLARE_INSTRUCTION
2882 #undef DECLARE_CONCRETE_INSTRUCTION
2883
2884 } } // namespace v8::internal
2885
2886 #endif // V8_HYDROGEN_INSTRUCTIONS_H_
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698