blob: 05ff68c359764cae7c6d7623d7ff32e4dc887e23 [file] [log] [blame]
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001// Copyright 2011 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// 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
kasperl@chromium.orga5551262010-12-07 12:49:48 +000049#define HYDROGEN_ALL_INSTRUCTION_LIST(V) \
50 V(ArithmeticBinaryOperation) \
51 V(BinaryOperation) \
52 V(BitwiseBinaryOperation) \
53 V(Call) \
54 V(ControlInstruction) \
55 V(Instruction) \
56 V(LoadKeyed) \
57 V(MaterializedLiteral) \
58 V(Phi) \
59 V(StoreKeyed) \
60 V(StoreNamed) \
61 V(UnaryControlInstruction) \
62 V(UnaryOperation) \
63 HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
64
65
66#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000067 V(AbnormalExit) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000068 V(AccessArgumentsAt) \
69 V(Add) \
70 V(ApplyArguments) \
71 V(ArgumentsElements) \
72 V(ArgumentsLength) \
73 V(ArgumentsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000074 V(ArrayLiteral) \
75 V(BitAnd) \
76 V(BitNot) \
77 V(BitOr) \
78 V(BitXor) \
79 V(BlockEntry) \
80 V(BoundsCheck) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000081 V(CallConstantFunction) \
82 V(CallFunction) \
83 V(CallGlobal) \
84 V(CallKeyed) \
85 V(CallKnownGlobal) \
86 V(CallNamed) \
87 V(CallNew) \
88 V(CallRuntime) \
89 V(CallStub) \
90 V(Change) \
91 V(CheckFunction) \
92 V(CheckInstanceType) \
93 V(CheckMap) \
94 V(CheckNonSmi) \
95 V(CheckPrototypeMaps) \
96 V(CheckSmi) \
97 V(Compare) \
98 V(CompareJSObjectEq) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000099 V(CompareMap) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000100 V(Constant) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000101 V(Context) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000102 V(DeleteProperty) \
103 V(Deoptimize) \
104 V(Div) \
105 V(EnterInlined) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000106 V(FixedArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000107 V(FunctionLiteral) \
108 V(GlobalObject) \
109 V(GlobalReceiver) \
110 V(Goto) \
111 V(InstanceOf) \
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000112 V(InstanceOfKnownGlobal) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000113 V(IsNull) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000114 V(IsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000115 V(IsSmi) \
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000116 V(IsConstructCall) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117 V(HasInstanceType) \
118 V(HasCachedArrayIndex) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000119 V(JSArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000120 V(ClassOfTest) \
121 V(LeaveInlined) \
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000122 V(LoadContextSlot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000123 V(LoadElements) \
ager@chromium.org378b34e2011-01-28 08:04:38 +0000124 V(LoadFunctionPrototype) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000125 V(LoadGlobal) \
126 V(LoadKeyedFastElement) \
127 V(LoadKeyedGeneric) \
128 V(LoadNamedField) \
129 V(LoadNamedGeneric) \
130 V(Mod) \
131 V(Mul) \
132 V(ObjectLiteral) \
133 V(OsrEntry) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000134 V(OuterContext) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000135 V(Parameter) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000136 V(Power) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000137 V(PushArgument) \
138 V(RegExpLiteral) \
139 V(Return) \
140 V(Sar) \
141 V(Shl) \
142 V(Shr) \
143 V(Simulate) \
144 V(StackCheck) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000145 V(StoreContextSlot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000146 V(StoreGlobal) \
147 V(StoreKeyedFastElement) \
148 V(StoreKeyedGeneric) \
149 V(StoreNamedField) \
150 V(StoreNamedGeneric) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000151 V(StringCharCodeAt) \
152 V(StringLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000153 V(Sub) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000154 V(Test) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000155 V(Throw) \
156 V(Typeof) \
157 V(TypeofIs) \
158 V(UnaryMathOperation) \
159 V(UnknownOSRValue) \
160 V(ValueOf)
161
162#define GVN_FLAG_LIST(V) \
163 V(Calls) \
164 V(InobjectFields) \
165 V(BackingStoreFields) \
166 V(ArrayElements) \
167 V(GlobalVars) \
168 V(Maps) \
169 V(ArrayLengths) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000170 V(ContextSlots) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000171 V(OsrEntries)
172
173#define DECLARE_INSTRUCTION(type) \
174 virtual bool Is##type() const { return true; } \
175 static H##type* cast(HValue* value) { \
176 ASSERT(value->Is##type()); \
177 return reinterpret_cast<H##type*>(value); \
178 } \
179 Opcode opcode() const { return HValue::k##type; }
180
181
182#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
183 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
184 virtual const char* Mnemonic() const { return mnemonic; } \
185 DECLARE_INSTRUCTION(type)
186
187
188
189template<int kSize>
190class HOperandVector : public EmbeddedVector<HValue*, kSize> {
191 public:
192 HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
193};
194
195
196class Range: public ZoneObject {
197 public:
198 Range() : lower_(kMinInt),
199 upper_(kMaxInt),
200 next_(NULL),
201 can_be_minus_zero_(false) { }
202
203 Range(int32_t lower, int32_t upper)
204 : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
205
206 bool IsInSmiRange() const {
207 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
208 }
209 void KeepOrder();
210 void Verify() const;
211 int32_t upper() const { return upper_; }
212 int32_t lower() const { return lower_; }
213 Range* next() const { return next_; }
214 Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
215 Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
216 void ClearLower() { lower_ = kMinInt; }
217 void ClearUpper() { upper_ = kMaxInt; }
218 Range* Copy() const { return new Range(lower_, upper_); }
219 bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
220 int32_t Mask() const;
221 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
222 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
223 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
224 bool CanBeNegative() const { return lower_ < 0; }
225 bool Includes(int value) const {
226 return lower_ <= value && upper_ >= value;
227 }
228
229 void Sar(int32_t value) {
230 int32_t bits = value & 0x1F;
231 lower_ = lower_ >> bits;
232 upper_ = upper_ >> bits;
233 set_can_be_minus_zero(false);
234 }
235
236 void Shl(int32_t value) {
237 int32_t bits = value & 0x1F;
238 int old_lower = lower_;
239 int old_upper = upper_;
240 lower_ = lower_ << bits;
241 upper_ = upper_ << bits;
242 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
243 upper_ = kMaxInt;
244 lower_ = kMinInt;
245 }
246 set_can_be_minus_zero(false);
247 }
248
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000249 // Adds a constant to the lower and upper bound of the range.
250 void AddConstant(int32_t value);
251
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000252 void StackUpon(Range* other) {
253 Intersect(other);
254 next_ = other;
255 }
256
257 void Intersect(Range* other) {
258 upper_ = Min(upper_, other->upper_);
259 lower_ = Max(lower_, other->lower_);
260 bool b = CanBeMinusZero() && other->CanBeMinusZero();
261 set_can_be_minus_zero(b);
262 }
263
264 void Union(Range* other) {
265 upper_ = Max(upper_, other->upper_);
266 lower_ = Min(lower_, other->lower_);
267 bool b = CanBeMinusZero() || other->CanBeMinusZero();
268 set_can_be_minus_zero(b);
269 }
270
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000271 // Compute a new result range and return true, if the operation
272 // can overflow.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000273 bool AddAndCheckOverflow(Range* other);
274 bool SubAndCheckOverflow(Range* other);
275 bool MulAndCheckOverflow(Range* other);
276
277 private:
278 int32_t lower_;
279 int32_t upper_;
280 Range* next_;
281 bool can_be_minus_zero_;
282};
283
284
285class Representation {
286 public:
287 enum Kind {
288 kNone,
289 kTagged,
290 kDouble,
291 kInteger32,
292 kNumRepresentations
293 };
294
295 Representation() : kind_(kNone) { }
296
297 static Representation None() { return Representation(kNone); }
298 static Representation Tagged() { return Representation(kTagged); }
299 static Representation Integer32() { return Representation(kInteger32); }
300 static Representation Double() { return Representation(kDouble); }
301
302 bool Equals(const Representation& other) const {
303 return kind_ == other.kind_;
304 }
305
306 Kind kind() const { return kind_; }
307 bool IsNone() const { return kind_ == kNone; }
308 bool IsTagged() const { return kind_ == kTagged; }
309 bool IsInteger32() const { return kind_ == kInteger32; }
310 bool IsDouble() const { return kind_ == kDouble; }
311 bool IsSpecialization() const {
312 return kind_ == kInteger32 || kind_ == kDouble;
313 }
314 const char* Mnemonic() const;
315
316 private:
317 explicit Representation(Kind k) : kind_(k) { }
318
319 Kind kind_;
320};
321
322
323class HType {
324 public:
325 HType() : type_(kUninitialized) { }
326
327 static HType Tagged() { return HType(kTagged); }
328 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
329 static HType TaggedNumber() { return HType(kTaggedNumber); }
330 static HType Smi() { return HType(kSmi); }
331 static HType HeapNumber() { return HType(kHeapNumber); }
332 static HType String() { return HType(kString); }
333 static HType Boolean() { return HType(kBoolean); }
334 static HType NonPrimitive() { return HType(kNonPrimitive); }
335 static HType JSArray() { return HType(kJSArray); }
336 static HType JSObject() { return HType(kJSObject); }
337 static HType Uninitialized() { return HType(kUninitialized); }
338
339 // Return the weakest (least precise) common type.
340 HType Combine(HType other) {
341 return HType(static_cast<Type>(type_ & other.type_));
342 }
343
344 bool Equals(const HType& other) {
345 return type_ == other.type_;
346 }
347
348 bool IsSubtypeOf(const HType& other) {
349 return Combine(other).Equals(other);
350 }
351
352 bool IsTagged() {
353 ASSERT(type_ != kUninitialized);
354 return ((type_ & kTagged) == kTagged);
355 }
356
357 bool IsTaggedPrimitive() {
358 ASSERT(type_ != kUninitialized);
359 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
360 }
361
362 bool IsTaggedNumber() {
363 ASSERT(type_ != kUninitialized);
364 return ((type_ & kTaggedNumber) == kTaggedNumber);
365 }
366
367 bool IsSmi() {
368 ASSERT(type_ != kUninitialized);
369 return ((type_ & kSmi) == kSmi);
370 }
371
372 bool IsHeapNumber() {
373 ASSERT(type_ != kUninitialized);
374 return ((type_ & kHeapNumber) == kHeapNumber);
375 }
376
377 bool IsString() {
378 ASSERT(type_ != kUninitialized);
379 return ((type_ & kString) == kString);
380 }
381
382 bool IsBoolean() {
383 ASSERT(type_ != kUninitialized);
384 return ((type_ & kBoolean) == kBoolean);
385 }
386
387 bool IsNonPrimitive() {
388 ASSERT(type_ != kUninitialized);
389 return ((type_ & kNonPrimitive) == kNonPrimitive);
390 }
391
392 bool IsJSArray() {
393 ASSERT(type_ != kUninitialized);
394 return ((type_ & kJSArray) == kJSArray);
395 }
396
397 bool IsJSObject() {
398 ASSERT(type_ != kUninitialized);
399 return ((type_ & kJSObject) == kJSObject);
400 }
401
402 bool IsUninitialized() {
403 return type_ == kUninitialized;
404 }
405
406 static HType TypeFromValue(Handle<Object> value);
407
408 const char* ToString();
409 const char* ToShortString();
410
411 private:
412 enum Type {
413 kTagged = 0x1, // 0000 0000 0000 0001
414 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
415 kTaggedNumber = 0xd, // 0000 0000 0000 1101
416 kSmi = 0x1d, // 0000 0000 0001 1101
417 kHeapNumber = 0x2d, // 0000 0000 0010 1101
418 kString = 0x45, // 0000 0000 0100 0101
419 kBoolean = 0x85, // 0000 0000 1000 0101
420 kNonPrimitive = 0x101, // 0000 0001 0000 0001
421 kJSObject = 0x301, // 0000 0011 0000 0001
422 kJSArray = 0x701, // 0000 0111 1000 0001
423 kUninitialized = 0x1fff // 0001 1111 1111 1111
424 };
425
426 explicit HType(Type t) : type_(t) { }
427
428 Type type_;
429};
430
431
432class HValue: public ZoneObject {
433 public:
434 static const int kNoNumber = -1;
435
436 // There must be one corresponding kDepends flag for every kChanges flag and
437 // the order of the kChanges flags must be exactly the same as of the kDepends
438 // flags.
439 enum Flag {
440 // Declare global value numbering flags.
441 #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
442 GVN_FLAG_LIST(DECLARE_DO)
443 #undef DECLARE_DO
444 kFlexibleRepresentation,
445 kUseGVN,
446 kCanOverflow,
447 kBailoutOnMinusZero,
448 kCanBeDivByZero,
449 kIsArguments,
450 kTruncatingToInt32,
451 kLastFlag = kTruncatingToInt32
452 };
453
454 STATIC_ASSERT(kLastFlag < kBitsPerInt);
455
456 static const int kChangesToDependsFlagsLeftShift = 1;
457
458 static int ChangesFlagsMask() {
459 int result = 0;
460 // Create changes mask.
461#define DECLARE_DO(type) result |= (1 << kChanges##type);
462 GVN_FLAG_LIST(DECLARE_DO)
463#undef DECLARE_DO
464 return result;
465 }
466
467 static int DependsFlagsMask() {
468 return ConvertChangesToDependsFlags(ChangesFlagsMask());
469 }
470
471 static int ConvertChangesToDependsFlags(int flags) {
472 return flags << kChangesToDependsFlagsLeftShift;
473 }
474
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000475 static HValue* cast(HValue* value) { return value; }
476
477 enum Opcode {
478 // Declare a unique enum value for each hydrogen instruction.
479 #define DECLARE_DO(type) k##type,
480 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
481 #undef DECLARE_DO
482 kMaxInstructionClass
483 };
484
485 HValue() : block_(NULL),
486 id_(kNoNumber),
487 uses_(2),
488 type_(HType::Tagged()),
489 range_(NULL),
490 flags_(0) {}
491 virtual ~HValue() {}
492
493 HBasicBlock* block() const { return block_; }
494 void SetBlock(HBasicBlock* block);
495
496 int id() const { return id_; }
497 void set_id(int id) { id_ = id; }
498
499 const ZoneList<HValue*>* uses() const { return &uses_; }
500
501 virtual bool EmitAtUses() const { return false; }
502 Representation representation() const { return representation_; }
503 void ChangeRepresentation(Representation r) {
504 // Representation was already set and is allowed to be changed.
505 ASSERT(!representation_.IsNone());
506 ASSERT(!r.IsNone());
507 ASSERT(CheckFlag(kFlexibleRepresentation));
508 RepresentationChanged(r);
509 representation_ = r;
510 }
511
512 HType type() const { return type_; }
513 void set_type(HType type) {
514 ASSERT(uses_.length() == 0);
515 type_ = type;
516 }
517
518 // An operation needs to override this function iff:
519 // 1) it can produce an int32 output.
520 // 2) the true value of its output can potentially be minus zero.
521 // The implementation must set a flag so that it bails out in the case where
522 // it would otherwise output what should be a minus zero as an int32 zero.
523 // If the operation also exists in a form that takes int32 and outputs int32
524 // then the operation should return its input value so that we can propagate
525 // back. There are two operations that need to propagate back to more than
526 // one input. They are phi and binary add. They always return NULL and
527 // expect the caller to take care of things.
528 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
529 visited->Add(id());
530 return NULL;
531 }
532
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000533 bool IsDefinedAfter(HBasicBlock* other) const;
534
535 // Operands.
536 virtual int OperandCount() const { return 0; }
537 virtual HValue* OperandAt(int index) const {
538 UNREACHABLE();
539 return NULL;
540 }
541 void SetOperandAt(int index, HValue* value);
542
543 int LookupOperandIndex(int occurrence_index, HValue* op) const;
544 bool UsesMultipleTimes(HValue* op) const;
545
546 void ReplaceAndDelete(HValue* other);
547 void ReplaceValue(HValue* other);
548 void ReplaceAtUse(HValue* use, HValue* other);
549 void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
550 bool HasNoUses() const { return uses_.is_empty(); }
551 void ClearOperands();
552 void Delete();
553
554 int flags() const { return flags_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000555 void SetFlag(Flag f) { flags_ |= (1 << f); }
556 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
557 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
558
559 void SetAllSideEffects() { flags_ |= AllSideEffects(); }
560 void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
561 bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000562
563 Range* range() const { return range_; }
564 bool HasRange() const { return range_ != NULL; }
565 void AddNewRange(Range* r);
566 void RemoveLastAddedRange();
567 void ComputeInitialRange();
568
569 // Representation helpers.
570 virtual Representation RequiredInputRepresentation(int index) const {
571 return Representation::None();
572 }
573 virtual Representation InferredRepresentation() const {
574 return representation();
575 }
576
577 // This gives the instruction an opportunity to replace itself with an
578 // instruction that does the same in some better way. To replace an
579 // instruction with a new one, first add the new instruction to the graph,
580 // then return it. Return NULL to have the instruction deleted.
581 virtual HValue* Canonicalize() { return this; }
582
583 // Declare virtual type testers.
584#define DECLARE_DO(type) virtual bool Is##type() const { return false; }
585 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
586#undef DECLARE_DO
587
588 bool Equals(HValue* other) const;
589 virtual intptr_t Hashcode() const;
590
591 // Printing support.
592 virtual void PrintTo(StringStream* stream) const = 0;
593 void PrintNameTo(StringStream* stream);
594 static void PrintTypeTo(HType type, StringStream* stream);
595
596 virtual const char* Mnemonic() const = 0;
597 virtual Opcode opcode() const = 0;
598
599 // Updated the inferred type of this instruction and returns true if
600 // it has changed.
601 bool UpdateInferredType();
602
603 virtual HType CalculateInferredType() const;
604
605 // Helper for type conversions used by normal and phi instructions.
606 void InsertInputConversion(HInstruction* previous, int index, HType type);
607
608#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000609 virtual void Verify() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000610#endif
611
612 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000613 // This function must be overridden for instructions with flag kUseGVN, to
614 // compare the non-Operand parts of the instruction.
615 virtual bool DataEquals(HValue* other) const {
616 UNREACHABLE();
617 return false;
618 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000619 virtual void RepresentationChanged(Representation to) { }
620 virtual Range* InferRange();
621 virtual void DeleteFromGraph() = 0;
622 virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
623 void clear_block() {
624 ASSERT(block_ != NULL);
625 block_ = NULL;
626 }
627
628 void set_representation(Representation r) {
629 // Representation is set-once.
630 ASSERT(representation_.IsNone() && !r.IsNone());
631 representation_ = r;
632 }
633
634 private:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000635 // A flag mask to mark an instruction as having arbitrary side effects.
636 static int AllSideEffects() {
637 return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
638 }
639
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000640 void InternalReplaceAtUse(HValue* use, HValue* other);
641 void RegisterUse(int index, HValue* new_value);
642
643 HBasicBlock* block_;
644
645 // The id of this instruction in the hydrogen graph, assigned when first
646 // added to the graph. Reflects creation order.
647 int id_;
648
649 Representation representation_;
650 ZoneList<HValue*> uses_;
651 HType type_;
652 Range* range_;
653 int flags_;
654
655 DISALLOW_COPY_AND_ASSIGN(HValue);
656};
657
658
659class HInstruction: public HValue {
660 public:
661 HInstruction* next() const { return next_; }
662 HInstruction* previous() const { return previous_; }
663
664 void PrintTo(StringStream* stream) const;
665 virtual void PrintDataTo(StringStream* stream) const {}
666
667 bool IsLinked() const { return block() != NULL; }
668 void Unlink();
669 void InsertBefore(HInstruction* next);
670 void InsertAfter(HInstruction* previous);
671
672 int position() const { return position_; }
673 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
674 void set_position(int position) { position_ = position; }
675
676 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
677
678#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000679 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000680#endif
681
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000682 // Returns whether this is some kind of deoptimizing check
683 // instruction.
684 virtual bool IsCheckInstruction() const { return false; }
685
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000686 DECLARE_INSTRUCTION(Instruction)
687
688 protected:
689 HInstruction()
690 : next_(NULL),
691 previous_(NULL),
692 position_(RelocInfo::kNoPosition) {
693 SetFlag(kDependsOnOsrEntries);
694 }
695
696 virtual void DeleteFromGraph() { Unlink(); }
697
698 private:
699 void InitializeAsFirst(HBasicBlock* block) {
700 ASSERT(!IsLinked());
701 SetBlock(block);
702 }
703
704 HInstruction* next_;
705 HInstruction* previous_;
706 int position_;
707
708 friend class HBasicBlock;
709};
710
711
712class HBlockEntry: public HInstruction {
713 public:
714 DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
715};
716
717
718class HControlInstruction: public HInstruction {
719 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000720 HControlInstruction(HBasicBlock* first, HBasicBlock* second)
721 : first_successor_(first), second_successor_(second) {
722 }
723
724 HBasicBlock* FirstSuccessor() const { return first_successor_; }
725 HBasicBlock* SecondSuccessor() const { return second_successor_; }
726
727 virtual void PrintDataTo(StringStream* stream) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000728
729 DECLARE_INSTRUCTION(ControlInstruction)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000730
731 private:
732 HBasicBlock* first_successor_;
733 HBasicBlock* second_successor_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000734};
735
736
737class HDeoptimize: public HControlInstruction {
738 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000739 HDeoptimize() : HControlInstruction(NULL, NULL) { }
740
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000741 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
742};
743
744
745class HGoto: public HControlInstruction {
746 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000747 explicit HGoto(HBasicBlock* target)
748 : HControlInstruction(target, NULL), include_stack_check_(false) {
749 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000750
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000751 void set_include_stack_check(bool include_stack_check) {
752 include_stack_check_ = include_stack_check;
753 }
754 bool include_stack_check() const { return include_stack_check_; }
755
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000756 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
757
758 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000759 bool include_stack_check_;
760};
761
762
763class HUnaryControlInstruction: public HControlInstruction {
764 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000765 explicit HUnaryControlInstruction(HValue* value,
766 HBasicBlock* true_target,
767 HBasicBlock* false_target)
768 : HControlInstruction(true_target, false_target) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000769 SetOperandAt(0, value);
770 }
771
772 virtual Representation RequiredInputRepresentation(int index) const {
773 return Representation::Tagged();
774 }
775
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000776 virtual void PrintDataTo(StringStream* stream) const;
777
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000778 HValue* value() const { return OperandAt(0); }
779 virtual int OperandCount() const { return 1; }
780 virtual HValue* OperandAt(int index) const { return operands_[index]; }
781
782 DECLARE_INSTRUCTION(UnaryControlInstruction)
783
784 protected:
785 virtual void InternalSetOperandAt(int index, HValue* value) {
786 operands_[index] = value;
787 }
788
789 private:
790 HOperandVector<1> operands_;
791};
792
793
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000794class HTest: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000795 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000796 HTest(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target)
797 : HUnaryControlInstruction(value, true_target, false_target) {
798 ASSERT(true_target != NULL && false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000799 }
800
801 virtual Representation RequiredInputRepresentation(int index) const {
802 return Representation::None();
803 }
804
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000805 DECLARE_CONCRETE_INSTRUCTION(Test, "test")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000806};
807
808
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000809class HCompareMap: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000810 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000811 HCompareMap(HValue* value,
812 Handle<Map> map,
813 HBasicBlock* true_target,
814 HBasicBlock* false_target)
815 : HUnaryControlInstruction(value, true_target, false_target),
816 map_(map) {
817 ASSERT(true_target != NULL);
818 ASSERT(false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000819 ASSERT(!map.is_null());
820 }
821
whesse@chromium.org023421e2010-12-21 12:19:12 +0000822 virtual void PrintDataTo(StringStream* stream) const;
823
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000824 Handle<Map> map() const { return map_; }
825
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000826 DECLARE_CONCRETE_INSTRUCTION(CompareMap, "compare_map")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000827
828 private:
829 Handle<Map> map_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000830};
831
832
833class HReturn: public HUnaryControlInstruction {
834 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000835 explicit HReturn(HValue* value)
836 : HUnaryControlInstruction(value, NULL, NULL) {
837 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000838
839 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
840};
841
842
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000843class HAbnormalExit: public HControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000844 public:
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000845 HAbnormalExit() : HControlInstruction(NULL, NULL) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000846
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000847 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000848};
849
850
851class HUnaryOperation: public HInstruction {
852 public:
853 explicit HUnaryOperation(HValue* value) {
854 SetOperandAt(0, value);
855 }
856
857 HValue* value() const { return OperandAt(0); }
858 virtual void PrintDataTo(StringStream* stream) const;
859 virtual int OperandCount() const { return 1; }
860 virtual HValue* OperandAt(int index) const { return operands_[index]; }
861
862 DECLARE_INSTRUCTION(UnaryOperation)
863
864 protected:
865 virtual void InternalSetOperandAt(int index, HValue* value) {
866 operands_[index] = value;
867 }
868
869 private:
870 HOperandVector<1> operands_;
871};
872
873
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000874class HThrow: public HUnaryOperation {
875 public:
876 explicit HThrow(HValue* value) : HUnaryOperation(value) {
877 SetAllSideEffects();
878 }
879
880 virtual Representation RequiredInputRepresentation(int index) const {
881 return Representation::Tagged();
882 }
883
884 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
885};
886
887
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000888class HChange: public HUnaryOperation {
889 public:
890 HChange(HValue* value,
891 Representation from,
892 Representation to)
893 : HUnaryOperation(value), from_(from), to_(to) {
894 ASSERT(!from.IsNone() && !to.IsNone());
895 ASSERT(!from.Equals(to));
896 set_representation(to);
897 SetFlag(kUseGVN);
898
899 if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
900 value->range()->IsInSmiRange()) {
901 set_type(HType::Smi());
902 }
903 }
904
905 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
906
907 Representation from() const { return from_; }
908 Representation to() const { return to_; }
909 virtual Representation RequiredInputRepresentation(int index) const {
910 return from_;
911 }
912
913 bool CanTruncateToInt32() const {
914 for (int i = 0; i < uses()->length(); ++i) {
915 if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
916 }
917 return true;
918 }
919
920 virtual void PrintDataTo(StringStream* stream) const;
921
922 DECLARE_CONCRETE_INSTRUCTION(Change,
923 CanTruncateToInt32() ? "truncate" : "change")
924
925 protected:
926 virtual bool DataEquals(HValue* other) const {
927 if (!other->IsChange()) return false;
928 HChange* change = HChange::cast(other);
929 return value() == change->value()
930 && to().Equals(change->to())
931 && CanTruncateToInt32() == change->CanTruncateToInt32();
932 }
933
934 private:
935 Representation from_;
936 Representation to_;
937};
938
939
940class HSimulate: public HInstruction {
941 public:
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000942 HSimulate(int ast_id, int pop_count, int environment_length)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000943 : ast_id_(ast_id),
944 pop_count_(pop_count),
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000945 environment_length_(environment_length),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000946 values_(2),
947 assigned_indexes_(2) {}
948 virtual ~HSimulate() {}
949
950 virtual void PrintDataTo(StringStream* stream) const;
951
952 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
953 int ast_id() const { return ast_id_; }
954 void set_ast_id(int id) {
955 ASSERT(!HasAstId());
956 ast_id_ = id;
957 }
958
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000959 int environment_length() const { return environment_length_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000960 int pop_count() const { return pop_count_; }
961 const ZoneList<HValue*>* values() const { return &values_; }
962 int GetAssignedIndexAt(int index) const {
963 ASSERT(HasAssignedIndexAt(index));
964 return assigned_indexes_[index];
965 }
966 bool HasAssignedIndexAt(int index) const {
967 return assigned_indexes_[index] != kNoIndex;
968 }
969 void AddAssignedValue(int index, HValue* value) {
970 AddValue(index, value);
971 }
972 void AddPushedValue(HValue* value) {
973 AddValue(kNoIndex, value);
974 }
975 virtual int OperandCount() const { return values_.length(); }
976 virtual HValue* OperandAt(int index) const { return values_[index]; }
977
978 DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
979
980#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000981 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000982#endif
983
984 protected:
985 virtual void InternalSetOperandAt(int index, HValue* value) {
986 values_[index] = value;
987 }
988
989 private:
990 static const int kNoIndex = -1;
991 void AddValue(int index, HValue* value) {
992 assigned_indexes_.Add(index);
993 // Resize the list of pushed values.
994 values_.Add(NULL);
995 // Set the operand through the base method in HValue to make sure that the
996 // use lists are correctly updated.
997 SetOperandAt(values_.length() - 1, value);
998 }
999 int ast_id_;
1000 int pop_count_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001001 int environment_length_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001002 ZoneList<HValue*> values_;
1003 ZoneList<int> assigned_indexes_;
1004};
1005
1006
1007class HStackCheck: public HInstruction {
1008 public:
1009 HStackCheck() { }
1010
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001011 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001012};
1013
1014
1015class HEnterInlined: public HInstruction {
1016 public:
1017 HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
1018 : closure_(closure), function_(function) {
1019 }
1020
1021 virtual void PrintDataTo(StringStream* stream) const;
1022
1023 Handle<JSFunction> closure() const { return closure_; }
1024 FunctionLiteral* function() const { return function_; }
1025
1026 DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
1027
1028 private:
1029 Handle<JSFunction> closure_;
1030 FunctionLiteral* function_;
1031};
1032
1033
1034class HLeaveInlined: public HInstruction {
1035 public:
1036 HLeaveInlined() {}
1037
1038 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
1039};
1040
1041
1042class HPushArgument: public HUnaryOperation {
1043 public:
1044 explicit HPushArgument(HValue* value)
1045 : HUnaryOperation(value), argument_index_(-1) {
1046 set_representation(Representation::Tagged());
1047 }
1048
1049 virtual Representation RequiredInputRepresentation(int index) const {
1050 return Representation::Tagged();
1051 }
1052
1053 virtual void PrintDataTo(StringStream* stream) const;
1054 HValue* argument() const { return OperandAt(0); }
1055 int argument_index() const { return argument_index_; }
1056 void set_argument_index(int index) {
1057 ASSERT(argument_index_ == -1 || index == argument_index_);
1058 argument_index_ = index;
1059 }
1060
1061 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
1062
1063 private:
1064 int argument_index_;
1065};
1066
1067
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001068class HContext: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001069 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001070 HContext() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001071 set_representation(Representation::Tagged());
1072 SetFlag(kUseGVN);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001073 }
1074
1075 DECLARE_CONCRETE_INSTRUCTION(Context, "context");
1076
1077 protected:
1078 virtual bool DataEquals(HValue* other) const { return true; }
1079};
1080
1081
1082class HOuterContext: public HUnaryOperation {
1083 public:
1084 explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
1085 set_representation(Representation::Tagged());
1086 SetFlag(kUseGVN);
1087 }
1088
1089 DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer_context");
1090
1091 protected:
1092 virtual bool DataEquals(HValue* other) const { return true; }
1093};
1094
1095
1096class HGlobalObject: public HUnaryOperation {
1097 public:
1098 explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
1099 set_representation(Representation::Tagged());
1100 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001101 }
1102
1103 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001104
1105 protected:
1106 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001107};
1108
1109
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001110class HGlobalReceiver: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001111 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001112 explicit HGlobalReceiver(HValue* global_object)
1113 : HUnaryOperation(global_object) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001114 set_representation(Representation::Tagged());
1115 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001116 }
1117
1118 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001119
1120 protected:
1121 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001122};
1123
1124
1125class HCall: public HInstruction {
1126 public:
1127 // Construct a call with uninitialized arguments. The argument count
1128 // includes the receiver.
1129 explicit HCall(int count);
1130
1131 virtual HType CalculateInferredType() const { return HType::Tagged(); }
1132
1133 // TODO(3190496): This needs a cleanup. We don't want the arguments
1134 // be operands of the call instruction. This results in bad code quality.
1135 virtual int argument_count() const { return arguments_.length(); }
1136 virtual int OperandCount() const { return argument_count(); }
1137 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1138 virtual HPushArgument* PushArgumentAt(int index) const {
1139 return HPushArgument::cast(OperandAt(index));
1140 }
1141 virtual HValue* ArgumentAt(int index) const {
1142 return PushArgumentAt(index)->argument();
1143 }
1144 virtual void SetArgumentAt(int index, HPushArgument* push_argument);
1145
1146 virtual void PrintDataTo(StringStream* stream) const;
1147
1148 DECLARE_INSTRUCTION(Call)
1149
1150 protected:
1151 virtual void InternalSetOperandAt(int index, HValue* value) {
1152 arguments_[index] = value;
1153 }
1154
1155 int argument_count_;
1156 Vector<HValue*> arguments_;
1157};
1158
1159
1160class HCallConstantFunction: public HCall {
1161 public:
1162 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1163 : HCall(argument_count), function_(function) { }
1164
1165 Handle<JSFunction> function() const { return function_; }
1166 bool IsApplyFunction() const {
1167 return function_->code() == Builtins::builtin(Builtins::FunctionApply);
1168 }
1169
1170 virtual void PrintDataTo(StringStream* stream) const;
1171
1172 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
1173
1174 private:
1175 Handle<JSFunction> function_;
1176};
1177
1178
1179class HCallKeyed: public HCall {
1180 public:
1181 HCallKeyed(HValue* key, int argument_count)
1182 : HCall(argument_count + 1) {
1183 SetOperandAt(0, key);
1184 }
1185
1186 virtual Representation RequiredInputRepresentation(int index) const {
1187 return Representation::Tagged();
1188 }
1189
1190 // TODO(3190496): This is a hack to get an additional operand that
1191 // is not an argument to work with the current setup. This _needs_ a cleanup.
1192 // (see HCall)
1193 virtual void PrintDataTo(StringStream* stream) const;
1194 HValue* key() const { return OperandAt(0); }
1195 virtual int argument_count() const { return arguments_.length() - 1; }
1196 virtual int OperandCount() const { return arguments_.length(); }
1197 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1198 virtual HPushArgument* PushArgumentAt(int index) const {
1199 return HPushArgument::cast(OperandAt(index + 1));
1200 }
1201 virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
1202 HCall::SetArgumentAt(index + 1, push_argument);
1203 }
1204
1205 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
1206};
1207
1208
1209class HCallNamed: public HCall {
1210 public:
1211 HCallNamed(Handle<String> name, int argument_count)
1212 : HCall(argument_count), name_(name) { }
1213 virtual void PrintDataTo(StringStream* stream) const;
1214
1215 Handle<String> name() const { return name_; }
1216
1217 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
1218
1219 private:
1220 Handle<String> name_;
1221};
1222
1223
1224class HCallFunction: public HCall {
1225 public:
1226 explicit HCallFunction(int argument_count) : HCall(argument_count) { }
1227
1228 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
1229};
1230
1231
1232class HCallGlobal: public HCall {
1233 public:
1234 HCallGlobal(Handle<String> name, int argument_count)
1235 : HCall(argument_count), name_(name) { }
1236
1237 virtual void PrintDataTo(StringStream* stream) const;
1238
1239 Handle<String> name() const { return name_; }
1240
1241 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
1242
1243 private:
1244 Handle<String> name_;
1245};
1246
1247
1248class HCallKnownGlobal: public HCall {
1249 public:
1250 HCallKnownGlobal(Handle<JSFunction> target,
1251 int argument_count)
1252 : HCall(argument_count), target_(target) { }
1253
1254 Handle<JSFunction> target() const { return target_; }
1255
1256 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
1257
1258 private:
1259 Handle<JSFunction> target_;
1260};
1261
1262
1263class HCallNew: public HCall {
1264 public:
1265 explicit HCallNew(int argument_count) : HCall(argument_count) { }
1266
1267 virtual Representation RequiredInputRepresentation(int index) const {
1268 return Representation::Tagged();
1269 }
1270
1271 HValue* constructor() const { return ArgumentAt(0); }
1272
1273 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
1274};
1275
1276
1277class HCallRuntime: public HCall {
1278 public:
1279 HCallRuntime(Handle<String> name,
1280 Runtime::Function* c_function,
1281 int argument_count)
1282 : HCall(argument_count), c_function_(c_function), name_(name) { }
1283 virtual void PrintDataTo(StringStream* stream) const;
1284
1285 Runtime::Function* function() const { return c_function_; }
1286 Handle<String> name() const { return name_; }
1287
1288 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
1289
1290 private:
1291 Runtime::Function* c_function_;
1292 Handle<String> name_;
1293};
1294
1295
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001296class HJSArrayLength: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001297 public:
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001298 explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001299 // The length of an array is stored as a tagged value in the array
1300 // object. It is guaranteed to be 32 bit integer, but it can be
1301 // represented as either a smi or heap number.
1302 set_representation(Representation::Tagged());
1303 SetFlag(kDependsOnArrayLengths);
1304 SetFlag(kUseGVN);
1305 }
1306
1307 virtual Representation RequiredInputRepresentation(int index) const {
1308 return Representation::Tagged();
1309 }
1310
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001311 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001312
1313 protected:
1314 virtual bool DataEquals(HValue* other) const { return true; }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001315};
1316
1317
1318class HFixedArrayLength: public HUnaryOperation {
1319 public:
1320 explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
1321 set_representation(Representation::Tagged());
1322 SetFlag(kDependsOnArrayLengths);
1323 SetFlag(kUseGVN);
1324 }
1325
1326 virtual Representation RequiredInputRepresentation(int index) const {
1327 return Representation::Tagged();
1328 }
1329
1330 DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001331
1332 protected:
1333 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001334};
1335
1336
1337class HBitNot: public HUnaryOperation {
1338 public:
1339 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1340 set_representation(Representation::Integer32());
1341 SetFlag(kUseGVN);
1342 SetFlag(kTruncatingToInt32);
1343 }
1344
1345 virtual Representation RequiredInputRepresentation(int index) const {
1346 return Representation::Integer32();
1347 }
1348 virtual HType CalculateInferredType() const;
1349
1350 DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001351
1352 protected:
1353 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001354};
1355
1356
1357class HUnaryMathOperation: public HUnaryOperation {
1358 public:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001359 HUnaryMathOperation(HValue* value, BuiltinFunctionId op)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001360 : HUnaryOperation(value), op_(op) {
1361 switch (op) {
1362 case kMathFloor:
1363 case kMathRound:
1364 case kMathCeil:
1365 set_representation(Representation::Integer32());
1366 break;
1367 case kMathAbs:
1368 set_representation(Representation::Tagged());
1369 SetFlag(kFlexibleRepresentation);
1370 break;
1371 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001372 case kMathPowHalf:
1373 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001374 case kMathSin:
1375 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001376 set_representation(Representation::Double());
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001377 break;
1378 default:
1379 UNREACHABLE();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001380 }
1381 SetFlag(kUseGVN);
1382 }
1383
1384 virtual void PrintDataTo(StringStream* stream) const;
1385
1386 virtual HType CalculateInferredType() const;
1387
1388 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1389
1390 virtual Representation RequiredInputRepresentation(int index) const {
1391 switch (op_) {
1392 case kMathFloor:
1393 case kMathRound:
1394 case kMathCeil:
1395 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001396 case kMathPowHalf:
1397 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001398 case kMathSin:
1399 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001400 return Representation::Double();
1401 break;
1402 case kMathAbs:
1403 return representation();
1404 break;
1405 default:
1406 return Representation::None();
1407 }
1408 }
1409
1410 virtual HValue* Canonicalize() {
1411 // If the input is integer32 then we replace the floor instruction
1412 // with its inputs. This happens before the representation changes are
1413 // introduced.
1414 if (op() == kMathFloor) {
1415 if (value()->representation().IsInteger32()) return value();
1416 }
1417 return this;
1418 }
1419
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001420 BuiltinFunctionId op() const { return op_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001421 const char* OpName() const;
1422
1423 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
1424
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001425 protected:
1426 virtual bool DataEquals(HValue* other) const {
1427 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
1428 return op_ == b->op();
1429 }
1430
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001431 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001432 BuiltinFunctionId op_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001433};
1434
1435
1436class HLoadElements: public HUnaryOperation {
1437 public:
1438 explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1439 set_representation(Representation::Tagged());
1440 SetFlag(kUseGVN);
1441 SetFlag(kDependsOnMaps);
1442 }
1443
1444 virtual Representation RequiredInputRepresentation(int index) const {
1445 return Representation::Tagged();
1446 }
1447
1448 DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001449
1450 protected:
1451 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001452};
1453
1454
1455class HCheckMap: public HUnaryOperation {
1456 public:
1457 HCheckMap(HValue* value, Handle<Map> map)
1458 : HUnaryOperation(value), map_(map) {
1459 set_representation(Representation::Tagged());
1460 SetFlag(kUseGVN);
1461 SetFlag(kDependsOnMaps);
1462 }
1463
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001464 virtual bool IsCheckInstruction() const { return true; }
1465
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001466 virtual Representation RequiredInputRepresentation(int index) const {
1467 return Representation::Tagged();
1468 }
1469 virtual void PrintDataTo(StringStream* stream) const;
1470 virtual HType CalculateInferredType() const;
1471
1472#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001473 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001474#endif
1475
1476 Handle<Map> map() const { return map_; }
1477
1478 DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
1479
1480 protected:
1481 virtual bool DataEquals(HValue* other) const {
1482 HCheckMap* b = HCheckMap::cast(other);
1483 return map_.is_identical_to(b->map());
1484 }
1485
1486 private:
1487 Handle<Map> map_;
1488};
1489
1490
1491class HCheckFunction: public HUnaryOperation {
1492 public:
1493 HCheckFunction(HValue* value, Handle<JSFunction> function)
1494 : HUnaryOperation(value), target_(function) {
1495 set_representation(Representation::Tagged());
1496 SetFlag(kUseGVN);
1497 }
1498
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001499 virtual bool IsCheckInstruction() const { return true; }
1500
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001501 virtual Representation RequiredInputRepresentation(int index) const {
1502 return Representation::Tagged();
1503 }
1504 virtual void PrintDataTo(StringStream* stream) const;
1505 virtual HType CalculateInferredType() const;
1506
1507#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001508 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001509#endif
1510
1511 Handle<JSFunction> target() const { return target_; }
1512
1513 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
1514
1515 protected:
1516 virtual bool DataEquals(HValue* other) const {
1517 HCheckFunction* b = HCheckFunction::cast(other);
1518 return target_.is_identical_to(b->target());
1519 }
1520
1521 private:
1522 Handle<JSFunction> target_;
1523};
1524
1525
1526class HCheckInstanceType: public HUnaryOperation {
1527 public:
1528 // Check that the instance type is in the range [first, last] where
1529 // both first and last are included.
1530 HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
1531 : HUnaryOperation(value), first_(first), last_(last) {
1532 ASSERT(first <= last);
1533 set_representation(Representation::Tagged());
1534 SetFlag(kUseGVN);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001535 if ((FIRST_STRING_TYPE < first && last <= LAST_STRING_TYPE) ||
1536 (FIRST_STRING_TYPE <= first && last < LAST_STRING_TYPE)) {
1537 // A particular string instance type can change because of GC or
1538 // externalization, but the value still remains a string.
1539 SetFlag(kDependsOnMaps);
1540 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001541 }
1542
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001543 virtual bool IsCheckInstruction() const { return true; }
1544
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001545 virtual Representation RequiredInputRepresentation(int index) const {
1546 return Representation::Tagged();
1547 }
1548
1549#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001550 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001551#endif
1552
1553 static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
1554
1555 InstanceType first() const { return first_; }
1556 InstanceType last() const { return last_; }
1557
1558 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")
1559
1560 protected:
1561 // TODO(ager): It could be nice to allow the ommision of instance
1562 // type checks if we have already performed an instance type check
1563 // with a larger range.
1564 virtual bool DataEquals(HValue* other) const {
1565 HCheckInstanceType* b = HCheckInstanceType::cast(other);
1566 return (first_ == b->first()) && (last_ == b->last());
1567 }
1568
1569 private:
1570 InstanceType first_;
1571 InstanceType last_;
1572};
1573
1574
1575class HCheckNonSmi: public HUnaryOperation {
1576 public:
1577 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
1578 set_representation(Representation::Tagged());
1579 SetFlag(kUseGVN);
1580 }
1581
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001582 virtual bool IsCheckInstruction() const { return true; }
1583
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001584 virtual Representation RequiredInputRepresentation(int index) const {
1585 return Representation::Tagged();
1586 }
1587
1588 virtual HType CalculateInferredType() const;
1589
1590#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001591 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001592#endif
1593
1594 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001595
1596 protected:
1597 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001598};
1599
1600
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001601class HCheckPrototypeMaps: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001602 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001603 HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
1604 : prototype_(prototype), holder_(holder) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001605 SetFlag(kUseGVN);
1606 SetFlag(kDependsOnMaps);
1607 }
1608
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001609 virtual bool IsCheckInstruction() const { return true; }
1610
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001611#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001612 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001613#endif
1614
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001615 Handle<JSObject> prototype() const { return prototype_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001616 Handle<JSObject> holder() const { return holder_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001617
1618 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
1619
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001620 virtual intptr_t Hashcode() const {
1621 ASSERT(!Heap::IsAllocationAllowed());
1622 intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
1623 hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
1624 return hash;
1625 }
1626
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001627 protected:
1628 virtual bool DataEquals(HValue* other) const {
1629 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001630 return prototype_.is_identical_to(b->prototype()) &&
1631 holder_.is_identical_to(b->holder());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001632 }
1633
1634 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001635 Handle<JSObject> prototype_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001636 Handle<JSObject> holder_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001637};
1638
1639
1640class HCheckSmi: public HUnaryOperation {
1641 public:
1642 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
1643 set_representation(Representation::Tagged());
1644 SetFlag(kUseGVN);
1645 }
1646
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001647 virtual bool IsCheckInstruction() const { return true; }
1648
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001649 virtual Representation RequiredInputRepresentation(int index) const {
1650 return Representation::Tagged();
1651 }
1652 virtual HType CalculateInferredType() const;
1653
1654#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001655 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001656#endif
1657
1658 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001659
1660 protected:
1661 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001662};
1663
1664
1665class HPhi: public HValue {
1666 public:
1667 explicit HPhi(int merged_index)
1668 : inputs_(2),
1669 merged_index_(merged_index),
1670 phi_id_(-1) {
1671 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1672 non_phi_uses_[i] = 0;
1673 indirect_uses_[i] = 0;
1674 }
1675 ASSERT(merged_index >= 0);
1676 set_representation(Representation::Tagged());
1677 SetFlag(kFlexibleRepresentation);
1678 }
1679
1680 virtual Representation InferredRepresentation() const {
1681 bool double_occurred = false;
1682 bool int32_occurred = false;
1683 for (int i = 0; i < OperandCount(); ++i) {
1684 HValue* value = OperandAt(i);
1685 if (value->representation().IsDouble()) double_occurred = true;
1686 if (value->representation().IsInteger32()) int32_occurred = true;
1687 if (value->representation().IsTagged()) return Representation::Tagged();
1688 }
1689
1690 if (double_occurred) return Representation::Double();
1691 if (int32_occurred) return Representation::Integer32();
1692 return Representation::None();
1693 }
1694
1695 virtual Range* InferRange();
1696 virtual Representation RequiredInputRepresentation(int index) const {
1697 return representation();
1698 }
1699 virtual HType CalculateInferredType() const;
1700 virtual int OperandCount() const { return inputs_.length(); }
1701 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
1702 HValue* GetRedundantReplacement() const;
1703 void AddInput(HValue* value);
1704
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001705 bool IsReceiver() { return merged_index_ == 0; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001706
1707 int merged_index() const { return merged_index_; }
1708
1709 virtual const char* Mnemonic() const { return "phi"; }
1710
1711 virtual void PrintTo(StringStream* stream) const;
1712
1713#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001714 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001715#endif
1716
1717 DECLARE_INSTRUCTION(Phi)
1718
1719 void InitRealUses(int id);
1720 void AddNonPhiUsesFrom(HPhi* other);
1721 void AddIndirectUsesTo(int* use_count);
1722
1723 int tagged_non_phi_uses() const {
1724 return non_phi_uses_[Representation::kTagged];
1725 }
1726 int int32_non_phi_uses() const {
1727 return non_phi_uses_[Representation::kInteger32];
1728 }
1729 int double_non_phi_uses() const {
1730 return non_phi_uses_[Representation::kDouble];
1731 }
1732 int tagged_indirect_uses() const {
1733 return indirect_uses_[Representation::kTagged];
1734 }
1735 int int32_indirect_uses() const {
1736 return indirect_uses_[Representation::kInteger32];
1737 }
1738 int double_indirect_uses() const {
1739 return indirect_uses_[Representation::kDouble];
1740 }
1741 int phi_id() { return phi_id_; }
1742
1743 protected:
1744 virtual void DeleteFromGraph();
1745 virtual void InternalSetOperandAt(int index, HValue* value) {
1746 inputs_[index] = value;
1747 }
1748
1749 private:
1750 ZoneList<HValue*> inputs_;
1751 int merged_index_;
1752
1753 int non_phi_uses_[Representation::kNumRepresentations];
1754 int indirect_uses_[Representation::kNumRepresentations];
1755 int phi_id_;
1756};
1757
1758
1759class HArgumentsObject: public HInstruction {
1760 public:
1761 HArgumentsObject() {
1762 set_representation(Representation::Tagged());
1763 SetFlag(kIsArguments);
1764 }
1765
1766 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
1767};
1768
1769
1770class HConstant: public HInstruction {
1771 public:
1772 HConstant(Handle<Object> handle, Representation r);
1773
1774 Handle<Object> handle() const { return handle_; }
1775
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001776 bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
1777
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001778 virtual bool EmitAtUses() const { return !representation().IsDouble(); }
1779 virtual void PrintDataTo(StringStream* stream) const;
1780 virtual HType CalculateInferredType() const;
1781 bool IsInteger() const { return handle_->IsSmi(); }
1782 HConstant* CopyToRepresentation(Representation r) const;
1783 HConstant* CopyToTruncatedInt32() const;
1784 bool HasInteger32Value() const { return has_int32_value_; }
1785 int32_t Integer32Value() const {
1786 ASSERT(HasInteger32Value());
1787 return int32_value_;
1788 }
1789 bool HasDoubleValue() const { return has_double_value_; }
1790 double DoubleValue() const {
1791 ASSERT(HasDoubleValue());
1792 return double_value_;
1793 }
1794 bool HasStringValue() const { return handle_->IsString(); }
1795
1796 virtual intptr_t Hashcode() const {
1797 ASSERT(!Heap::allow_allocation(false));
1798 return reinterpret_cast<intptr_t>(*handle());
1799 }
1800
1801#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001802 virtual void Verify() { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001803#endif
1804
1805 DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
1806
1807 protected:
1808 virtual Range* InferRange();
1809
1810 virtual bool DataEquals(HValue* other) const {
1811 HConstant* other_constant = HConstant::cast(other);
1812 return handle().is_identical_to(other_constant->handle());
1813 }
1814
1815 private:
1816 Handle<Object> handle_;
1817 HType constant_type_;
1818
1819 // The following two values represent the int32 and the double value of the
1820 // given constant if there is a lossless conversion between the constant
1821 // and the specific representation.
1822 bool has_int32_value_;
1823 int32_t int32_value_;
1824 bool has_double_value_;
1825 double double_value_;
1826};
1827
1828
1829class HBinaryOperation: public HInstruction {
1830 public:
1831 HBinaryOperation(HValue* left, HValue* right) {
1832 ASSERT(left != NULL && right != NULL);
1833 SetOperandAt(0, left);
1834 SetOperandAt(1, right);
1835 }
1836
1837 HValue* left() const { return OperandAt(0); }
1838 HValue* right() const { return OperandAt(1); }
1839
1840 // TODO(kasperl): Move these helpers to the IA-32 Lithium
1841 // instruction sequence builder.
1842 HValue* LeastConstantOperand() const {
1843 if (IsCommutative() && left()->IsConstant()) return right();
1844 return left();
1845 }
1846 HValue* MostConstantOperand() const {
1847 if (IsCommutative() && left()->IsConstant()) return left();
1848 return right();
1849 }
1850
1851 virtual bool IsCommutative() const { return false; }
1852
1853 virtual void PrintDataTo(StringStream* stream) const;
1854 virtual int OperandCount() const { return operands_.length(); }
1855 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1856
1857 DECLARE_INSTRUCTION(BinaryOperation)
1858
1859 protected:
1860 virtual void InternalSetOperandAt(int index, HValue* value) {
1861 operands_[index] = value;
1862 }
1863
1864 private:
1865 HOperandVector<2> operands_;
1866};
1867
1868
1869class HApplyArguments: public HInstruction {
1870 public:
1871 HApplyArguments(HValue* function,
1872 HValue* receiver,
1873 HValue* length,
1874 HValue* elements) {
1875 set_representation(Representation::Tagged());
1876 SetOperandAt(0, function);
1877 SetOperandAt(1, receiver);
1878 SetOperandAt(2, length);
1879 SetOperandAt(3, elements);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001880 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001881 }
1882
1883 virtual Representation RequiredInputRepresentation(int index) const {
1884 // The length is untagged, all other inputs are tagged.
1885 return (index == 2)
1886 ? Representation::Integer32()
1887 : Representation::Tagged();
1888 }
1889
1890 HValue* function() const { return OperandAt(0); }
1891 HValue* receiver() const { return OperandAt(1); }
1892 HValue* length() const { return OperandAt(2); }
1893 HValue* elements() const { return OperandAt(3); }
1894
1895 virtual int OperandCount() const { return operands_.length(); }
1896 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1897
1898 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
1899
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001900 protected:
1901 virtual void InternalSetOperandAt(int index, HValue* value) {
1902 operands_[index] = value;
1903 }
1904
1905 private:
1906 HOperandVector<4> operands_;
1907};
1908
1909
1910class HArgumentsElements: public HInstruction {
1911 public:
1912 HArgumentsElements() {
1913 // The value produced by this instruction is a pointer into the stack
1914 // that looks as if it was a smi because of alignment.
1915 set_representation(Representation::Tagged());
1916 SetFlag(kUseGVN);
1917 }
1918
1919 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001920
1921 protected:
1922 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001923};
1924
1925
1926class HArgumentsLength: public HUnaryOperation {
1927 public:
1928 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
1929 set_representation(Representation::Integer32());
1930 SetFlag(kUseGVN);
1931 }
1932
1933 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001934
1935 protected:
1936 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001937};
1938
1939
1940class HAccessArgumentsAt: public HInstruction {
1941 public:
1942 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
1943 set_representation(Representation::Tagged());
1944 SetFlag(kUseGVN);
1945 SetOperandAt(0, arguments);
1946 SetOperandAt(1, length);
1947 SetOperandAt(2, index);
1948 }
1949
1950 virtual void PrintDataTo(StringStream* stream) const;
1951
1952 virtual Representation RequiredInputRepresentation(int index) const {
1953 // The arguments elements is considered tagged.
1954 return index == 0
1955 ? Representation::Tagged()
1956 : Representation::Integer32();
1957 }
1958
1959 HValue* arguments() const { return operands_[0]; }
1960 HValue* length() const { return operands_[1]; }
1961 HValue* index() const { return operands_[2]; }
1962
1963 virtual int OperandCount() const { return operands_.length(); }
1964 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1965
1966 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
1967
1968 protected:
1969 virtual void InternalSetOperandAt(int index, HValue* value) {
1970 operands_[index] = value;
1971 }
1972
ager@chromium.org378b34e2011-01-28 08:04:38 +00001973 virtual bool DataEquals(HValue* other) const { return true; }
1974
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001975 private:
1976 HOperandVector<3> operands_;
1977};
1978
1979
1980class HBoundsCheck: public HBinaryOperation {
1981 public:
1982 HBoundsCheck(HValue* index, HValue* length)
1983 : HBinaryOperation(index, length) {
1984 SetFlag(kUseGVN);
1985 }
1986
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001987 virtual bool IsCheckInstruction() const { return true; }
1988
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001989 virtual Representation RequiredInputRepresentation(int index) const {
1990 return Representation::Integer32();
1991 }
1992
1993#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001994 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001995#endif
1996
1997 HValue* index() const { return left(); }
1998 HValue* length() const { return right(); }
1999
2000 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002001
2002 protected:
2003 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002004};
2005
2006
2007class HBitwiseBinaryOperation: public HBinaryOperation {
2008 public:
2009 HBitwiseBinaryOperation(HValue* left, HValue* right)
2010 : HBinaryOperation(left, right) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002011 set_representation(Representation::Tagged());
2012 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002013 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002014 }
2015
2016 virtual Representation RequiredInputRepresentation(int index) const {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002017 return representation();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002018 }
2019
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002020 virtual void RepresentationChanged(Representation to) {
2021 if (!to.IsTagged()) {
2022 ASSERT(to.IsInteger32());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002023 ClearAllSideEffects();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002024 SetFlag(kTruncatingToInt32);
2025 SetFlag(kUseGVN);
2026 }
2027 }
2028
2029 HType CalculateInferredType() const;
2030
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002031 DECLARE_INSTRUCTION(BitwiseBinaryOperation)
2032};
2033
2034
2035class HArithmeticBinaryOperation: public HBinaryOperation {
2036 public:
2037 HArithmeticBinaryOperation(HValue* left, HValue* right)
2038 : HBinaryOperation(left, right) {
2039 set_representation(Representation::Tagged());
2040 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002041 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002042 }
2043
2044 virtual void RepresentationChanged(Representation to) {
2045 if (!to.IsTagged()) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002046 ClearAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002047 SetFlag(kUseGVN);
2048 }
2049 }
2050
2051 virtual HType CalculateInferredType() const;
2052 virtual Representation RequiredInputRepresentation(int index) const {
2053 return representation();
2054 }
2055 virtual Representation InferredRepresentation() const {
2056 if (left()->representation().Equals(right()->representation())) {
2057 return left()->representation();
2058 }
2059 return HValue::InferredRepresentation();
2060 }
2061
2062 DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
2063};
2064
2065
2066class HCompare: public HBinaryOperation {
2067 public:
2068 HCompare(HValue* left, HValue* right, Token::Value token)
2069 : HBinaryOperation(left, right), token_(token) {
2070 ASSERT(Token::IsCompareOp(token));
2071 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002072 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002073 }
2074
2075 void SetInputRepresentation(Representation r);
2076 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2077 virtual Representation RequiredInputRepresentation(int index) const {
2078 return input_representation_;
2079 }
2080 Representation GetInputRepresentation() const {
2081 return input_representation_;
2082 }
2083 Token::Value token() const { return token_; }
2084 virtual void PrintDataTo(StringStream* stream) const;
2085
2086 virtual HType CalculateInferredType() const;
2087
2088 virtual intptr_t Hashcode() const {
2089 return HValue::Hashcode() * 7 + token_;
2090 }
2091
2092 DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
2093
2094 protected:
2095 virtual bool DataEquals(HValue* other) const {
2096 HCompare* comp = HCompare::cast(other);
2097 return token_ == comp->token();
2098 }
2099
2100 private:
2101 Representation input_representation_;
2102 Token::Value token_;
2103};
2104
2105
2106class HCompareJSObjectEq: public HBinaryOperation {
2107 public:
2108 HCompareJSObjectEq(HValue* left, HValue* right)
2109 : HBinaryOperation(left, right) {
2110 set_representation(Representation::Tagged());
2111 SetFlag(kUseGVN);
2112 }
2113
2114 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2115 virtual Representation RequiredInputRepresentation(int index) const {
2116 return Representation::Tagged();
2117 }
2118 virtual HType CalculateInferredType() const;
2119
2120 DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002121
2122 protected:
2123 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002124};
2125
2126
2127class HUnaryPredicate: public HUnaryOperation {
2128 public:
2129 explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
2130 set_representation(Representation::Tagged());
2131 SetFlag(kUseGVN);
2132 }
2133 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2134 virtual Representation RequiredInputRepresentation(int index) const {
2135 return Representation::Tagged();
2136 }
2137 virtual HType CalculateInferredType() const;
2138};
2139
2140
2141class HIsNull: public HUnaryPredicate {
2142 public:
2143 HIsNull(HValue* value, bool is_strict)
2144 : HUnaryPredicate(value), is_strict_(is_strict) { }
2145
2146 bool is_strict() const { return is_strict_; }
2147
2148 DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
2149
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002150 protected:
2151 virtual bool DataEquals(HValue* other) const {
2152 HIsNull* b = HIsNull::cast(other);
2153 return is_strict_ == b->is_strict();
2154 }
2155
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002156 private:
2157 bool is_strict_;
2158};
2159
2160
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002161class HIsObject: public HUnaryPredicate {
2162 public:
2163 explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }
2164
2165 DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002166
2167 protected:
2168 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002169};
2170
2171
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002172class HIsSmi: public HUnaryPredicate {
2173 public:
2174 explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
2175
2176 DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002177
2178 protected:
2179 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002180};
2181
2182
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002183class HIsConstructCall: public HInstruction {
2184 public:
2185 HIsConstructCall() {
2186 set_representation(Representation::Tagged());
2187 SetFlag(kUseGVN);
2188 }
2189
2190 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2191
2192 DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is_construct_call")
2193
2194 protected:
2195 virtual bool DataEquals(HValue* other) const { return true; }
2196};
2197
2198
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002199class HHasInstanceType: public HUnaryPredicate {
2200 public:
2201 HHasInstanceType(HValue* value, InstanceType type)
2202 : HUnaryPredicate(value), from_(type), to_(type) { }
2203 HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
2204 : HUnaryPredicate(value), from_(from), to_(to) {
2205 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
2206 }
2207
2208 InstanceType from() { return from_; }
2209 InstanceType to() { return to_; }
2210
2211 virtual void PrintDataTo(StringStream* stream) const;
2212
2213 DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
2214
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002215 protected:
2216 virtual bool DataEquals(HValue* other) const {
2217 HHasInstanceType* b = HHasInstanceType::cast(other);
2218 return (from_ == b->from()) && (to_ == b->to());
2219 }
2220
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002221 private:
2222 InstanceType from_;
2223 InstanceType to_; // Inclusive range, not all combinations work.
2224};
2225
2226
2227class HHasCachedArrayIndex: public HUnaryPredicate {
2228 public:
2229 explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
2230
2231 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002232
2233 protected:
2234 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002235};
2236
2237
2238class HClassOfTest: public HUnaryPredicate {
2239 public:
2240 HClassOfTest(HValue* value, Handle<String> class_name)
2241 : HUnaryPredicate(value), class_name_(class_name) { }
2242
2243 DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
2244
2245 virtual void PrintDataTo(StringStream* stream) const;
2246
2247 Handle<String> class_name() const { return class_name_; }
2248
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002249 protected:
2250 virtual bool DataEquals(HValue* other) const {
2251 HClassOfTest* b = HClassOfTest::cast(other);
2252 return class_name_.is_identical_to(b->class_name_);
2253 }
2254
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002255 private:
2256 Handle<String> class_name_;
2257};
2258
2259
2260class HTypeofIs: public HUnaryPredicate {
2261 public:
2262 HTypeofIs(HValue* value, Handle<String> type_literal)
2263 : HUnaryPredicate(value), type_literal_(type_literal) { }
2264
2265 Handle<String> type_literal() { return type_literal_; }
2266 virtual void PrintDataTo(StringStream* stream) const;
2267
2268 DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
2269
2270 protected:
2271 virtual bool DataEquals(HValue* other) const {
2272 HTypeofIs* b = HTypeofIs::cast(other);
2273 return type_literal_.is_identical_to(b->type_literal_);
2274 }
2275
2276 private:
2277 Handle<String> type_literal_;
2278};
2279
2280
2281class HInstanceOf: public HBinaryOperation {
2282 public:
2283 HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
2284 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002285 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002286 }
2287
2288 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2289
2290 virtual Representation RequiredInputRepresentation(int index) const {
2291 return Representation::Tagged();
2292 }
2293
2294 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
2295};
2296
2297
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002298class HInstanceOfKnownGlobal: public HUnaryOperation {
2299 public:
2300 HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right)
2301 : HUnaryOperation(left), function_(right) {
2302 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002303 SetAllSideEffects();
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002304 }
2305
2306 Handle<JSFunction> function() { return function_; }
2307
2308 virtual Representation RequiredInputRepresentation(int index) const {
2309 return Representation::Tagged();
2310 }
2311
2312 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
2313 "instance_of_known_global")
2314
2315 private:
2316 Handle<JSFunction> function_;
2317};
2318
2319
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002320class HPower: public HBinaryOperation {
2321 public:
2322 HPower(HValue* left, HValue* right)
2323 : HBinaryOperation(left, right) {
2324 set_representation(Representation::Double());
2325 SetFlag(kUseGVN);
2326 }
2327
2328 virtual Representation RequiredInputRepresentation(int index) const {
2329 return (index == 1) ? Representation::None() : Representation::Double();
2330 }
2331
2332 DECLARE_CONCRETE_INSTRUCTION(Power, "power")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002333
2334 protected:
2335 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002336};
2337
2338
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002339class HAdd: public HArithmeticBinaryOperation {
2340 public:
2341 HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2342 SetFlag(kCanOverflow);
2343 }
2344
2345 // Add is only commutative if two integer values are added and not if two
2346 // tagged values are added (because it might be a String concatenation).
2347 virtual bool IsCommutative() const {
2348 return !representation().IsTagged();
2349 }
2350
2351 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2352
2353 virtual HType CalculateInferredType() const;
2354
2355 DECLARE_CONCRETE_INSTRUCTION(Add, "add")
2356
2357 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002358 virtual bool DataEquals(HValue* other) const { return true; }
2359
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002360 virtual Range* InferRange();
2361};
2362
2363
2364class HSub: public HArithmeticBinaryOperation {
2365 public:
2366 HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2367 SetFlag(kCanOverflow);
2368 }
2369
2370 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2371
2372 DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
2373
2374 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002375 virtual bool DataEquals(HValue* other) const { return true; }
2376
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002377 virtual Range* InferRange();
2378};
2379
2380
2381class HMul: public HArithmeticBinaryOperation {
2382 public:
2383 HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2384 SetFlag(kCanOverflow);
2385 }
2386
2387 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2388
2389 // Only commutative if it is certain that not two objects are multiplicated.
2390 virtual bool IsCommutative() const {
2391 return !representation().IsTagged();
2392 }
2393
2394 DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
2395
2396 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002397 virtual bool DataEquals(HValue* other) const { return true; }
2398
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002399 virtual Range* InferRange();
2400};
2401
2402
2403class HMod: public HArithmeticBinaryOperation {
2404 public:
2405 HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2406 SetFlag(kCanBeDivByZero);
2407 }
2408
2409 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2410
2411 DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
2412
2413 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002414 virtual bool DataEquals(HValue* other) const { return true; }
2415
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002416 virtual Range* InferRange();
2417};
2418
2419
2420class HDiv: public HArithmeticBinaryOperation {
2421 public:
2422 HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2423 SetFlag(kCanBeDivByZero);
2424 SetFlag(kCanOverflow);
2425 }
2426
2427 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2428
2429 DECLARE_CONCRETE_INSTRUCTION(Div, "div")
2430
2431 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002432 virtual bool DataEquals(HValue* other) const { return true; }
2433
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002434 virtual Range* InferRange();
2435};
2436
2437
2438class HBitAnd: public HBitwiseBinaryOperation {
2439 public:
2440 HBitAnd(HValue* left, HValue* right)
2441 : HBitwiseBinaryOperation(left, right) { }
2442
2443 virtual bool IsCommutative() const { return true; }
2444 virtual HType CalculateInferredType() const;
2445
2446 DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
2447
2448 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002449 virtual bool DataEquals(HValue* other) const { return true; }
2450
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002451 virtual Range* InferRange();
2452};
2453
2454
2455class HBitXor: public HBitwiseBinaryOperation {
2456 public:
2457 HBitXor(HValue* left, HValue* right)
2458 : HBitwiseBinaryOperation(left, right) { }
2459
2460 virtual bool IsCommutative() const { return true; }
2461 virtual HType CalculateInferredType() const;
2462
2463 DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002464
2465 protected:
2466 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002467};
2468
2469
2470class HBitOr: public HBitwiseBinaryOperation {
2471 public:
2472 HBitOr(HValue* left, HValue* right)
2473 : HBitwiseBinaryOperation(left, right) { }
2474
2475 virtual bool IsCommutative() const { return true; }
2476 virtual HType CalculateInferredType() const;
2477
2478 DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
2479
2480 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002481 virtual bool DataEquals(HValue* other) const { return true; }
2482
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002483 virtual Range* InferRange();
2484};
2485
2486
2487class HShl: public HBitwiseBinaryOperation {
2488 public:
2489 HShl(HValue* left, HValue* right)
2490 : HBitwiseBinaryOperation(left, right) { }
2491
2492 virtual Range* InferRange();
2493 virtual HType CalculateInferredType() const;
2494
2495 DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002496
2497 protected:
2498 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002499};
2500
2501
2502class HShr: public HBitwiseBinaryOperation {
2503 public:
2504 HShr(HValue* left, HValue* right)
2505 : HBitwiseBinaryOperation(left, right) { }
2506
2507 virtual HType CalculateInferredType() const;
2508
2509 DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002510
2511 protected:
2512 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002513};
2514
2515
2516class HSar: public HBitwiseBinaryOperation {
2517 public:
2518 HSar(HValue* left, HValue* right)
2519 : HBitwiseBinaryOperation(left, right) { }
2520
2521 virtual Range* InferRange();
2522 virtual HType CalculateInferredType() const;
2523
2524 DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002525
2526 protected:
2527 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002528};
2529
2530
2531class HOsrEntry: public HInstruction {
2532 public:
2533 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
2534 SetFlag(kChangesOsrEntries);
2535 }
2536
2537 int ast_id() const { return ast_id_; }
2538
2539 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
2540
2541 private:
2542 int ast_id_;
2543};
2544
2545
2546class HParameter: public HInstruction {
2547 public:
2548 explicit HParameter(unsigned index) : index_(index) {
2549 set_representation(Representation::Tagged());
2550 }
2551
2552 unsigned index() const { return index_; }
2553
2554 virtual void PrintDataTo(StringStream* stream) const;
2555
2556 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2557
2558 private:
2559 unsigned index_;
2560};
2561
2562
2563class HCallStub: public HInstruction {
2564 public:
2565 HCallStub(CodeStub::Major major_key, int argument_count)
2566 : major_key_(major_key),
2567 argument_count_(argument_count),
2568 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
2569 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002570 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002571 }
2572
2573 CodeStub::Major major_key() { return major_key_; }
2574 int argument_count() { return argument_count_; }
2575
2576 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
2577 transcendental_type_ = transcendental_type;
2578 }
2579 TranscendentalCache::Type transcendental_type() {
2580 return transcendental_type_;
2581 }
2582 virtual void PrintDataTo(StringStream* stream) const;
2583
2584 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
2585
2586 private:
2587 CodeStub::Major major_key_;
2588 int argument_count_;
2589 TranscendentalCache::Type transcendental_type_;
2590};
2591
2592
2593class HUnknownOSRValue: public HInstruction {
2594 public:
2595 HUnknownOSRValue() { set_representation(Representation::Tagged()); }
2596
2597 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
2598};
2599
2600
2601class HLoadGlobal: public HInstruction {
2602 public:
2603 HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
2604 : cell_(cell), check_hole_value_(check_hole_value) {
2605 set_representation(Representation::Tagged());
2606 SetFlag(kUseGVN);
2607 SetFlag(kDependsOnGlobalVars);
2608 }
2609
2610 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2611 bool check_hole_value() const { return check_hole_value_; }
2612
2613 virtual Representation RequiredInputRepresentation(int index) const {
2614 return Representation::Tagged();
2615 }
2616 virtual void PrintDataTo(StringStream* stream) const;
2617
2618 virtual intptr_t Hashcode() const {
2619 ASSERT(!Heap::allow_allocation(false));
2620 return reinterpret_cast<intptr_t>(*cell_);
2621 }
2622
2623 DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
2624
2625 protected:
2626 virtual bool DataEquals(HValue* other) const {
2627 HLoadGlobal* b = HLoadGlobal::cast(other);
2628 return cell_.is_identical_to(b->cell());
2629 }
2630
2631 private:
2632 Handle<JSGlobalPropertyCell> cell_;
2633 bool check_hole_value_;
2634};
2635
2636
2637class HStoreGlobal: public HUnaryOperation {
2638 public:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002639 HStoreGlobal(HValue* value,
2640 Handle<JSGlobalPropertyCell> cell,
2641 bool check_hole_value)
2642 : HUnaryOperation(value),
2643 cell_(cell),
2644 check_hole_value_(check_hole_value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002645 SetFlag(kChangesGlobalVars);
2646 }
2647
2648 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002649 bool check_hole_value() const { return check_hole_value_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002650
2651 virtual Representation RequiredInputRepresentation(int index) const {
2652 return Representation::Tagged();
2653 }
2654 virtual void PrintDataTo(StringStream* stream) const;
2655
2656 DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
2657
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002658 private:
2659 Handle<JSGlobalPropertyCell> cell_;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002660 bool check_hole_value_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002661};
2662
2663
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002664class HLoadContextSlot: public HUnaryOperation {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002665 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002666 HLoadContextSlot(HValue* context , int slot_index)
2667 : HUnaryOperation(context), slot_index_(slot_index) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002668 set_representation(Representation::Tagged());
2669 SetFlag(kUseGVN);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002670 SetFlag(kDependsOnContextSlots);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002671 }
2672
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002673 int slot_index() const { return slot_index_; }
2674
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002675 virtual Representation RequiredInputRepresentation(int index) const {
2676 return Representation::Tagged();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002677 }
2678
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002679 virtual void PrintDataTo(StringStream* stream) const;
2680
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002681 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
2682
2683 protected:
2684 virtual bool DataEquals(HValue* other) const {
2685 HLoadContextSlot* b = HLoadContextSlot::cast(other);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002686 return (slot_index() == b->slot_index());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002687 }
2688
2689 private:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002690 int slot_index_;
2691};
2692
2693
2694static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
2695 return !value->type().IsSmi() &&
2696 !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
2697}
2698
2699
2700class HStoreContextSlot: public HBinaryOperation {
2701 public:
2702 HStoreContextSlot(HValue* context, int slot_index, HValue* value)
2703 : HBinaryOperation(context, value), slot_index_(slot_index) {
2704 SetFlag(kChangesContextSlots);
2705 }
2706
2707 HValue* context() const { return OperandAt(0); }
2708 HValue* value() const { return OperandAt(1); }
2709 int slot_index() const { return slot_index_; }
2710
2711 bool NeedsWriteBarrier() const {
2712 return StoringValueNeedsWriteBarrier(value());
2713 }
2714
2715 virtual Representation RequiredInputRepresentation(int index) const {
2716 return Representation::Tagged();
2717 }
2718
2719 virtual void PrintDataTo(StringStream* stream) const;
2720
2721 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store_context_slot")
2722
2723 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002724 int slot_index_;
2725};
2726
2727
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002728class HLoadNamedField: public HUnaryOperation {
2729 public:
2730 HLoadNamedField(HValue* object, bool is_in_object, int offset)
2731 : HUnaryOperation(object),
2732 is_in_object_(is_in_object),
2733 offset_(offset) {
2734 set_representation(Representation::Tagged());
2735 SetFlag(kUseGVN);
2736 if (is_in_object) {
2737 SetFlag(kDependsOnInobjectFields);
2738 } else {
2739 SetFlag(kDependsOnBackingStoreFields);
2740 }
2741 }
2742
2743 HValue* object() const { return OperandAt(0); }
2744 bool is_in_object() const { return is_in_object_; }
2745 int offset() const { return offset_; }
2746
2747 virtual Representation RequiredInputRepresentation(int index) const {
2748 return Representation::Tagged();
2749 }
2750 virtual void PrintDataTo(StringStream* stream) const;
2751
2752 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
2753
2754 protected:
2755 virtual bool DataEquals(HValue* other) const {
2756 HLoadNamedField* b = HLoadNamedField::cast(other);
2757 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
2758 }
2759
2760 private:
2761 bool is_in_object_;
2762 int offset_;
2763};
2764
2765
2766class HLoadNamedGeneric: public HUnaryOperation {
2767 public:
2768 HLoadNamedGeneric(HValue* object, Handle<Object> name)
2769 : HUnaryOperation(object), name_(name) {
2770 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002771 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002772 }
2773
2774 HValue* object() const { return OperandAt(0); }
2775 Handle<Object> name() const { return name_; }
2776
2777 virtual Representation RequiredInputRepresentation(int index) const {
2778 return Representation::Tagged();
2779 }
2780
2781 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
2782
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002783 private:
2784 Handle<Object> name_;
2785};
2786
2787
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002788class HLoadFunctionPrototype: public HUnaryOperation {
2789 public:
2790 explicit HLoadFunctionPrototype(HValue* function)
2791 : HUnaryOperation(function) {
2792 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002793 SetFlag(kUseGVN);
2794 SetFlag(kDependsOnCalls);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002795 }
2796
2797 HValue* function() const { return OperandAt(0); }
2798
2799 virtual Representation RequiredInputRepresentation(int index) const {
2800 return Representation::Tagged();
2801 }
2802
2803 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
2804
2805 protected:
2806 virtual bool DataEquals(HValue* other) const { return true; }
2807};
2808
2809
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002810class HLoadKeyed: public HBinaryOperation {
2811 public:
2812 HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
2813 set_representation(Representation::Tagged());
2814 }
2815
2816 virtual void PrintDataTo(StringStream* stream) const;
2817
2818 virtual Representation RequiredInputRepresentation(int index) const {
2819 return Representation::Tagged();
2820 }
2821 HValue* object() const { return OperandAt(0); }
2822 HValue* key() const { return OperandAt(1); }
2823
2824 DECLARE_INSTRUCTION(LoadKeyed)
2825};
2826
2827
2828class HLoadKeyedFastElement: public HLoadKeyed {
2829 public:
2830 HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2831 SetFlag(kDependsOnArrayElements);
2832 SetFlag(kUseGVN);
2833 }
2834
2835 virtual Representation RequiredInputRepresentation(int index) const {
2836 // The key is supposed to be Integer32.
2837 return (index == 1) ? Representation::Integer32()
2838 : Representation::Tagged();
2839 }
2840
2841 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
2842 "load_keyed_fast_element")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002843
2844 protected:
2845 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002846};
2847
2848
2849class HLoadKeyedGeneric: public HLoadKeyed {
2850 public:
2851 HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002852 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002853 }
2854
2855 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
2856};
2857
2858
2859class HStoreNamed: public HBinaryOperation {
2860 public:
2861 HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
2862 : HBinaryOperation(obj, val), name_(name) {
2863 }
2864
2865 virtual Representation RequiredInputRepresentation(int index) const {
2866 return Representation::Tagged();
2867 }
2868
2869 virtual void PrintDataTo(StringStream* stream) const;
2870
2871 HValue* object() const { return OperandAt(0); }
2872 Handle<Object> name() const { return name_; }
2873 HValue* value() const { return OperandAt(1); }
2874 void set_value(HValue* value) { SetOperandAt(1, value); }
2875
2876 DECLARE_INSTRUCTION(StoreNamed)
2877
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002878 private:
2879 Handle<Object> name_;
2880};
2881
2882
2883class HStoreNamedField: public HStoreNamed {
2884 public:
2885 HStoreNamedField(HValue* obj,
2886 Handle<Object> name,
2887 HValue* val,
2888 bool in_object,
2889 int offset)
2890 : HStoreNamed(obj, name, val),
2891 is_in_object_(in_object),
2892 offset_(offset) {
2893 if (is_in_object_) {
2894 SetFlag(kChangesInobjectFields);
2895 } else {
2896 SetFlag(kChangesBackingStoreFields);
2897 }
2898 }
2899
2900 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
2901
2902 virtual Representation RequiredInputRepresentation(int index) const {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002903 return Representation::Tagged();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002904 }
2905 virtual void PrintDataTo(StringStream* stream) const;
2906
2907 bool is_in_object() const { return is_in_object_; }
2908 int offset() const { return offset_; }
2909 Handle<Map> transition() const { return transition_; }
2910 void set_transition(Handle<Map> map) { transition_ = map; }
2911
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002912 bool NeedsWriteBarrier() const {
2913 return StoringValueNeedsWriteBarrier(value());
2914 }
2915
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002916 private:
2917 bool is_in_object_;
2918 int offset_;
2919 Handle<Map> transition_;
2920};
2921
2922
2923class HStoreNamedGeneric: public HStoreNamed {
2924 public:
2925 HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
2926 : HStoreNamed(obj, name, val) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002927 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002928 }
2929
2930 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
2931};
2932
2933
2934class HStoreKeyed: public HInstruction {
2935 public:
2936 HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
2937 SetOperandAt(0, obj);
2938 SetOperandAt(1, key);
2939 SetOperandAt(2, val);
2940 }
2941
2942 virtual void PrintDataTo(StringStream* stream) const;
2943 virtual int OperandCount() const { return operands_.length(); }
2944 virtual HValue* OperandAt(int index) const { return operands_[index]; }
2945
2946 virtual Representation RequiredInputRepresentation(int index) const {
2947 return Representation::Tagged();
2948 }
2949
2950 HValue* object() const { return OperandAt(0); }
2951 HValue* key() const { return OperandAt(1); }
2952 HValue* value() const { return OperandAt(2); }
2953
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002954 bool NeedsWriteBarrier() const {
2955 return StoringValueNeedsWriteBarrier(value());
2956 }
2957
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002958 DECLARE_INSTRUCTION(StoreKeyed)
2959
2960 protected:
2961 virtual void InternalSetOperandAt(int index, HValue* value) {
2962 operands_[index] = value;
2963 }
2964
2965 private:
2966 HOperandVector<3> operands_;
2967};
2968
2969
2970class HStoreKeyedFastElement: public HStoreKeyed {
2971 public:
2972 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
2973 : HStoreKeyed(obj, key, val) {
2974 SetFlag(kChangesArrayElements);
2975 }
2976
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002977 virtual Representation RequiredInputRepresentation(int index) const {
2978 // The key is supposed to be Integer32.
2979 return (index == 1) ? Representation::Integer32()
2980 : Representation::Tagged();
2981 }
2982
2983 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
2984 "store_keyed_fast_element")
2985};
2986
2987
2988class HStoreKeyedGeneric: public HStoreKeyed {
2989 public:
2990 HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
2991 : HStoreKeyed(obj, key, val) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002992 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002993 }
2994
2995 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
2996};
2997
2998
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002999class HStringCharCodeAt: public HBinaryOperation {
3000 public:
3001 HStringCharCodeAt(HValue* string, HValue* index)
3002 : HBinaryOperation(string, index) {
3003 set_representation(Representation::Integer32());
3004 SetFlag(kUseGVN);
3005 }
3006
3007 virtual Representation RequiredInputRepresentation(int index) const {
3008 // The index is supposed to be Integer32.
3009 return (index == 1) ? Representation::Integer32()
3010 : Representation::Tagged();
3011 }
3012
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003013 HValue* string() const { return OperandAt(0); }
3014 HValue* index() const { return OperandAt(1); }
3015
3016 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string_char_code_at")
3017
3018 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00003019 virtual bool DataEquals(HValue* other) const { return true; }
3020
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003021 virtual Range* InferRange() {
3022 return new Range(0, String::kMaxUC16CharCode);
3023 }
3024};
3025
3026
3027class HStringLength: public HUnaryOperation {
3028 public:
3029 explicit HStringLength(HValue* string) : HUnaryOperation(string) {
3030 set_representation(Representation::Tagged());
3031 SetFlag(kUseGVN);
3032 }
3033
3034 virtual Representation RequiredInputRepresentation(int index) const {
3035 return Representation::Tagged();
3036 }
3037
3038 virtual HType CalculateInferredType() const {
3039 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
3040 return HType::Smi();
3041 }
3042
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003043 DECLARE_CONCRETE_INSTRUCTION(StringLength, "string_length")
3044
3045 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00003046 virtual bool DataEquals(HValue* other) const { return true; }
3047
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003048 virtual Range* InferRange() {
3049 return new Range(0, String::kMaxLength);
3050 }
3051};
3052
3053
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003054class HMaterializedLiteral: public HInstruction {
3055 public:
3056 HMaterializedLiteral(int index, int depth)
3057 : literal_index_(index), depth_(depth) {
3058 set_representation(Representation::Tagged());
3059 }
3060
3061 int literal_index() const { return literal_index_; }
3062 int depth() const { return depth_; }
3063
3064 DECLARE_INSTRUCTION(MaterializedLiteral)
3065
3066 private:
3067 int literal_index_;
3068 int depth_;
3069};
3070
3071
3072class HArrayLiteral: public HMaterializedLiteral {
3073 public:
3074 HArrayLiteral(Handle<FixedArray> constant_elements,
3075 int length,
3076 int literal_index,
3077 int depth)
3078 : HMaterializedLiteral(literal_index, depth),
3079 length_(length),
3080 constant_elements_(constant_elements) {}
3081
3082 Handle<FixedArray> constant_elements() const { return constant_elements_; }
3083 int length() const { return length_; }
3084
3085 bool IsCopyOnWrite() const;
3086
3087 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
3088
3089 private:
3090 int length_;
3091 Handle<FixedArray> constant_elements_;
3092};
3093
3094
3095class HObjectLiteral: public HMaterializedLiteral {
3096 public:
3097 HObjectLiteral(Handle<FixedArray> constant_properties,
3098 bool fast_elements,
3099 int literal_index,
3100 int depth)
3101 : HMaterializedLiteral(literal_index, depth),
3102 constant_properties_(constant_properties),
3103 fast_elements_(fast_elements) {}
3104
3105 Handle<FixedArray> constant_properties() const {
3106 return constant_properties_;
3107 }
3108 bool fast_elements() const { return fast_elements_; }
3109
3110 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
3111
3112 private:
3113 Handle<FixedArray> constant_properties_;
3114 bool fast_elements_;
3115};
3116
3117
3118class HRegExpLiteral: public HMaterializedLiteral {
3119 public:
3120 HRegExpLiteral(Handle<String> pattern,
3121 Handle<String> flags,
3122 int literal_index)
3123 : HMaterializedLiteral(literal_index, 0),
3124 pattern_(pattern),
3125 flags_(flags) { }
3126
3127 Handle<String> pattern() { return pattern_; }
3128 Handle<String> flags() { return flags_; }
3129
3130 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
3131
3132 private:
3133 Handle<String> pattern_;
3134 Handle<String> flags_;
3135};
3136
3137
3138class HFunctionLiteral: public HInstruction {
3139 public:
3140 HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
3141 : shared_info_(shared), pretenure_(pretenure) {
3142 set_representation(Representation::Tagged());
3143 }
3144
3145 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
3146
3147 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
3148 bool pretenure() const { return pretenure_; }
3149
3150 private:
3151 Handle<SharedFunctionInfo> shared_info_;
3152 bool pretenure_;
3153};
3154
3155
3156class HTypeof: public HUnaryOperation {
3157 public:
3158 explicit HTypeof(HValue* value) : HUnaryOperation(value) {
3159 set_representation(Representation::Tagged());
3160 }
3161
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003162 virtual Representation RequiredInputRepresentation(int index) const {
3163 return Representation::Tagged();
3164 }
3165
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003166 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
3167};
3168
3169
3170class HValueOf: public HUnaryOperation {
3171 public:
3172 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
3173 set_representation(Representation::Tagged());
3174 }
3175
3176 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
3177};
3178
3179
3180class HDeleteProperty: public HBinaryOperation {
3181 public:
3182 HDeleteProperty(HValue* obj, HValue* key)
3183 : HBinaryOperation(obj, key) {
3184 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00003185 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003186 }
3187
3188 virtual Representation RequiredInputRepresentation(int index) const {
3189 return Representation::Tagged();
3190 }
3191
3192 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
3193
3194 HValue* object() const { return left(); }
3195 HValue* key() const { return right(); }
3196};
3197
3198#undef DECLARE_INSTRUCTION
3199#undef DECLARE_CONCRETE_INSTRUCTION
3200
3201} } // namespace v8::internal
3202
3203#endif // V8_HYDROGEN_INSTRUCTIONS_H_