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