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