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