blob: 9f5170ca2bcc9e5f9d7dcdd9d5fccdbf1f2eb910 [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) \
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000051 V(BinaryCall) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000052 V(BinaryOperation) \
53 V(BitwiseBinaryOperation) \
54 V(Call) \
55 V(ControlInstruction) \
56 V(Instruction) \
57 V(LoadKeyed) \
58 V(MaterializedLiteral) \
59 V(Phi) \
60 V(StoreKeyed) \
61 V(StoreNamed) \
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000062 V(UnaryCall) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000063 V(UnaryControlInstruction) \
64 V(UnaryOperation) \
65 HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
66
67
68#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000069 V(AbnormalExit) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000070 V(AccessArgumentsAt) \
71 V(Add) \
72 V(ApplyArguments) \
73 V(ArgumentsElements) \
74 V(ArgumentsLength) \
75 V(ArgumentsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000076 V(ArrayLiteral) \
77 V(BitAnd) \
78 V(BitNot) \
79 V(BitOr) \
80 V(BitXor) \
81 V(BlockEntry) \
82 V(BoundsCheck) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000083 V(CallConstantFunction) \
84 V(CallFunction) \
85 V(CallGlobal) \
86 V(CallKeyed) \
87 V(CallKnownGlobal) \
88 V(CallNamed) \
89 V(CallNew) \
90 V(CallRuntime) \
91 V(CallStub) \
92 V(Change) \
93 V(CheckFunction) \
94 V(CheckInstanceType) \
95 V(CheckMap) \
96 V(CheckNonSmi) \
97 V(CheckPrototypeMaps) \
98 V(CheckSmi) \
99 V(Compare) \
100 V(CompareJSObjectEq) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000101 V(CompareMap) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000102 V(Constant) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000103 V(Context) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000104 V(DeleteProperty) \
105 V(Deoptimize) \
106 V(Div) \
107 V(EnterInlined) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000108 V(FixedArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000109 V(FunctionLiteral) \
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000110 V(GetCachedArrayIndex) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000111 V(GlobalObject) \
112 V(GlobalReceiver) \
113 V(Goto) \
114 V(InstanceOf) \
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000115 V(InstanceOfKnownGlobal) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000116 V(IsNull) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000117 V(IsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000118 V(IsSmi) \
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000119 V(IsConstructCall) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000120 V(HasInstanceType) \
121 V(HasCachedArrayIndex) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000122 V(JSArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000123 V(ClassOfTest) \
124 V(LeaveInlined) \
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000125 V(LoadContextSlot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000126 V(LoadElements) \
ager@chromium.org378b34e2011-01-28 08:04:38 +0000127 V(LoadFunctionPrototype) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000128 V(LoadGlobal) \
129 V(LoadKeyedFastElement) \
130 V(LoadKeyedGeneric) \
131 V(LoadNamedField) \
132 V(LoadNamedGeneric) \
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000133 V(LoadPixelArrayElement) \
134 V(LoadPixelArrayExternalPointer) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000135 V(Mod) \
136 V(Mul) \
137 V(ObjectLiteral) \
138 V(OsrEntry) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000139 V(OuterContext) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000140 V(Parameter) \
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000141 V(PixelArrayLength) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000142 V(Power) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000143 V(PushArgument) \
144 V(RegExpLiteral) \
145 V(Return) \
146 V(Sar) \
147 V(Shl) \
148 V(Shr) \
149 V(Simulate) \
150 V(StackCheck) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000151 V(StoreContextSlot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000152 V(StoreGlobal) \
153 V(StoreKeyedFastElement) \
154 V(StoreKeyedGeneric) \
155 V(StoreNamedField) \
156 V(StoreNamedGeneric) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000157 V(StringCharCodeAt) \
158 V(StringLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000159 V(Sub) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000160 V(Test) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000161 V(Throw) \
162 V(Typeof) \
163 V(TypeofIs) \
164 V(UnaryMathOperation) \
165 V(UnknownOSRValue) \
166 V(ValueOf)
167
168#define GVN_FLAG_LIST(V) \
169 V(Calls) \
170 V(InobjectFields) \
171 V(BackingStoreFields) \
172 V(ArrayElements) \
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000173 V(PixelArrayElements) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000174 V(GlobalVars) \
175 V(Maps) \
176 V(ArrayLengths) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000177 V(ContextSlots) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000178 V(OsrEntries)
179
180#define DECLARE_INSTRUCTION(type) \
181 virtual bool Is##type() const { return true; } \
182 static H##type* cast(HValue* value) { \
183 ASSERT(value->Is##type()); \
184 return reinterpret_cast<H##type*>(value); \
185 } \
186 Opcode opcode() const { return HValue::k##type; }
187
188
189#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
190 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
191 virtual const char* Mnemonic() const { return mnemonic; } \
192 DECLARE_INSTRUCTION(type)
193
194
195
196template<int kSize>
197class HOperandVector : public EmbeddedVector<HValue*, kSize> {
198 public:
199 HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
200};
201
202
203class Range: public ZoneObject {
204 public:
205 Range() : lower_(kMinInt),
206 upper_(kMaxInt),
207 next_(NULL),
208 can_be_minus_zero_(false) { }
209
210 Range(int32_t lower, int32_t upper)
211 : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
212
213 bool IsInSmiRange() const {
214 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
215 }
216 void KeepOrder();
217 void Verify() const;
218 int32_t upper() const { return upper_; }
219 int32_t lower() const { return lower_; }
220 Range* next() const { return next_; }
221 Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
222 Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
223 void ClearLower() { lower_ = kMinInt; }
224 void ClearUpper() { upper_ = kMaxInt; }
225 Range* Copy() const { return new Range(lower_, upper_); }
226 bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
227 int32_t Mask() const;
228 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
229 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
230 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
231 bool CanBeNegative() const { return lower_ < 0; }
232 bool Includes(int value) const {
233 return lower_ <= value && upper_ >= value;
234 }
235
236 void Sar(int32_t value) {
237 int32_t bits = value & 0x1F;
238 lower_ = lower_ >> bits;
239 upper_ = upper_ >> bits;
240 set_can_be_minus_zero(false);
241 }
242
243 void Shl(int32_t value) {
244 int32_t bits = value & 0x1F;
245 int old_lower = lower_;
246 int old_upper = upper_;
247 lower_ = lower_ << bits;
248 upper_ = upper_ << bits;
249 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
250 upper_ = kMaxInt;
251 lower_ = kMinInt;
252 }
253 set_can_be_minus_zero(false);
254 }
255
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000256 // Adds a constant to the lower and upper bound of the range.
257 void AddConstant(int32_t value);
258
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000259 void StackUpon(Range* other) {
260 Intersect(other);
261 next_ = other;
262 }
263
264 void Intersect(Range* other) {
265 upper_ = Min(upper_, other->upper_);
266 lower_ = Max(lower_, other->lower_);
267 bool b = CanBeMinusZero() && other->CanBeMinusZero();
268 set_can_be_minus_zero(b);
269 }
270
271 void Union(Range* other) {
272 upper_ = Max(upper_, other->upper_);
273 lower_ = Min(lower_, other->lower_);
274 bool b = CanBeMinusZero() || other->CanBeMinusZero();
275 set_can_be_minus_zero(b);
276 }
277
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000278 // Compute a new result range and return true, if the operation
279 // can overflow.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000280 bool AddAndCheckOverflow(Range* other);
281 bool SubAndCheckOverflow(Range* other);
282 bool MulAndCheckOverflow(Range* other);
283
284 private:
285 int32_t lower_;
286 int32_t upper_;
287 Range* next_;
288 bool can_be_minus_zero_;
289};
290
291
292class Representation {
293 public:
294 enum Kind {
295 kNone,
296 kTagged,
297 kDouble,
298 kInteger32,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000299 kExternal,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000300 kNumRepresentations
301 };
302
303 Representation() : kind_(kNone) { }
304
305 static Representation None() { return Representation(kNone); }
306 static Representation Tagged() { return Representation(kTagged); }
307 static Representation Integer32() { return Representation(kInteger32); }
308 static Representation Double() { return Representation(kDouble); }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000309 static Representation External() { return Representation(kExternal); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000310
311 bool Equals(const Representation& other) const {
312 return kind_ == other.kind_;
313 }
314
315 Kind kind() const { return kind_; }
316 bool IsNone() const { return kind_ == kNone; }
317 bool IsTagged() const { return kind_ == kTagged; }
318 bool IsInteger32() const { return kind_ == kInteger32; }
319 bool IsDouble() const { return kind_ == kDouble; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000320 bool IsExternal() const { return kind_ == kExternal; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000321 bool IsSpecialization() const {
322 return kind_ == kInteger32 || kind_ == kDouble;
323 }
324 const char* Mnemonic() const;
325
326 private:
327 explicit Representation(Kind k) : kind_(k) { }
328
329 Kind kind_;
330};
331
332
333class HType {
334 public:
335 HType() : type_(kUninitialized) { }
336
337 static HType Tagged() { return HType(kTagged); }
338 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
339 static HType TaggedNumber() { return HType(kTaggedNumber); }
340 static HType Smi() { return HType(kSmi); }
341 static HType HeapNumber() { return HType(kHeapNumber); }
342 static HType String() { return HType(kString); }
343 static HType Boolean() { return HType(kBoolean); }
344 static HType NonPrimitive() { return HType(kNonPrimitive); }
345 static HType JSArray() { return HType(kJSArray); }
346 static HType JSObject() { return HType(kJSObject); }
347 static HType Uninitialized() { return HType(kUninitialized); }
348
349 // Return the weakest (least precise) common type.
350 HType Combine(HType other) {
351 return HType(static_cast<Type>(type_ & other.type_));
352 }
353
354 bool Equals(const HType& other) {
355 return type_ == other.type_;
356 }
357
358 bool IsSubtypeOf(const HType& other) {
359 return Combine(other).Equals(other);
360 }
361
362 bool IsTagged() {
363 ASSERT(type_ != kUninitialized);
364 return ((type_ & kTagged) == kTagged);
365 }
366
367 bool IsTaggedPrimitive() {
368 ASSERT(type_ != kUninitialized);
369 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
370 }
371
372 bool IsTaggedNumber() {
373 ASSERT(type_ != kUninitialized);
374 return ((type_ & kTaggedNumber) == kTaggedNumber);
375 }
376
377 bool IsSmi() {
378 ASSERT(type_ != kUninitialized);
379 return ((type_ & kSmi) == kSmi);
380 }
381
382 bool IsHeapNumber() {
383 ASSERT(type_ != kUninitialized);
384 return ((type_ & kHeapNumber) == kHeapNumber);
385 }
386
387 bool IsString() {
388 ASSERT(type_ != kUninitialized);
389 return ((type_ & kString) == kString);
390 }
391
392 bool IsBoolean() {
393 ASSERT(type_ != kUninitialized);
394 return ((type_ & kBoolean) == kBoolean);
395 }
396
397 bool IsNonPrimitive() {
398 ASSERT(type_ != kUninitialized);
399 return ((type_ & kNonPrimitive) == kNonPrimitive);
400 }
401
402 bool IsJSArray() {
403 ASSERT(type_ != kUninitialized);
404 return ((type_ & kJSArray) == kJSArray);
405 }
406
407 bool IsJSObject() {
408 ASSERT(type_ != kUninitialized);
409 return ((type_ & kJSObject) == kJSObject);
410 }
411
412 bool IsUninitialized() {
413 return type_ == kUninitialized;
414 }
415
416 static HType TypeFromValue(Handle<Object> value);
417
418 const char* ToString();
419 const char* ToShortString();
420
421 private:
422 enum Type {
423 kTagged = 0x1, // 0000 0000 0000 0001
424 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
425 kTaggedNumber = 0xd, // 0000 0000 0000 1101
426 kSmi = 0x1d, // 0000 0000 0001 1101
427 kHeapNumber = 0x2d, // 0000 0000 0010 1101
428 kString = 0x45, // 0000 0000 0100 0101
429 kBoolean = 0x85, // 0000 0000 1000 0101
430 kNonPrimitive = 0x101, // 0000 0001 0000 0001
431 kJSObject = 0x301, // 0000 0011 0000 0001
432 kJSArray = 0x701, // 0000 0111 1000 0001
433 kUninitialized = 0x1fff // 0001 1111 1111 1111
434 };
435
436 explicit HType(Type t) : type_(t) { }
437
438 Type type_;
439};
440
441
442class HValue: public ZoneObject {
443 public:
444 static const int kNoNumber = -1;
445
446 // There must be one corresponding kDepends flag for every kChanges flag and
447 // the order of the kChanges flags must be exactly the same as of the kDepends
448 // flags.
449 enum Flag {
450 // Declare global value numbering flags.
451 #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
452 GVN_FLAG_LIST(DECLARE_DO)
453 #undef DECLARE_DO
454 kFlexibleRepresentation,
455 kUseGVN,
456 kCanOverflow,
457 kBailoutOnMinusZero,
458 kCanBeDivByZero,
459 kIsArguments,
460 kTruncatingToInt32,
461 kLastFlag = kTruncatingToInt32
462 };
463
464 STATIC_ASSERT(kLastFlag < kBitsPerInt);
465
466 static const int kChangesToDependsFlagsLeftShift = 1;
467
468 static int ChangesFlagsMask() {
469 int result = 0;
470 // Create changes mask.
471#define DECLARE_DO(type) result |= (1 << kChanges##type);
472 GVN_FLAG_LIST(DECLARE_DO)
473#undef DECLARE_DO
474 return result;
475 }
476
477 static int DependsFlagsMask() {
478 return ConvertChangesToDependsFlags(ChangesFlagsMask());
479 }
480
481 static int ConvertChangesToDependsFlags(int flags) {
482 return flags << kChangesToDependsFlagsLeftShift;
483 }
484
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000485 static HValue* cast(HValue* value) { return value; }
486
487 enum Opcode {
488 // Declare a unique enum value for each hydrogen instruction.
489 #define DECLARE_DO(type) k##type,
490 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
491 #undef DECLARE_DO
492 kMaxInstructionClass
493 };
494
495 HValue() : block_(NULL),
496 id_(kNoNumber),
497 uses_(2),
498 type_(HType::Tagged()),
499 range_(NULL),
500 flags_(0) {}
501 virtual ~HValue() {}
502
503 HBasicBlock* block() const { return block_; }
504 void SetBlock(HBasicBlock* block);
505
506 int id() const { return id_; }
507 void set_id(int id) { id_ = id; }
508
509 const ZoneList<HValue*>* uses() const { return &uses_; }
510
511 virtual bool EmitAtUses() const { return false; }
512 Representation representation() const { return representation_; }
513 void ChangeRepresentation(Representation r) {
514 // Representation was already set and is allowed to be changed.
515 ASSERT(!representation_.IsNone());
516 ASSERT(!r.IsNone());
517 ASSERT(CheckFlag(kFlexibleRepresentation));
518 RepresentationChanged(r);
519 representation_ = r;
520 }
521
522 HType type() const { return type_; }
523 void set_type(HType type) {
524 ASSERT(uses_.length() == 0);
525 type_ = type;
526 }
527
528 // An operation needs to override this function iff:
529 // 1) it can produce an int32 output.
530 // 2) the true value of its output can potentially be minus zero.
531 // The implementation must set a flag so that it bails out in the case where
532 // it would otherwise output what should be a minus zero as an int32 zero.
533 // If the operation also exists in a form that takes int32 and outputs int32
534 // then the operation should return its input value so that we can propagate
535 // back. There are two operations that need to propagate back to more than
536 // one input. They are phi and binary add. They always return NULL and
537 // expect the caller to take care of things.
538 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
539 visited->Add(id());
540 return NULL;
541 }
542
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000543 bool IsDefinedAfter(HBasicBlock* other) const;
544
545 // Operands.
546 virtual int OperandCount() const { return 0; }
547 virtual HValue* OperandAt(int index) const {
548 UNREACHABLE();
549 return NULL;
550 }
551 void SetOperandAt(int index, HValue* value);
552
553 int LookupOperandIndex(int occurrence_index, HValue* op) const;
554 bool UsesMultipleTimes(HValue* op) const;
555
556 void ReplaceAndDelete(HValue* other);
557 void ReplaceValue(HValue* other);
558 void ReplaceAtUse(HValue* use, HValue* other);
559 void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
560 bool HasNoUses() const { return uses_.is_empty(); }
561 void ClearOperands();
562 void Delete();
563
564 int flags() const { return flags_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000565 void SetFlag(Flag f) { flags_ |= (1 << f); }
566 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
567 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
568
569 void SetAllSideEffects() { flags_ |= AllSideEffects(); }
570 void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
571 bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000572
573 Range* range() const { return range_; }
574 bool HasRange() const { return range_ != NULL; }
575 void AddNewRange(Range* r);
576 void RemoveLastAddedRange();
577 void ComputeInitialRange();
578
579 // Representation helpers.
580 virtual Representation RequiredInputRepresentation(int index) const {
581 return Representation::None();
582 }
583 virtual Representation InferredRepresentation() const {
584 return representation();
585 }
586
587 // This gives the instruction an opportunity to replace itself with an
588 // instruction that does the same in some better way. To replace an
589 // instruction with a new one, first add the new instruction to the graph,
590 // then return it. Return NULL to have the instruction deleted.
591 virtual HValue* Canonicalize() { return this; }
592
593 // Declare virtual type testers.
594#define DECLARE_DO(type) virtual bool Is##type() const { return false; }
595 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
596#undef DECLARE_DO
597
598 bool Equals(HValue* other) const;
599 virtual intptr_t Hashcode() const;
600
601 // Printing support.
602 virtual void PrintTo(StringStream* stream) const = 0;
603 void PrintNameTo(StringStream* stream);
604 static void PrintTypeTo(HType type, StringStream* stream);
605
606 virtual const char* Mnemonic() const = 0;
607 virtual Opcode opcode() const = 0;
608
609 // Updated the inferred type of this instruction and returns true if
610 // it has changed.
611 bool UpdateInferredType();
612
613 virtual HType CalculateInferredType() const;
614
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000615#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000616 virtual void Verify() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000617#endif
618
619 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000620 // This function must be overridden for instructions with flag kUseGVN, to
621 // compare the non-Operand parts of the instruction.
622 virtual bool DataEquals(HValue* other) const {
623 UNREACHABLE();
624 return false;
625 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000626 virtual void RepresentationChanged(Representation to) { }
627 virtual Range* InferRange();
628 virtual void DeleteFromGraph() = 0;
629 virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
630 void clear_block() {
631 ASSERT(block_ != NULL);
632 block_ = NULL;
633 }
634
635 void set_representation(Representation r) {
636 // Representation is set-once.
637 ASSERT(representation_.IsNone() && !r.IsNone());
638 representation_ = r;
639 }
640
641 private:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000642 // A flag mask to mark an instruction as having arbitrary side effects.
643 static int AllSideEffects() {
644 return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
645 }
646
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000647 void InternalReplaceAtUse(HValue* use, HValue* other);
648 void RegisterUse(int index, HValue* new_value);
649
650 HBasicBlock* block_;
651
652 // The id of this instruction in the hydrogen graph, assigned when first
653 // added to the graph. Reflects creation order.
654 int id_;
655
656 Representation representation_;
657 ZoneList<HValue*> uses_;
658 HType type_;
659 Range* range_;
660 int flags_;
661
662 DISALLOW_COPY_AND_ASSIGN(HValue);
663};
664
665
666class HInstruction: public HValue {
667 public:
668 HInstruction* next() const { return next_; }
669 HInstruction* previous() const { return previous_; }
670
671 void PrintTo(StringStream* stream) const;
672 virtual void PrintDataTo(StringStream* stream) const {}
673
674 bool IsLinked() const { return block() != NULL; }
675 void Unlink();
676 void InsertBefore(HInstruction* next);
677 void InsertAfter(HInstruction* previous);
678
679 int position() const { return position_; }
680 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
681 void set_position(int position) { position_ = position; }
682
683 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
684
685#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000686 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000687#endif
688
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000689 // Returns whether this is some kind of deoptimizing check
690 // instruction.
691 virtual bool IsCheckInstruction() const { return false; }
692
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000693 DECLARE_INSTRUCTION(Instruction)
694
695 protected:
696 HInstruction()
697 : next_(NULL),
698 previous_(NULL),
699 position_(RelocInfo::kNoPosition) {
700 SetFlag(kDependsOnOsrEntries);
701 }
702
703 virtual void DeleteFromGraph() { Unlink(); }
704
705 private:
706 void InitializeAsFirst(HBasicBlock* block) {
707 ASSERT(!IsLinked());
708 SetBlock(block);
709 }
710
711 HInstruction* next_;
712 HInstruction* previous_;
713 int position_;
714
715 friend class HBasicBlock;
716};
717
718
719class HBlockEntry: public HInstruction {
720 public:
721 DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
722};
723
724
725class HControlInstruction: public HInstruction {
726 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000727 HControlInstruction(HBasicBlock* first, HBasicBlock* second)
728 : first_successor_(first), second_successor_(second) {
729 }
730
731 HBasicBlock* FirstSuccessor() const { return first_successor_; }
732 HBasicBlock* SecondSuccessor() const { return second_successor_; }
733
734 virtual void PrintDataTo(StringStream* stream) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000735
736 DECLARE_INSTRUCTION(ControlInstruction)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000737
738 private:
739 HBasicBlock* first_successor_;
740 HBasicBlock* second_successor_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000741};
742
743
744class HDeoptimize: public HControlInstruction {
745 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000746 HDeoptimize() : HControlInstruction(NULL, NULL) { }
747
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000748 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
749};
750
751
752class HGoto: public HControlInstruction {
753 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000754 explicit HGoto(HBasicBlock* target)
755 : HControlInstruction(target, NULL), include_stack_check_(false) {
756 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000757
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000758 void set_include_stack_check(bool include_stack_check) {
759 include_stack_check_ = include_stack_check;
760 }
761 bool include_stack_check() const { return include_stack_check_; }
762
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000763 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
764
765 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000766 bool include_stack_check_;
767};
768
769
770class HUnaryControlInstruction: public HControlInstruction {
771 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000772 explicit HUnaryControlInstruction(HValue* value,
773 HBasicBlock* true_target,
774 HBasicBlock* false_target)
775 : HControlInstruction(true_target, false_target) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000776 SetOperandAt(0, value);
777 }
778
779 virtual Representation RequiredInputRepresentation(int index) const {
780 return Representation::Tagged();
781 }
782
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000783 virtual void PrintDataTo(StringStream* stream) const;
784
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000785 HValue* value() const { return OperandAt(0); }
786 virtual int OperandCount() const { return 1; }
787 virtual HValue* OperandAt(int index) const { return operands_[index]; }
788
789 DECLARE_INSTRUCTION(UnaryControlInstruction)
790
791 protected:
792 virtual void InternalSetOperandAt(int index, HValue* value) {
793 operands_[index] = value;
794 }
795
796 private:
797 HOperandVector<1> operands_;
798};
799
800
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000801class HTest: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000802 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000803 HTest(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target)
804 : HUnaryControlInstruction(value, true_target, false_target) {
805 ASSERT(true_target != NULL && false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000806 }
807
808 virtual Representation RequiredInputRepresentation(int index) const {
809 return Representation::None();
810 }
811
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000812 DECLARE_CONCRETE_INSTRUCTION(Test, "test")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000813};
814
815
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000816class HCompareMap: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000817 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000818 HCompareMap(HValue* value,
819 Handle<Map> map,
820 HBasicBlock* true_target,
821 HBasicBlock* false_target)
822 : HUnaryControlInstruction(value, true_target, false_target),
823 map_(map) {
824 ASSERT(true_target != NULL);
825 ASSERT(false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000826 ASSERT(!map.is_null());
827 }
828
whesse@chromium.org023421e2010-12-21 12:19:12 +0000829 virtual void PrintDataTo(StringStream* stream) const;
830
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000831 Handle<Map> map() const { return map_; }
832
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000833 DECLARE_CONCRETE_INSTRUCTION(CompareMap, "compare_map")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000834
835 private:
836 Handle<Map> map_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000837};
838
839
840class HReturn: public HUnaryControlInstruction {
841 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000842 explicit HReturn(HValue* value)
843 : HUnaryControlInstruction(value, NULL, NULL) {
844 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000845
846 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
847};
848
849
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000850class HAbnormalExit: public HControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000851 public:
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000852 HAbnormalExit() : HControlInstruction(NULL, NULL) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000853
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000854 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000855};
856
857
858class HUnaryOperation: public HInstruction {
859 public:
860 explicit HUnaryOperation(HValue* value) {
861 SetOperandAt(0, value);
862 }
863
864 HValue* value() const { return OperandAt(0); }
865 virtual void PrintDataTo(StringStream* stream) const;
866 virtual int OperandCount() const { return 1; }
867 virtual HValue* OperandAt(int index) const { return operands_[index]; }
868
869 DECLARE_INSTRUCTION(UnaryOperation)
870
871 protected:
872 virtual void InternalSetOperandAt(int index, HValue* value) {
873 operands_[index] = value;
874 }
875
876 private:
877 HOperandVector<1> operands_;
878};
879
880
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000881class HThrow: public HUnaryOperation {
882 public:
883 explicit HThrow(HValue* value) : HUnaryOperation(value) {
884 SetAllSideEffects();
885 }
886
887 virtual Representation RequiredInputRepresentation(int index) const {
888 return Representation::Tagged();
889 }
890
891 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
892};
893
894
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000895class HChange: public HUnaryOperation {
896 public:
897 HChange(HValue* value,
898 Representation from,
899 Representation to)
900 : HUnaryOperation(value), from_(from), to_(to) {
901 ASSERT(!from.IsNone() && !to.IsNone());
902 ASSERT(!from.Equals(to));
903 set_representation(to);
904 SetFlag(kUseGVN);
905
906 if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
907 value->range()->IsInSmiRange()) {
908 set_type(HType::Smi());
909 }
910 }
911
912 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
913
914 Representation from() const { return from_; }
915 Representation to() const { return to_; }
916 virtual Representation RequiredInputRepresentation(int index) const {
917 return from_;
918 }
919
920 bool CanTruncateToInt32() const {
921 for (int i = 0; i < uses()->length(); ++i) {
922 if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
923 }
924 return true;
925 }
926
927 virtual void PrintDataTo(StringStream* stream) const;
928
929 DECLARE_CONCRETE_INSTRUCTION(Change,
930 CanTruncateToInt32() ? "truncate" : "change")
931
932 protected:
933 virtual bool DataEquals(HValue* other) const {
934 if (!other->IsChange()) return false;
935 HChange* change = HChange::cast(other);
936 return value() == change->value()
937 && to().Equals(change->to())
938 && CanTruncateToInt32() == change->CanTruncateToInt32();
939 }
940
941 private:
942 Representation from_;
943 Representation to_;
944};
945
946
947class HSimulate: public HInstruction {
948 public:
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000949 HSimulate(int ast_id, int pop_count, int environment_length)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000950 : ast_id_(ast_id),
951 pop_count_(pop_count),
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000952 environment_length_(environment_length),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000953 values_(2),
954 assigned_indexes_(2) {}
955 virtual ~HSimulate() {}
956
957 virtual void PrintDataTo(StringStream* stream) const;
958
959 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
960 int ast_id() const { return ast_id_; }
961 void set_ast_id(int id) {
962 ASSERT(!HasAstId());
963 ast_id_ = id;
964 }
965
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000966 int environment_length() const { return environment_length_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000967 int pop_count() const { return pop_count_; }
968 const ZoneList<HValue*>* values() const { return &values_; }
969 int GetAssignedIndexAt(int index) const {
970 ASSERT(HasAssignedIndexAt(index));
971 return assigned_indexes_[index];
972 }
973 bool HasAssignedIndexAt(int index) const {
974 return assigned_indexes_[index] != kNoIndex;
975 }
976 void AddAssignedValue(int index, HValue* value) {
977 AddValue(index, value);
978 }
979 void AddPushedValue(HValue* value) {
980 AddValue(kNoIndex, value);
981 }
982 virtual int OperandCount() const { return values_.length(); }
983 virtual HValue* OperandAt(int index) const { return values_[index]; }
984
985 DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
986
987#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000988 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000989#endif
990
991 protected:
992 virtual void InternalSetOperandAt(int index, HValue* value) {
993 values_[index] = value;
994 }
995
996 private:
997 static const int kNoIndex = -1;
998 void AddValue(int index, HValue* value) {
999 assigned_indexes_.Add(index);
1000 // Resize the list of pushed values.
1001 values_.Add(NULL);
1002 // Set the operand through the base method in HValue to make sure that the
1003 // use lists are correctly updated.
1004 SetOperandAt(values_.length() - 1, value);
1005 }
1006 int ast_id_;
1007 int pop_count_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001008 int environment_length_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001009 ZoneList<HValue*> values_;
1010 ZoneList<int> assigned_indexes_;
1011};
1012
1013
1014class HStackCheck: public HInstruction {
1015 public:
1016 HStackCheck() { }
1017
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001018 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001019};
1020
1021
1022class HEnterInlined: public HInstruction {
1023 public:
1024 HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
1025 : closure_(closure), function_(function) {
1026 }
1027
1028 virtual void PrintDataTo(StringStream* stream) const;
1029
1030 Handle<JSFunction> closure() const { return closure_; }
1031 FunctionLiteral* function() const { return function_; }
1032
1033 DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
1034
1035 private:
1036 Handle<JSFunction> closure_;
1037 FunctionLiteral* function_;
1038};
1039
1040
1041class HLeaveInlined: public HInstruction {
1042 public:
1043 HLeaveInlined() {}
1044
1045 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
1046};
1047
1048
1049class HPushArgument: public HUnaryOperation {
1050 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001051 explicit HPushArgument(HValue* value) : HUnaryOperation(value) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001052
1053 virtual Representation RequiredInputRepresentation(int index) const {
1054 return Representation::Tagged();
1055 }
1056
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001057 HValue* argument() const { return OperandAt(0); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001058
1059 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001060};
1061
1062
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001063class HContext: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001064 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001065 HContext() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001066 set_representation(Representation::Tagged());
1067 SetFlag(kUseGVN);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001068 }
1069
1070 DECLARE_CONCRETE_INSTRUCTION(Context, "context");
1071
1072 protected:
1073 virtual bool DataEquals(HValue* other) const { return true; }
1074};
1075
1076
1077class HOuterContext: public HUnaryOperation {
1078 public:
1079 explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
1080 set_representation(Representation::Tagged());
1081 SetFlag(kUseGVN);
1082 }
1083
1084 DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer_context");
1085
1086 protected:
1087 virtual bool DataEquals(HValue* other) const { return true; }
1088};
1089
1090
1091class HGlobalObject: public HUnaryOperation {
1092 public:
1093 explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
1094 set_representation(Representation::Tagged());
1095 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001096 }
1097
1098 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001099
1100 protected:
1101 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001102};
1103
1104
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001105class HGlobalReceiver: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001106 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001107 explicit HGlobalReceiver(HValue* global_object)
1108 : HUnaryOperation(global_object) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001109 set_representation(Representation::Tagged());
1110 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001111 }
1112
1113 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001114
1115 protected:
1116 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001117};
1118
1119
1120class HCall: public HInstruction {
1121 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001122 // The argument count includes the receiver.
1123 explicit HCall(int argument_count) : argument_count_(argument_count) {
1124 set_representation(Representation::Tagged());
1125 SetAllSideEffects();
1126 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001127
1128 virtual HType CalculateInferredType() const { return HType::Tagged(); }
1129
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001130 virtual int argument_count() const { return argument_count_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001131
1132 virtual void PrintDataTo(StringStream* stream) const;
1133
1134 DECLARE_INSTRUCTION(Call)
1135
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001136 private:
1137 int argument_count_;
1138};
1139
1140
1141class HUnaryCall: public HCall {
1142 public:
1143 HUnaryCall(HValue* value, int argument_count)
1144 : HCall(argument_count), value_(NULL) {
1145 SetOperandAt(0, value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001146 }
1147
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001148 virtual void PrintDataTo(StringStream* stream) const;
1149
1150 HValue* value() const { return value_; }
1151
1152 virtual int OperandCount() const { return 1; }
1153 virtual HValue* OperandAt(int index) const {
1154 ASSERT(index == 0);
1155 return value_;
1156 }
1157
1158 DECLARE_INSTRUCTION(UnaryCall)
1159
1160 protected:
1161 virtual void InternalSetOperandAt(int index, HValue* value) {
1162 ASSERT(index == 0);
1163 value_ = value;
1164 }
1165
1166 private:
1167 HValue* value_;
1168};
1169
1170
1171class HBinaryCall: public HCall {
1172 public:
1173 HBinaryCall(HValue* first, HValue* second, int argument_count)
1174 : HCall(argument_count) {
1175 SetOperandAt(0, first);
1176 SetOperandAt(1, second);
1177 }
1178
1179 virtual void PrintDataTo(StringStream* stream) const;
1180
1181 HValue* first() const { return operands_[0]; }
1182 HValue* second() const { return operands_[1]; }
1183
1184 virtual int OperandCount() const { return 2; }
1185 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1186
1187 DECLARE_INSTRUCTION(BinaryCall)
1188
1189 protected:
1190 virtual void InternalSetOperandAt(int index, HValue* value) {
1191 operands_[index] = value;
1192 }
1193
1194 private:
1195 HOperandVector<2> operands_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001196};
1197
1198
1199class HCallConstantFunction: public HCall {
1200 public:
1201 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1202 : HCall(argument_count), function_(function) { }
1203
1204 Handle<JSFunction> function() const { return function_; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001205
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001206 bool IsApplyFunction() const {
1207 return function_->code() == Builtins::builtin(Builtins::FunctionApply);
1208 }
1209
1210 virtual void PrintDataTo(StringStream* stream) const;
1211
1212 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
1213
1214 private:
1215 Handle<JSFunction> function_;
1216};
1217
1218
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001219class HCallKeyed: public HBinaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001220 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001221 HCallKeyed(HValue* context, HValue* key, int argument_count)
1222 : HBinaryCall(context, key, argument_count) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001223 }
1224
1225 virtual Representation RequiredInputRepresentation(int index) const {
1226 return Representation::Tagged();
1227 }
1228
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001229 HValue* context() const { return first(); }
1230 HValue* key() const { return second(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001231
1232 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
1233};
1234
1235
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001236class HCallNamed: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001237 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001238 HCallNamed(HValue* context, Handle<String> name, int argument_count)
1239 : HUnaryCall(context, argument_count), name_(name) {
1240 }
1241
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001242 virtual void PrintDataTo(StringStream* stream) const;
1243
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001244 HValue* context() const { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001245 Handle<String> name() const { return name_; }
1246
1247 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
1248
1249 private:
1250 Handle<String> name_;
1251};
1252
1253
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001254class HCallFunction: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001255 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001256 HCallFunction(HValue* context, int argument_count)
1257 : HUnaryCall(context, argument_count) {
1258 }
1259
1260 HValue* context() const { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001261
1262 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
1263};
1264
1265
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001266class HCallGlobal: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001267 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001268 HCallGlobal(HValue* context, Handle<String> name, int argument_count)
1269 : HUnaryCall(context, argument_count), name_(name) {
1270 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001271
1272 virtual void PrintDataTo(StringStream* stream) const;
1273
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001274 HValue* context() const { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001275 Handle<String> name() const { return name_; }
1276
1277 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
1278
1279 private:
1280 Handle<String> name_;
1281};
1282
1283
1284class HCallKnownGlobal: public HCall {
1285 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001286 HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001287 : HCall(argument_count), target_(target) { }
1288
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001289 virtual void PrintDataTo(StringStream* stream) const;
1290
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001291 Handle<JSFunction> target() const { return target_; }
1292
1293 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
1294
1295 private:
1296 Handle<JSFunction> target_;
1297};
1298
1299
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001300class HCallNew: public HBinaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001301 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001302 HCallNew(HValue* context, HValue* constructor, int argument_count)
1303 : HBinaryCall(context, constructor, argument_count) {
1304 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001305
1306 virtual Representation RequiredInputRepresentation(int index) const {
1307 return Representation::Tagged();
1308 }
1309
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001310 HValue* context() const { return first(); }
1311 HValue* constructor() const { return second(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001312
1313 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
1314};
1315
1316
1317class HCallRuntime: public HCall {
1318 public:
1319 HCallRuntime(Handle<String> name,
1320 Runtime::Function* c_function,
1321 int argument_count)
1322 : HCall(argument_count), c_function_(c_function), name_(name) { }
1323 virtual void PrintDataTo(StringStream* stream) const;
1324
1325 Runtime::Function* function() const { return c_function_; }
1326 Handle<String> name() const { return name_; }
1327
1328 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
1329
1330 private:
1331 Runtime::Function* c_function_;
1332 Handle<String> name_;
1333};
1334
1335
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001336class HJSArrayLength: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001337 public:
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001338 explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001339 // The length of an array is stored as a tagged value in the array
1340 // object. It is guaranteed to be 32 bit integer, but it can be
1341 // represented as either a smi or heap number.
1342 set_representation(Representation::Tagged());
1343 SetFlag(kDependsOnArrayLengths);
1344 SetFlag(kUseGVN);
1345 }
1346
1347 virtual Representation RequiredInputRepresentation(int index) const {
1348 return Representation::Tagged();
1349 }
1350
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001351 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001352
1353 protected:
1354 virtual bool DataEquals(HValue* other) const { return true; }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001355};
1356
1357
1358class HFixedArrayLength: public HUnaryOperation {
1359 public:
1360 explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
1361 set_representation(Representation::Tagged());
1362 SetFlag(kDependsOnArrayLengths);
1363 SetFlag(kUseGVN);
1364 }
1365
1366 virtual Representation RequiredInputRepresentation(int index) const {
1367 return Representation::Tagged();
1368 }
1369
1370 DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001371
1372 protected:
1373 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001374};
1375
1376
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001377class HPixelArrayLength: public HUnaryOperation {
1378 public:
1379 explicit HPixelArrayLength(HValue* value) : HUnaryOperation(value) {
1380 set_representation(Representation::Integer32());
1381 // The result of this instruction is idempotent as long as its inputs don't
1382 // change. The length of a pixel array cannot change once set, so it's not
1383 // necessary to introduce a kDependsOnArrayLengths or any other dependency.
1384 SetFlag(kUseGVN);
1385 }
1386
1387 virtual Representation RequiredInputRepresentation(int index) const {
1388 return Representation::Tagged();
1389 }
1390
1391 DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel_array_length")
1392
1393 protected:
1394 virtual bool DataEquals(HValue* other) const { return true; }
1395};
1396
1397
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001398class HBitNot: public HUnaryOperation {
1399 public:
1400 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1401 set_representation(Representation::Integer32());
1402 SetFlag(kUseGVN);
1403 SetFlag(kTruncatingToInt32);
1404 }
1405
1406 virtual Representation RequiredInputRepresentation(int index) const {
1407 return Representation::Integer32();
1408 }
1409 virtual HType CalculateInferredType() const;
1410
1411 DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001412
1413 protected:
1414 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001415};
1416
1417
1418class HUnaryMathOperation: public HUnaryOperation {
1419 public:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001420 HUnaryMathOperation(HValue* value, BuiltinFunctionId op)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001421 : HUnaryOperation(value), op_(op) {
1422 switch (op) {
1423 case kMathFloor:
1424 case kMathRound:
1425 case kMathCeil:
1426 set_representation(Representation::Integer32());
1427 break;
1428 case kMathAbs:
1429 set_representation(Representation::Tagged());
1430 SetFlag(kFlexibleRepresentation);
1431 break;
1432 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001433 case kMathPowHalf:
1434 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001435 case kMathSin:
1436 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001437 set_representation(Representation::Double());
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001438 break;
1439 default:
1440 UNREACHABLE();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001441 }
1442 SetFlag(kUseGVN);
1443 }
1444
1445 virtual void PrintDataTo(StringStream* stream) const;
1446
1447 virtual HType CalculateInferredType() const;
1448
1449 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1450
1451 virtual Representation RequiredInputRepresentation(int index) const {
1452 switch (op_) {
1453 case kMathFloor:
1454 case kMathRound:
1455 case kMathCeil:
1456 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001457 case kMathPowHalf:
1458 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001459 case kMathSin:
1460 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001461 return Representation::Double();
1462 break;
1463 case kMathAbs:
1464 return representation();
1465 break;
1466 default:
1467 return Representation::None();
1468 }
1469 }
1470
1471 virtual HValue* Canonicalize() {
1472 // If the input is integer32 then we replace the floor instruction
1473 // with its inputs. This happens before the representation changes are
1474 // introduced.
1475 if (op() == kMathFloor) {
1476 if (value()->representation().IsInteger32()) return value();
1477 }
1478 return this;
1479 }
1480
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001481 BuiltinFunctionId op() const { return op_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001482 const char* OpName() const;
1483
1484 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
1485
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001486 protected:
1487 virtual bool DataEquals(HValue* other) const {
1488 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
1489 return op_ == b->op();
1490 }
1491
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001492 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001493 BuiltinFunctionId op_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001494};
1495
1496
1497class HLoadElements: public HUnaryOperation {
1498 public:
1499 explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1500 set_representation(Representation::Tagged());
1501 SetFlag(kUseGVN);
1502 SetFlag(kDependsOnMaps);
1503 }
1504
1505 virtual Representation RequiredInputRepresentation(int index) const {
1506 return Representation::Tagged();
1507 }
1508
1509 DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001510
1511 protected:
1512 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001513};
1514
1515
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001516class HLoadPixelArrayExternalPointer: public HUnaryOperation {
1517 public:
1518 explicit HLoadPixelArrayExternalPointer(HValue* value)
1519 : HUnaryOperation(value) {
1520 set_representation(Representation::External());
1521 // The result of this instruction is idempotent as long as its inputs don't
1522 // change. The external array of a pixel array elements object cannot
1523 // change once set, so it's no necessary to introduce any additional
1524 // dependencies on top of the inputs.
1525 SetFlag(kUseGVN);
1526 }
1527
1528 virtual Representation RequiredInputRepresentation(int index) const {
1529 return Representation::Tagged();
1530 }
1531
1532 DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
1533 "load-pixel-array-external-pointer")
1534
1535 protected:
1536 virtual bool DataEquals(HValue* other) const { return true; }
1537};
1538
1539
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001540class HCheckMap: public HUnaryOperation {
1541 public:
1542 HCheckMap(HValue* value, Handle<Map> map)
1543 : HUnaryOperation(value), map_(map) {
1544 set_representation(Representation::Tagged());
1545 SetFlag(kUseGVN);
1546 SetFlag(kDependsOnMaps);
1547 }
1548
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001549 virtual bool IsCheckInstruction() const { return true; }
1550
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001551 virtual Representation RequiredInputRepresentation(int index) const {
1552 return Representation::Tagged();
1553 }
1554 virtual void PrintDataTo(StringStream* stream) const;
1555 virtual HType CalculateInferredType() const;
1556
1557#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001558 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001559#endif
1560
1561 Handle<Map> map() const { return map_; }
1562
1563 DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
1564
1565 protected:
1566 virtual bool DataEquals(HValue* other) const {
1567 HCheckMap* b = HCheckMap::cast(other);
1568 return map_.is_identical_to(b->map());
1569 }
1570
1571 private:
1572 Handle<Map> map_;
1573};
1574
1575
1576class HCheckFunction: public HUnaryOperation {
1577 public:
1578 HCheckFunction(HValue* value, Handle<JSFunction> function)
1579 : HUnaryOperation(value), target_(function) {
1580 set_representation(Representation::Tagged());
1581 SetFlag(kUseGVN);
1582 }
1583
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001584 virtual bool IsCheckInstruction() const { return true; }
1585
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001586 virtual Representation RequiredInputRepresentation(int index) const {
1587 return Representation::Tagged();
1588 }
1589 virtual void PrintDataTo(StringStream* stream) const;
1590 virtual HType CalculateInferredType() const;
1591
1592#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001593 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001594#endif
1595
1596 Handle<JSFunction> target() const { return target_; }
1597
1598 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
1599
1600 protected:
1601 virtual bool DataEquals(HValue* other) const {
1602 HCheckFunction* b = HCheckFunction::cast(other);
1603 return target_.is_identical_to(b->target());
1604 }
1605
1606 private:
1607 Handle<JSFunction> target_;
1608};
1609
1610
1611class HCheckInstanceType: public HUnaryOperation {
1612 public:
1613 // Check that the instance type is in the range [first, last] where
1614 // both first and last are included.
1615 HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
1616 : HUnaryOperation(value), first_(first), last_(last) {
1617 ASSERT(first <= last);
1618 set_representation(Representation::Tagged());
1619 SetFlag(kUseGVN);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001620 if ((FIRST_STRING_TYPE < first && last <= LAST_STRING_TYPE) ||
1621 (FIRST_STRING_TYPE <= first && last < LAST_STRING_TYPE)) {
1622 // A particular string instance type can change because of GC or
1623 // externalization, but the value still remains a string.
1624 SetFlag(kDependsOnMaps);
1625 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001626 }
1627
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001628 virtual bool IsCheckInstruction() const { return true; }
1629
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001630 virtual Representation RequiredInputRepresentation(int index) const {
1631 return Representation::Tagged();
1632 }
1633
1634#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001635 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001636#endif
1637
1638 static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
1639
1640 InstanceType first() const { return first_; }
1641 InstanceType last() const { return last_; }
1642
1643 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")
1644
1645 protected:
1646 // TODO(ager): It could be nice to allow the ommision of instance
1647 // type checks if we have already performed an instance type check
1648 // with a larger range.
1649 virtual bool DataEquals(HValue* other) const {
1650 HCheckInstanceType* b = HCheckInstanceType::cast(other);
1651 return (first_ == b->first()) && (last_ == b->last());
1652 }
1653
1654 private:
1655 InstanceType first_;
1656 InstanceType last_;
1657};
1658
1659
1660class HCheckNonSmi: public HUnaryOperation {
1661 public:
1662 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
1663 set_representation(Representation::Tagged());
1664 SetFlag(kUseGVN);
1665 }
1666
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001667 virtual bool IsCheckInstruction() const { return true; }
1668
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001669 virtual Representation RequiredInputRepresentation(int index) const {
1670 return Representation::Tagged();
1671 }
1672
1673 virtual HType CalculateInferredType() const;
1674
1675#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001676 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001677#endif
1678
1679 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001680
1681 protected:
1682 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001683};
1684
1685
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001686class HCheckPrototypeMaps: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001687 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001688 HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
1689 : prototype_(prototype), holder_(holder) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001690 SetFlag(kUseGVN);
1691 SetFlag(kDependsOnMaps);
1692 }
1693
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001694 virtual bool IsCheckInstruction() const { return true; }
1695
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001696#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001697 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001698#endif
1699
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001700 Handle<JSObject> prototype() const { return prototype_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001701 Handle<JSObject> holder() const { return holder_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001702
1703 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
1704
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001705 virtual intptr_t Hashcode() const {
1706 ASSERT(!Heap::IsAllocationAllowed());
1707 intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
1708 hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
1709 return hash;
1710 }
1711
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001712 protected:
1713 virtual bool DataEquals(HValue* other) const {
1714 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001715 return prototype_.is_identical_to(b->prototype()) &&
1716 holder_.is_identical_to(b->holder());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001717 }
1718
1719 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001720 Handle<JSObject> prototype_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001721 Handle<JSObject> holder_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001722};
1723
1724
1725class HCheckSmi: public HUnaryOperation {
1726 public:
1727 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
1728 set_representation(Representation::Tagged());
1729 SetFlag(kUseGVN);
1730 }
1731
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001732 virtual bool IsCheckInstruction() const { return true; }
1733
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001734 virtual Representation RequiredInputRepresentation(int index) const {
1735 return Representation::Tagged();
1736 }
1737 virtual HType CalculateInferredType() const;
1738
1739#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001740 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001741#endif
1742
1743 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001744
1745 protected:
1746 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001747};
1748
1749
1750class HPhi: public HValue {
1751 public:
1752 explicit HPhi(int merged_index)
1753 : inputs_(2),
1754 merged_index_(merged_index),
1755 phi_id_(-1) {
1756 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1757 non_phi_uses_[i] = 0;
1758 indirect_uses_[i] = 0;
1759 }
1760 ASSERT(merged_index >= 0);
1761 set_representation(Representation::Tagged());
1762 SetFlag(kFlexibleRepresentation);
1763 }
1764
1765 virtual Representation InferredRepresentation() const {
1766 bool double_occurred = false;
1767 bool int32_occurred = false;
1768 for (int i = 0; i < OperandCount(); ++i) {
1769 HValue* value = OperandAt(i);
1770 if (value->representation().IsDouble()) double_occurred = true;
1771 if (value->representation().IsInteger32()) int32_occurred = true;
1772 if (value->representation().IsTagged()) return Representation::Tagged();
1773 }
1774
1775 if (double_occurred) return Representation::Double();
1776 if (int32_occurred) return Representation::Integer32();
1777 return Representation::None();
1778 }
1779
1780 virtual Range* InferRange();
1781 virtual Representation RequiredInputRepresentation(int index) const {
1782 return representation();
1783 }
1784 virtual HType CalculateInferredType() const;
1785 virtual int OperandCount() const { return inputs_.length(); }
1786 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
1787 HValue* GetRedundantReplacement() const;
1788 void AddInput(HValue* value);
1789
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001790 bool IsReceiver() { return merged_index_ == 0; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001791
1792 int merged_index() const { return merged_index_; }
1793
1794 virtual const char* Mnemonic() const { return "phi"; }
1795
1796 virtual void PrintTo(StringStream* stream) const;
1797
1798#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001799 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001800#endif
1801
1802 DECLARE_INSTRUCTION(Phi)
1803
1804 void InitRealUses(int id);
1805 void AddNonPhiUsesFrom(HPhi* other);
1806 void AddIndirectUsesTo(int* use_count);
1807
1808 int tagged_non_phi_uses() const {
1809 return non_phi_uses_[Representation::kTagged];
1810 }
1811 int int32_non_phi_uses() const {
1812 return non_phi_uses_[Representation::kInteger32];
1813 }
1814 int double_non_phi_uses() const {
1815 return non_phi_uses_[Representation::kDouble];
1816 }
1817 int tagged_indirect_uses() const {
1818 return indirect_uses_[Representation::kTagged];
1819 }
1820 int int32_indirect_uses() const {
1821 return indirect_uses_[Representation::kInteger32];
1822 }
1823 int double_indirect_uses() const {
1824 return indirect_uses_[Representation::kDouble];
1825 }
1826 int phi_id() { return phi_id_; }
1827
1828 protected:
1829 virtual void DeleteFromGraph();
1830 virtual void InternalSetOperandAt(int index, HValue* value) {
1831 inputs_[index] = value;
1832 }
1833
1834 private:
1835 ZoneList<HValue*> inputs_;
1836 int merged_index_;
1837
1838 int non_phi_uses_[Representation::kNumRepresentations];
1839 int indirect_uses_[Representation::kNumRepresentations];
1840 int phi_id_;
1841};
1842
1843
1844class HArgumentsObject: public HInstruction {
1845 public:
1846 HArgumentsObject() {
1847 set_representation(Representation::Tagged());
1848 SetFlag(kIsArguments);
1849 }
1850
1851 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
1852};
1853
1854
1855class HConstant: public HInstruction {
1856 public:
1857 HConstant(Handle<Object> handle, Representation r);
1858
1859 Handle<Object> handle() const { return handle_; }
1860
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001861 bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
1862
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001863 virtual bool EmitAtUses() const { return !representation().IsDouble(); }
1864 virtual void PrintDataTo(StringStream* stream) const;
1865 virtual HType CalculateInferredType() const;
1866 bool IsInteger() const { return handle_->IsSmi(); }
1867 HConstant* CopyToRepresentation(Representation r) const;
1868 HConstant* CopyToTruncatedInt32() const;
1869 bool HasInteger32Value() const { return has_int32_value_; }
1870 int32_t Integer32Value() const {
1871 ASSERT(HasInteger32Value());
1872 return int32_value_;
1873 }
1874 bool HasDoubleValue() const { return has_double_value_; }
1875 double DoubleValue() const {
1876 ASSERT(HasDoubleValue());
1877 return double_value_;
1878 }
1879 bool HasStringValue() const { return handle_->IsString(); }
1880
1881 virtual intptr_t Hashcode() const {
1882 ASSERT(!Heap::allow_allocation(false));
1883 return reinterpret_cast<intptr_t>(*handle());
1884 }
1885
1886#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001887 virtual void Verify() { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001888#endif
1889
1890 DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
1891
1892 protected:
1893 virtual Range* InferRange();
1894
1895 virtual bool DataEquals(HValue* other) const {
1896 HConstant* other_constant = HConstant::cast(other);
1897 return handle().is_identical_to(other_constant->handle());
1898 }
1899
1900 private:
1901 Handle<Object> handle_;
1902 HType constant_type_;
1903
1904 // The following two values represent the int32 and the double value of the
1905 // given constant if there is a lossless conversion between the constant
1906 // and the specific representation.
1907 bool has_int32_value_;
1908 int32_t int32_value_;
1909 bool has_double_value_;
1910 double double_value_;
1911};
1912
1913
1914class HBinaryOperation: public HInstruction {
1915 public:
1916 HBinaryOperation(HValue* left, HValue* right) {
1917 ASSERT(left != NULL && right != NULL);
1918 SetOperandAt(0, left);
1919 SetOperandAt(1, right);
1920 }
1921
1922 HValue* left() const { return OperandAt(0); }
1923 HValue* right() const { return OperandAt(1); }
1924
1925 // TODO(kasperl): Move these helpers to the IA-32 Lithium
1926 // instruction sequence builder.
1927 HValue* LeastConstantOperand() const {
1928 if (IsCommutative() && left()->IsConstant()) return right();
1929 return left();
1930 }
1931 HValue* MostConstantOperand() const {
1932 if (IsCommutative() && left()->IsConstant()) return left();
1933 return right();
1934 }
1935
1936 virtual bool IsCommutative() const { return false; }
1937
1938 virtual void PrintDataTo(StringStream* stream) const;
1939 virtual int OperandCount() const { return operands_.length(); }
1940 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1941
1942 DECLARE_INSTRUCTION(BinaryOperation)
1943
1944 protected:
1945 virtual void InternalSetOperandAt(int index, HValue* value) {
1946 operands_[index] = value;
1947 }
1948
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001949 HOperandVector<2> operands_;
1950};
1951
1952
1953class HApplyArguments: public HInstruction {
1954 public:
1955 HApplyArguments(HValue* function,
1956 HValue* receiver,
1957 HValue* length,
1958 HValue* elements) {
1959 set_representation(Representation::Tagged());
1960 SetOperandAt(0, function);
1961 SetOperandAt(1, receiver);
1962 SetOperandAt(2, length);
1963 SetOperandAt(3, elements);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001964 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001965 }
1966
1967 virtual Representation RequiredInputRepresentation(int index) const {
1968 // The length is untagged, all other inputs are tagged.
1969 return (index == 2)
1970 ? Representation::Integer32()
1971 : Representation::Tagged();
1972 }
1973
1974 HValue* function() const { return OperandAt(0); }
1975 HValue* receiver() const { return OperandAt(1); }
1976 HValue* length() const { return OperandAt(2); }
1977 HValue* elements() const { return OperandAt(3); }
1978
1979 virtual int OperandCount() const { return operands_.length(); }
1980 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1981
1982 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
1983
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001984 protected:
1985 virtual void InternalSetOperandAt(int index, HValue* value) {
1986 operands_[index] = value;
1987 }
1988
1989 private:
1990 HOperandVector<4> operands_;
1991};
1992
1993
1994class HArgumentsElements: public HInstruction {
1995 public:
1996 HArgumentsElements() {
1997 // The value produced by this instruction is a pointer into the stack
1998 // that looks as if it was a smi because of alignment.
1999 set_representation(Representation::Tagged());
2000 SetFlag(kUseGVN);
2001 }
2002
2003 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002004
2005 protected:
2006 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002007};
2008
2009
2010class HArgumentsLength: public HUnaryOperation {
2011 public:
2012 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
2013 set_representation(Representation::Integer32());
2014 SetFlag(kUseGVN);
2015 }
2016
2017 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002018
2019 protected:
2020 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002021};
2022
2023
2024class HAccessArgumentsAt: public HInstruction {
2025 public:
2026 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
2027 set_representation(Representation::Tagged());
2028 SetFlag(kUseGVN);
2029 SetOperandAt(0, arguments);
2030 SetOperandAt(1, length);
2031 SetOperandAt(2, index);
2032 }
2033
2034 virtual void PrintDataTo(StringStream* stream) const;
2035
2036 virtual Representation RequiredInputRepresentation(int index) const {
2037 // The arguments elements is considered tagged.
2038 return index == 0
2039 ? Representation::Tagged()
2040 : Representation::Integer32();
2041 }
2042
2043 HValue* arguments() const { return operands_[0]; }
2044 HValue* length() const { return operands_[1]; }
2045 HValue* index() const { return operands_[2]; }
2046
2047 virtual int OperandCount() const { return operands_.length(); }
2048 virtual HValue* OperandAt(int index) const { return operands_[index]; }
2049
2050 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
2051
2052 protected:
2053 virtual void InternalSetOperandAt(int index, HValue* value) {
2054 operands_[index] = value;
2055 }
2056
ager@chromium.org378b34e2011-01-28 08:04:38 +00002057 virtual bool DataEquals(HValue* other) const { return true; }
2058
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002059 private:
2060 HOperandVector<3> operands_;
2061};
2062
2063
2064class HBoundsCheck: public HBinaryOperation {
2065 public:
2066 HBoundsCheck(HValue* index, HValue* length)
2067 : HBinaryOperation(index, length) {
2068 SetFlag(kUseGVN);
2069 }
2070
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002071 virtual bool IsCheckInstruction() const { return true; }
2072
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002073 virtual Representation RequiredInputRepresentation(int index) const {
2074 return Representation::Integer32();
2075 }
2076
2077#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00002078 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002079#endif
2080
2081 HValue* index() const { return left(); }
2082 HValue* length() const { return right(); }
2083
2084 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002085
2086 protected:
2087 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002088};
2089
2090
2091class HBitwiseBinaryOperation: public HBinaryOperation {
2092 public:
2093 HBitwiseBinaryOperation(HValue* left, HValue* right)
2094 : HBinaryOperation(left, right) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002095 set_representation(Representation::Tagged());
2096 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002097 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002098 }
2099
2100 virtual Representation RequiredInputRepresentation(int index) const {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002101 return representation();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002102 }
2103
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002104 virtual void RepresentationChanged(Representation to) {
2105 if (!to.IsTagged()) {
2106 ASSERT(to.IsInteger32());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002107 ClearAllSideEffects();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002108 SetFlag(kTruncatingToInt32);
2109 SetFlag(kUseGVN);
2110 }
2111 }
2112
2113 HType CalculateInferredType() const;
2114
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002115 DECLARE_INSTRUCTION(BitwiseBinaryOperation)
2116};
2117
2118
2119class HArithmeticBinaryOperation: public HBinaryOperation {
2120 public:
2121 HArithmeticBinaryOperation(HValue* left, HValue* right)
2122 : HBinaryOperation(left, right) {
2123 set_representation(Representation::Tagged());
2124 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002125 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002126 }
2127
2128 virtual void RepresentationChanged(Representation to) {
2129 if (!to.IsTagged()) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002130 ClearAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002131 SetFlag(kUseGVN);
2132 }
2133 }
2134
2135 virtual HType CalculateInferredType() const;
2136 virtual Representation RequiredInputRepresentation(int index) const {
2137 return representation();
2138 }
2139 virtual Representation InferredRepresentation() const {
2140 if (left()->representation().Equals(right()->representation())) {
2141 return left()->representation();
2142 }
2143 return HValue::InferredRepresentation();
2144 }
2145
2146 DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
2147};
2148
2149
2150class HCompare: public HBinaryOperation {
2151 public:
2152 HCompare(HValue* left, HValue* right, Token::Value token)
2153 : HBinaryOperation(left, right), token_(token) {
2154 ASSERT(Token::IsCompareOp(token));
2155 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002156 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002157 }
2158
2159 void SetInputRepresentation(Representation r);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002160
2161 virtual bool EmitAtUses() const {
2162 return !HasSideEffects() && (uses()->length() <= 1);
2163 }
2164
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002165 virtual Representation RequiredInputRepresentation(int index) const {
2166 return input_representation_;
2167 }
2168 Representation GetInputRepresentation() const {
2169 return input_representation_;
2170 }
2171 Token::Value token() const { return token_; }
2172 virtual void PrintDataTo(StringStream* stream) const;
2173
2174 virtual HType CalculateInferredType() const;
2175
2176 virtual intptr_t Hashcode() const {
2177 return HValue::Hashcode() * 7 + token_;
2178 }
2179
2180 DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
2181
2182 protected:
2183 virtual bool DataEquals(HValue* other) const {
2184 HCompare* comp = HCompare::cast(other);
2185 return token_ == comp->token();
2186 }
2187
2188 private:
2189 Representation input_representation_;
2190 Token::Value token_;
2191};
2192
2193
2194class HCompareJSObjectEq: public HBinaryOperation {
2195 public:
2196 HCompareJSObjectEq(HValue* left, HValue* right)
2197 : HBinaryOperation(left, right) {
2198 set_representation(Representation::Tagged());
2199 SetFlag(kUseGVN);
2200 }
2201
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002202 virtual bool EmitAtUses() const {
2203 return !HasSideEffects() && (uses()->length() <= 1);
2204 }
2205
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002206 virtual Representation RequiredInputRepresentation(int index) const {
2207 return Representation::Tagged();
2208 }
2209 virtual HType CalculateInferredType() const;
2210
2211 DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002212
2213 protected:
2214 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002215};
2216
2217
2218class HUnaryPredicate: public HUnaryOperation {
2219 public:
2220 explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
2221 set_representation(Representation::Tagged());
2222 SetFlag(kUseGVN);
2223 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002224
2225 virtual bool EmitAtUses() const {
2226 return !HasSideEffects() && (uses()->length() <= 1);
2227 }
2228
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002229 virtual Representation RequiredInputRepresentation(int index) const {
2230 return Representation::Tagged();
2231 }
2232 virtual HType CalculateInferredType() const;
2233};
2234
2235
2236class HIsNull: public HUnaryPredicate {
2237 public:
2238 HIsNull(HValue* value, bool is_strict)
2239 : HUnaryPredicate(value), is_strict_(is_strict) { }
2240
2241 bool is_strict() const { return is_strict_; }
2242
2243 DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
2244
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002245 protected:
2246 virtual bool DataEquals(HValue* other) const {
2247 HIsNull* b = HIsNull::cast(other);
2248 return is_strict_ == b->is_strict();
2249 }
2250
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002251 private:
2252 bool is_strict_;
2253};
2254
2255
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002256class HIsObject: public HUnaryPredicate {
2257 public:
2258 explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }
2259
2260 DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002261
2262 protected:
2263 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002264};
2265
2266
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002267class HIsSmi: public HUnaryPredicate {
2268 public:
2269 explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
2270
2271 DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002272
2273 protected:
2274 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002275};
2276
2277
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002278class HIsConstructCall: public HInstruction {
2279 public:
2280 HIsConstructCall() {
2281 set_representation(Representation::Tagged());
2282 SetFlag(kUseGVN);
2283 }
2284
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002285 virtual bool EmitAtUses() const {
2286 return !HasSideEffects() && (uses()->length() <= 1);
2287 }
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002288
2289 DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is_construct_call")
2290
2291 protected:
2292 virtual bool DataEquals(HValue* other) const { return true; }
2293};
2294
2295
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002296class HHasInstanceType: public HUnaryPredicate {
2297 public:
2298 HHasInstanceType(HValue* value, InstanceType type)
2299 : HUnaryPredicate(value), from_(type), to_(type) { }
2300 HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
2301 : HUnaryPredicate(value), from_(from), to_(to) {
2302 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
2303 }
2304
2305 InstanceType from() { return from_; }
2306 InstanceType to() { return to_; }
2307
2308 virtual void PrintDataTo(StringStream* stream) const;
2309
2310 DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
2311
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002312 protected:
2313 virtual bool DataEquals(HValue* other) const {
2314 HHasInstanceType* b = HHasInstanceType::cast(other);
2315 return (from_ == b->from()) && (to_ == b->to());
2316 }
2317
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002318 private:
2319 InstanceType from_;
2320 InstanceType to_; // Inclusive range, not all combinations work.
2321};
2322
2323
2324class HHasCachedArrayIndex: public HUnaryPredicate {
2325 public:
2326 explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
2327
2328 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002329
2330 protected:
2331 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002332};
2333
2334
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00002335class HGetCachedArrayIndex: public HUnaryPredicate {
2336 public:
2337 explicit HGetCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
2338
2339 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get_cached_array_index")
2340
2341 protected:
2342 virtual bool DataEquals(HValue* other) const { return true; }
2343};
2344
2345
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002346class HClassOfTest: public HUnaryPredicate {
2347 public:
2348 HClassOfTest(HValue* value, Handle<String> class_name)
2349 : HUnaryPredicate(value), class_name_(class_name) { }
2350
2351 DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
2352
2353 virtual void PrintDataTo(StringStream* stream) const;
2354
2355 Handle<String> class_name() const { return class_name_; }
2356
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002357 protected:
2358 virtual bool DataEquals(HValue* other) const {
2359 HClassOfTest* b = HClassOfTest::cast(other);
2360 return class_name_.is_identical_to(b->class_name_);
2361 }
2362
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002363 private:
2364 Handle<String> class_name_;
2365};
2366
2367
2368class HTypeofIs: public HUnaryPredicate {
2369 public:
2370 HTypeofIs(HValue* value, Handle<String> type_literal)
2371 : HUnaryPredicate(value), type_literal_(type_literal) { }
2372
2373 Handle<String> type_literal() { return type_literal_; }
2374 virtual void PrintDataTo(StringStream* stream) const;
2375
2376 DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
2377
2378 protected:
2379 virtual bool DataEquals(HValue* other) const {
2380 HTypeofIs* b = HTypeofIs::cast(other);
2381 return type_literal_.is_identical_to(b->type_literal_);
2382 }
2383
2384 private:
2385 Handle<String> type_literal_;
2386};
2387
2388
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002389class HInstanceOf: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002390 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002391 HInstanceOf(HValue* context, HValue* left, HValue* right) {
2392 SetOperandAt(0, context);
2393 SetOperandAt(1, left);
2394 SetOperandAt(2, right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002395 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002396 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002397 }
2398
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002399 HValue* context() const { return operands_[0]; }
2400 HValue* left() const { return operands_[1]; }
2401 HValue* right() const { return operands_[2]; }
2402
2403 virtual bool EmitAtUses() const {
2404 return !HasSideEffects() && (uses()->length() <= 1);
2405 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002406
2407 virtual Representation RequiredInputRepresentation(int index) const {
2408 return Representation::Tagged();
2409 }
2410
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002411 virtual void PrintDataTo(StringStream* stream) const;
2412
2413 virtual int OperandCount() const { return 3; }
2414 virtual HValue* OperandAt(int index) const { return operands_[index]; }
2415
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002416 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002417
2418 protected:
2419 virtual void InternalSetOperandAt(int index, HValue* value) {
2420 operands_[index] = value;
2421 }
2422
2423 private:
2424 HOperandVector<3> operands_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002425};
2426
2427
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002428class HInstanceOfKnownGlobal: public HUnaryOperation {
2429 public:
2430 HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right)
2431 : HUnaryOperation(left), function_(right) {
2432 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002433 SetAllSideEffects();
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002434 }
2435
2436 Handle<JSFunction> function() { return function_; }
2437
2438 virtual Representation RequiredInputRepresentation(int index) const {
2439 return Representation::Tagged();
2440 }
2441
2442 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
2443 "instance_of_known_global")
2444
2445 private:
2446 Handle<JSFunction> function_;
2447};
2448
2449
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002450class HPower: public HBinaryOperation {
2451 public:
2452 HPower(HValue* left, HValue* right)
2453 : HBinaryOperation(left, right) {
2454 set_representation(Representation::Double());
2455 SetFlag(kUseGVN);
2456 }
2457
2458 virtual Representation RequiredInputRepresentation(int index) const {
2459 return (index == 1) ? Representation::None() : Representation::Double();
2460 }
2461
2462 DECLARE_CONCRETE_INSTRUCTION(Power, "power")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002463
2464 protected:
2465 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002466};
2467
2468
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002469class HAdd: public HArithmeticBinaryOperation {
2470 public:
2471 HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2472 SetFlag(kCanOverflow);
2473 }
2474
2475 // Add is only commutative if two integer values are added and not if two
2476 // tagged values are added (because it might be a String concatenation).
2477 virtual bool IsCommutative() const {
2478 return !representation().IsTagged();
2479 }
2480
2481 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2482
2483 virtual HType CalculateInferredType() const;
2484
2485 DECLARE_CONCRETE_INSTRUCTION(Add, "add")
2486
2487 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002488 virtual bool DataEquals(HValue* other) const { return true; }
2489
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002490 virtual Range* InferRange();
2491};
2492
2493
2494class HSub: public HArithmeticBinaryOperation {
2495 public:
2496 HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2497 SetFlag(kCanOverflow);
2498 }
2499
2500 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2501
2502 DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
2503
2504 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002505 virtual bool DataEquals(HValue* other) const { return true; }
2506
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002507 virtual Range* InferRange();
2508};
2509
2510
2511class HMul: public HArithmeticBinaryOperation {
2512 public:
2513 HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2514 SetFlag(kCanOverflow);
2515 }
2516
2517 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2518
2519 // Only commutative if it is certain that not two objects are multiplicated.
2520 virtual bool IsCommutative() const {
2521 return !representation().IsTagged();
2522 }
2523
2524 DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
2525
2526 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002527 virtual bool DataEquals(HValue* other) const { return true; }
2528
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002529 virtual Range* InferRange();
2530};
2531
2532
2533class HMod: public HArithmeticBinaryOperation {
2534 public:
2535 HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2536 SetFlag(kCanBeDivByZero);
2537 }
2538
2539 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2540
2541 DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
2542
2543 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002544 virtual bool DataEquals(HValue* other) const { return true; }
2545
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002546 virtual Range* InferRange();
2547};
2548
2549
2550class HDiv: public HArithmeticBinaryOperation {
2551 public:
2552 HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2553 SetFlag(kCanBeDivByZero);
2554 SetFlag(kCanOverflow);
2555 }
2556
2557 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2558
2559 DECLARE_CONCRETE_INSTRUCTION(Div, "div")
2560
2561 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002562 virtual bool DataEquals(HValue* other) const { return true; }
2563
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002564 virtual Range* InferRange();
2565};
2566
2567
2568class HBitAnd: public HBitwiseBinaryOperation {
2569 public:
2570 HBitAnd(HValue* left, HValue* right)
2571 : HBitwiseBinaryOperation(left, right) { }
2572
2573 virtual bool IsCommutative() const { return true; }
2574 virtual HType CalculateInferredType() const;
2575
2576 DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
2577
2578 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002579 virtual bool DataEquals(HValue* other) const { return true; }
2580
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002581 virtual Range* InferRange();
2582};
2583
2584
2585class HBitXor: public HBitwiseBinaryOperation {
2586 public:
2587 HBitXor(HValue* left, HValue* right)
2588 : HBitwiseBinaryOperation(left, right) { }
2589
2590 virtual bool IsCommutative() const { return true; }
2591 virtual HType CalculateInferredType() const;
2592
2593 DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002594
2595 protected:
2596 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002597};
2598
2599
2600class HBitOr: public HBitwiseBinaryOperation {
2601 public:
2602 HBitOr(HValue* left, HValue* right)
2603 : HBitwiseBinaryOperation(left, right) { }
2604
2605 virtual bool IsCommutative() const { return true; }
2606 virtual HType CalculateInferredType() const;
2607
2608 DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
2609
2610 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002611 virtual bool DataEquals(HValue* other) const { return true; }
2612
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002613 virtual Range* InferRange();
2614};
2615
2616
2617class HShl: public HBitwiseBinaryOperation {
2618 public:
2619 HShl(HValue* left, HValue* right)
2620 : HBitwiseBinaryOperation(left, right) { }
2621
2622 virtual Range* InferRange();
2623 virtual HType CalculateInferredType() const;
2624
2625 DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002626
2627 protected:
2628 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002629};
2630
2631
2632class HShr: public HBitwiseBinaryOperation {
2633 public:
2634 HShr(HValue* left, HValue* right)
2635 : HBitwiseBinaryOperation(left, right) { }
2636
2637 virtual HType CalculateInferredType() const;
2638
2639 DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002640
2641 protected:
2642 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002643};
2644
2645
2646class HSar: public HBitwiseBinaryOperation {
2647 public:
2648 HSar(HValue* left, HValue* right)
2649 : HBitwiseBinaryOperation(left, right) { }
2650
2651 virtual Range* InferRange();
2652 virtual HType CalculateInferredType() const;
2653
2654 DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002655
2656 protected:
2657 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002658};
2659
2660
2661class HOsrEntry: public HInstruction {
2662 public:
2663 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
2664 SetFlag(kChangesOsrEntries);
2665 }
2666
2667 int ast_id() const { return ast_id_; }
2668
2669 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
2670
2671 private:
2672 int ast_id_;
2673};
2674
2675
2676class HParameter: public HInstruction {
2677 public:
2678 explicit HParameter(unsigned index) : index_(index) {
2679 set_representation(Representation::Tagged());
2680 }
2681
2682 unsigned index() const { return index_; }
2683
2684 virtual void PrintDataTo(StringStream* stream) const;
2685
2686 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2687
2688 private:
2689 unsigned index_;
2690};
2691
2692
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002693class HCallStub: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002694 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002695 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
2696 : HUnaryCall(context, argument_count),
2697 major_key_(major_key),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002698 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002699 }
2700
2701 CodeStub::Major major_key() { return major_key_; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002702
2703 HValue* context() const { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002704
2705 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
2706 transcendental_type_ = transcendental_type;
2707 }
2708 TranscendentalCache::Type transcendental_type() {
2709 return transcendental_type_;
2710 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002711
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002712 virtual void PrintDataTo(StringStream* stream) const;
2713
2714 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
2715
2716 private:
2717 CodeStub::Major major_key_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002718 TranscendentalCache::Type transcendental_type_;
2719};
2720
2721
2722class HUnknownOSRValue: public HInstruction {
2723 public:
2724 HUnknownOSRValue() { set_representation(Representation::Tagged()); }
2725
2726 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
2727};
2728
2729
2730class HLoadGlobal: public HInstruction {
2731 public:
2732 HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
2733 : cell_(cell), check_hole_value_(check_hole_value) {
2734 set_representation(Representation::Tagged());
2735 SetFlag(kUseGVN);
2736 SetFlag(kDependsOnGlobalVars);
2737 }
2738
2739 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2740 bool check_hole_value() const { return check_hole_value_; }
2741
2742 virtual Representation RequiredInputRepresentation(int index) const {
2743 return Representation::Tagged();
2744 }
2745 virtual void PrintDataTo(StringStream* stream) const;
2746
2747 virtual intptr_t Hashcode() const {
2748 ASSERT(!Heap::allow_allocation(false));
2749 return reinterpret_cast<intptr_t>(*cell_);
2750 }
2751
2752 DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
2753
2754 protected:
2755 virtual bool DataEquals(HValue* other) const {
2756 HLoadGlobal* b = HLoadGlobal::cast(other);
2757 return cell_.is_identical_to(b->cell());
2758 }
2759
2760 private:
2761 Handle<JSGlobalPropertyCell> cell_;
2762 bool check_hole_value_;
2763};
2764
2765
2766class HStoreGlobal: public HUnaryOperation {
2767 public:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002768 HStoreGlobal(HValue* value,
2769 Handle<JSGlobalPropertyCell> cell,
2770 bool check_hole_value)
2771 : HUnaryOperation(value),
2772 cell_(cell),
2773 check_hole_value_(check_hole_value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002774 SetFlag(kChangesGlobalVars);
2775 }
2776
2777 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002778 bool check_hole_value() const { return check_hole_value_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002779
2780 virtual Representation RequiredInputRepresentation(int index) const {
2781 return Representation::Tagged();
2782 }
2783 virtual void PrintDataTo(StringStream* stream) const;
2784
2785 DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
2786
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002787 private:
2788 Handle<JSGlobalPropertyCell> cell_;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002789 bool check_hole_value_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002790};
2791
2792
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002793class HLoadContextSlot: public HUnaryOperation {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002794 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002795 HLoadContextSlot(HValue* context , int slot_index)
2796 : HUnaryOperation(context), slot_index_(slot_index) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002797 set_representation(Representation::Tagged());
2798 SetFlag(kUseGVN);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002799 SetFlag(kDependsOnContextSlots);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002800 }
2801
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002802 int slot_index() const { return slot_index_; }
2803
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002804 virtual Representation RequiredInputRepresentation(int index) const {
2805 return Representation::Tagged();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002806 }
2807
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002808 virtual void PrintDataTo(StringStream* stream) const;
2809
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002810 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
2811
2812 protected:
2813 virtual bool DataEquals(HValue* other) const {
2814 HLoadContextSlot* b = HLoadContextSlot::cast(other);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002815 return (slot_index() == b->slot_index());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002816 }
2817
2818 private:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002819 int slot_index_;
2820};
2821
2822
2823static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
2824 return !value->type().IsSmi() &&
2825 !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
2826}
2827
2828
2829class HStoreContextSlot: public HBinaryOperation {
2830 public:
2831 HStoreContextSlot(HValue* context, int slot_index, HValue* value)
2832 : HBinaryOperation(context, value), slot_index_(slot_index) {
2833 SetFlag(kChangesContextSlots);
2834 }
2835
2836 HValue* context() const { return OperandAt(0); }
2837 HValue* value() const { return OperandAt(1); }
2838 int slot_index() const { return slot_index_; }
2839
2840 bool NeedsWriteBarrier() const {
2841 return StoringValueNeedsWriteBarrier(value());
2842 }
2843
2844 virtual Representation RequiredInputRepresentation(int index) const {
2845 return Representation::Tagged();
2846 }
2847
2848 virtual void PrintDataTo(StringStream* stream) const;
2849
2850 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store_context_slot")
2851
2852 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002853 int slot_index_;
2854};
2855
2856
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002857class HLoadNamedField: public HUnaryOperation {
2858 public:
2859 HLoadNamedField(HValue* object, bool is_in_object, int offset)
2860 : HUnaryOperation(object),
2861 is_in_object_(is_in_object),
2862 offset_(offset) {
2863 set_representation(Representation::Tagged());
2864 SetFlag(kUseGVN);
2865 if (is_in_object) {
2866 SetFlag(kDependsOnInobjectFields);
2867 } else {
2868 SetFlag(kDependsOnBackingStoreFields);
2869 }
2870 }
2871
2872 HValue* object() const { return OperandAt(0); }
2873 bool is_in_object() const { return is_in_object_; }
2874 int offset() const { return offset_; }
2875
2876 virtual Representation RequiredInputRepresentation(int index) const {
2877 return Representation::Tagged();
2878 }
2879 virtual void PrintDataTo(StringStream* stream) const;
2880
2881 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
2882
2883 protected:
2884 virtual bool DataEquals(HValue* other) const {
2885 HLoadNamedField* b = HLoadNamedField::cast(other);
2886 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
2887 }
2888
2889 private:
2890 bool is_in_object_;
2891 int offset_;
2892};
2893
2894
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002895class HLoadNamedGeneric: public HBinaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002896 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002897 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
2898 : HBinaryOperation(context, object), name_(name) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002899 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002900 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002901 }
2902
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002903 HValue* context() const { return OperandAt(0); }
2904 HValue* object() const { return OperandAt(1); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002905 Handle<Object> name() const { return name_; }
2906
2907 virtual Representation RequiredInputRepresentation(int index) const {
2908 return Representation::Tagged();
2909 }
2910
2911 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
2912
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002913 private:
2914 Handle<Object> name_;
2915};
2916
2917
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002918class HLoadFunctionPrototype: public HUnaryOperation {
2919 public:
2920 explicit HLoadFunctionPrototype(HValue* function)
2921 : HUnaryOperation(function) {
2922 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002923 SetFlag(kUseGVN);
2924 SetFlag(kDependsOnCalls);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002925 }
2926
2927 HValue* function() const { return OperandAt(0); }
2928
2929 virtual Representation RequiredInputRepresentation(int index) const {
2930 return Representation::Tagged();
2931 }
2932
2933 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
2934
2935 protected:
2936 virtual bool DataEquals(HValue* other) const { return true; }
2937};
2938
2939
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002940class HLoadKeyed: public HBinaryOperation {
2941 public:
2942 HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
2943 set_representation(Representation::Tagged());
2944 }
2945
2946 virtual void PrintDataTo(StringStream* stream) const;
2947
2948 virtual Representation RequiredInputRepresentation(int index) const {
2949 return Representation::Tagged();
2950 }
2951 HValue* object() const { return OperandAt(0); }
2952 HValue* key() const { return OperandAt(1); }
2953
2954 DECLARE_INSTRUCTION(LoadKeyed)
2955};
2956
2957
2958class HLoadKeyedFastElement: public HLoadKeyed {
2959 public:
2960 HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2961 SetFlag(kDependsOnArrayElements);
2962 SetFlag(kUseGVN);
2963 }
2964
2965 virtual Representation RequiredInputRepresentation(int index) const {
2966 // The key is supposed to be Integer32.
2967 return (index == 1) ? Representation::Integer32()
2968 : Representation::Tagged();
2969 }
2970
2971 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
2972 "load_keyed_fast_element")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002973
2974 protected:
2975 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002976};
2977
2978
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002979class HLoadPixelArrayElement: public HBinaryOperation {
2980 public:
2981 HLoadPixelArrayElement(HValue* external_elements, HValue* key)
2982 : HBinaryOperation(external_elements, key) {
2983 set_representation(Representation::Integer32());
2984 SetFlag(kDependsOnPixelArrayElements);
2985 // Native code could change the pixel array.
2986 SetFlag(kDependsOnCalls);
2987 SetFlag(kUseGVN);
2988 }
2989
2990 virtual void PrintDataTo(StringStream* stream) const;
2991
2992 virtual Representation RequiredInputRepresentation(int index) const {
2993 // The key is supposed to be Integer32, but the base pointer
2994 // for the element load is a naked pointer.
2995 return (index == 1) ? Representation::Integer32()
2996 : Representation::External();
2997 }
2998
2999 HValue* external_pointer() const { return OperandAt(0); }
3000 HValue* key() const { return OperandAt(1); }
3001
3002 DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
3003 "load_pixel_array_element")
3004
3005 protected:
3006 virtual bool DataEquals(HValue* other) const { return true; }
3007};
3008
3009
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003010class HLoadKeyedGeneric: public HLoadKeyed {
3011 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003012 HLoadKeyedGeneric(HContext* context, HValue* obj, HValue* key)
3013 : HLoadKeyed(obj, key), context_(NULL) {
3014 SetOperandAt(2, context);
ager@chromium.org378b34e2011-01-28 08:04:38 +00003015 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003016 }
3017
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003018 HValue* context() const { return context_; }
3019 HValue* object() const { return operands_[0]; }
3020 HValue* key() const { return operands_[1]; }
3021
3022 virtual int OperandCount() const { return 3; }
3023 virtual HValue* OperandAt(int index) const {
3024 return (index < 2) ? operands_[index] : context_;
3025 }
3026
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003027 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003028
3029 protected:
3030 virtual void InternalSetOperandAt(int index, HValue* value);
3031
3032 private:
3033 HValue* context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003034};
3035
3036
3037class HStoreNamed: public HBinaryOperation {
3038 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003039 HStoreNamed(HValue* obj, Handle<String> name, HValue* val)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003040 : HBinaryOperation(obj, val), name_(name) {
3041 }
3042
3043 virtual Representation RequiredInputRepresentation(int index) const {
3044 return Representation::Tagged();
3045 }
3046
3047 virtual void PrintDataTo(StringStream* stream) const;
3048
3049 HValue* object() const { return OperandAt(0); }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003050 Handle<String> name() const { return name_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003051 HValue* value() const { return OperandAt(1); }
3052 void set_value(HValue* value) { SetOperandAt(1, value); }
3053
3054 DECLARE_INSTRUCTION(StoreNamed)
3055
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003056 private:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003057 Handle<String> name_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003058};
3059
3060
3061class HStoreNamedField: public HStoreNamed {
3062 public:
3063 HStoreNamedField(HValue* obj,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003064 Handle<String> name,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003065 HValue* val,
3066 bool in_object,
3067 int offset)
3068 : HStoreNamed(obj, name, val),
3069 is_in_object_(in_object),
3070 offset_(offset) {
3071 if (is_in_object_) {
3072 SetFlag(kChangesInobjectFields);
3073 } else {
3074 SetFlag(kChangesBackingStoreFields);
3075 }
3076 }
3077
3078 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
3079
3080 virtual Representation RequiredInputRepresentation(int index) const {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00003081 return Representation::Tagged();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003082 }
3083 virtual void PrintDataTo(StringStream* stream) const;
3084
3085 bool is_in_object() const { return is_in_object_; }
3086 int offset() const { return offset_; }
3087 Handle<Map> transition() const { return transition_; }
3088 void set_transition(Handle<Map> map) { transition_ = map; }
3089
ricow@chromium.org83aa5492011-02-07 12:42:56 +00003090 bool NeedsWriteBarrier() const {
3091 return StoringValueNeedsWriteBarrier(value());
3092 }
3093
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003094 private:
3095 bool is_in_object_;
3096 int offset_;
3097 Handle<Map> transition_;
3098};
3099
3100
3101class HStoreNamedGeneric: public HStoreNamed {
3102 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003103 HStoreNamedGeneric(HValue* context,
3104 HValue* object,
3105 Handle<String> name,
3106 HValue* value)
3107 : HStoreNamed(object, name, value), context_(NULL) {
3108 SetOperandAt(2, context);
ager@chromium.org378b34e2011-01-28 08:04:38 +00003109 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003110 }
3111
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003112 HValue* context() const { return context_; }
3113 HValue* object() const { return operands_[0]; }
3114 HValue* value() const { return operands_[1]; }
3115
3116 virtual int OperandCount() const { return 3; }
3117
3118 virtual HValue* OperandAt(int index) const {
3119 return (index < 2) ? operands_[index] : context_;
3120 }
3121
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003122 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003123
3124 protected:
3125 virtual void InternalSetOperandAt(int index, HValue* value);
3126
3127 private:
3128 HValue* context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003129};
3130
3131
3132class HStoreKeyed: public HInstruction {
3133 public:
3134 HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
3135 SetOperandAt(0, obj);
3136 SetOperandAt(1, key);
3137 SetOperandAt(2, val);
3138 }
3139
3140 virtual void PrintDataTo(StringStream* stream) const;
3141 virtual int OperandCount() const { return operands_.length(); }
3142 virtual HValue* OperandAt(int index) const { return operands_[index]; }
3143
3144 virtual Representation RequiredInputRepresentation(int index) const {
3145 return Representation::Tagged();
3146 }
3147
3148 HValue* object() const { return OperandAt(0); }
3149 HValue* key() const { return OperandAt(1); }
3150 HValue* value() const { return OperandAt(2); }
3151
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00003152 bool NeedsWriteBarrier() const {
3153 return StoringValueNeedsWriteBarrier(value());
3154 }
3155
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003156 DECLARE_INSTRUCTION(StoreKeyed)
3157
3158 protected:
3159 virtual void InternalSetOperandAt(int index, HValue* value) {
3160 operands_[index] = value;
3161 }
3162
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003163 HOperandVector<3> operands_;
3164};
3165
3166
3167class HStoreKeyedFastElement: public HStoreKeyed {
3168 public:
3169 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
3170 : HStoreKeyed(obj, key, val) {
3171 SetFlag(kChangesArrayElements);
3172 }
3173
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003174 virtual Representation RequiredInputRepresentation(int index) const {
3175 // The key is supposed to be Integer32.
3176 return (index == 1) ? Representation::Integer32()
3177 : Representation::Tagged();
3178 }
3179
3180 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
3181 "store_keyed_fast_element")
3182};
3183
3184
3185class HStoreKeyedGeneric: public HStoreKeyed {
3186 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003187 HStoreKeyedGeneric(HValue* context,
3188 HValue* object,
3189 HValue* key,
3190 HValue* value)
3191 : HStoreKeyed(object, key, value), context_(NULL) {
3192 SetOperandAt(3, context);
ager@chromium.org378b34e2011-01-28 08:04:38 +00003193 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003194 }
3195
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003196 HValue* context() const { return context_; }
3197 HValue* object() const { return operands_[0]; }
3198 HValue* key() const { return operands_[1]; }
3199 HValue* value() const { return operands_[2]; }
3200
3201 virtual int OperandCount() const { return 4; }
3202
3203 virtual HValue* OperandAt(int index) const {
3204 return (index < 3) ? operands_[index] : context_;
3205 }
3206
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003207 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003208
3209 protected:
3210 virtual void InternalSetOperandAt(int index, HValue* value);
3211
3212 private:
3213 HValue* context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003214};
3215
3216
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003217class HStringCharCodeAt: public HBinaryOperation {
3218 public:
3219 HStringCharCodeAt(HValue* string, HValue* index)
3220 : HBinaryOperation(string, index) {
3221 set_representation(Representation::Integer32());
3222 SetFlag(kUseGVN);
3223 }
3224
3225 virtual Representation RequiredInputRepresentation(int index) const {
3226 // The index is supposed to be Integer32.
3227 return (index == 1) ? Representation::Integer32()
3228 : Representation::Tagged();
3229 }
3230
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003231 HValue* string() const { return OperandAt(0); }
3232 HValue* index() const { return OperandAt(1); }
3233
3234 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string_char_code_at")
3235
3236 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00003237 virtual bool DataEquals(HValue* other) const { return true; }
3238
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003239 virtual Range* InferRange() {
3240 return new Range(0, String::kMaxUC16CharCode);
3241 }
3242};
3243
3244
3245class HStringLength: public HUnaryOperation {
3246 public:
3247 explicit HStringLength(HValue* string) : HUnaryOperation(string) {
3248 set_representation(Representation::Tagged());
3249 SetFlag(kUseGVN);
3250 }
3251
3252 virtual Representation RequiredInputRepresentation(int index) const {
3253 return Representation::Tagged();
3254 }
3255
3256 virtual HType CalculateInferredType() const {
3257 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
3258 return HType::Smi();
3259 }
3260
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003261 DECLARE_CONCRETE_INSTRUCTION(StringLength, "string_length")
3262
3263 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00003264 virtual bool DataEquals(HValue* other) const { return true; }
3265
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003266 virtual Range* InferRange() {
3267 return new Range(0, String::kMaxLength);
3268 }
3269};
3270
3271
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003272class HMaterializedLiteral: public HInstruction {
3273 public:
3274 HMaterializedLiteral(int index, int depth)
3275 : literal_index_(index), depth_(depth) {
3276 set_representation(Representation::Tagged());
3277 }
3278
3279 int literal_index() const { return literal_index_; }
3280 int depth() const { return depth_; }
3281
3282 DECLARE_INSTRUCTION(MaterializedLiteral)
3283
3284 private:
3285 int literal_index_;
3286 int depth_;
3287};
3288
3289
3290class HArrayLiteral: public HMaterializedLiteral {
3291 public:
3292 HArrayLiteral(Handle<FixedArray> constant_elements,
3293 int length,
3294 int literal_index,
3295 int depth)
3296 : HMaterializedLiteral(literal_index, depth),
3297 length_(length),
3298 constant_elements_(constant_elements) {}
3299
3300 Handle<FixedArray> constant_elements() const { return constant_elements_; }
3301 int length() const { return length_; }
3302
3303 bool IsCopyOnWrite() const;
3304
3305 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
3306
3307 private:
3308 int length_;
3309 Handle<FixedArray> constant_elements_;
3310};
3311
3312
3313class HObjectLiteral: public HMaterializedLiteral {
3314 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003315 HObjectLiteral(HValue* context,
3316 Handle<FixedArray> constant_properties,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003317 bool fast_elements,
3318 int literal_index,
3319 int depth)
3320 : HMaterializedLiteral(literal_index, depth),
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003321 context_(NULL),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003322 constant_properties_(constant_properties),
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003323 fast_elements_(fast_elements) {
3324 SetOperandAt(0, context);
3325 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003326
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003327 HValue* context() const { return context_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003328 Handle<FixedArray> constant_properties() const {
3329 return constant_properties_;
3330 }
3331 bool fast_elements() const { return fast_elements_; }
3332
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003333 virtual int OperandCount() const { return 1; }
3334 virtual HValue* OperandAt(int index) const { return context_; }
3335
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003336 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
3337
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003338 protected:
3339 virtual void InternalSetOperandAt(int index, HValue* value) {
3340 context_ = value;
3341 }
3342
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003343 private:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003344 HValue* context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003345 Handle<FixedArray> constant_properties_;
3346 bool fast_elements_;
3347};
3348
3349
3350class HRegExpLiteral: public HMaterializedLiteral {
3351 public:
3352 HRegExpLiteral(Handle<String> pattern,
3353 Handle<String> flags,
3354 int literal_index)
3355 : HMaterializedLiteral(literal_index, 0),
3356 pattern_(pattern),
3357 flags_(flags) { }
3358
3359 Handle<String> pattern() { return pattern_; }
3360 Handle<String> flags() { return flags_; }
3361
3362 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
3363
3364 private:
3365 Handle<String> pattern_;
3366 Handle<String> flags_;
3367};
3368
3369
3370class HFunctionLiteral: public HInstruction {
3371 public:
3372 HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
3373 : shared_info_(shared), pretenure_(pretenure) {
3374 set_representation(Representation::Tagged());
3375 }
3376
3377 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
3378
3379 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
3380 bool pretenure() const { return pretenure_; }
3381
3382 private:
3383 Handle<SharedFunctionInfo> shared_info_;
3384 bool pretenure_;
3385};
3386
3387
3388class HTypeof: public HUnaryOperation {
3389 public:
3390 explicit HTypeof(HValue* value) : HUnaryOperation(value) {
3391 set_representation(Representation::Tagged());
3392 }
3393
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003394 virtual Representation RequiredInputRepresentation(int index) const {
3395 return Representation::Tagged();
3396 }
3397
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003398 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
3399};
3400
3401
3402class HValueOf: public HUnaryOperation {
3403 public:
3404 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
3405 set_representation(Representation::Tagged());
3406 }
3407
3408 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
3409};
3410
3411
3412class HDeleteProperty: public HBinaryOperation {
3413 public:
3414 HDeleteProperty(HValue* obj, HValue* key)
3415 : HBinaryOperation(obj, key) {
3416 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00003417 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003418 }
3419
3420 virtual Representation RequiredInputRepresentation(int index) const {
3421 return Representation::Tagged();
3422 }
3423
3424 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
3425
3426 HValue* object() const { return left(); }
3427 HValue* key() const { return right(); }
3428};
3429
3430#undef DECLARE_INSTRUCTION
3431#undef DECLARE_CONCRETE_INSTRUCTION
3432
3433} } // namespace v8::internal
3434
3435#endif // V8_HYDROGEN_INSTRUCTIONS_H_