blob: cb2225dcf69b973a1ba07c3c71c879212bd23b20 [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 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"
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000032
lrn@chromium.org1c092762011-05-09 09:42:16 +000033#include "allocation.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000034#include "code-stubs.h"
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000035#include "data-flow.h"
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000036#include "small-pointer-list.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000037#include "string-stream.h"
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +000038#include "v8conversions.h"
39#include "v8utils.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000040#include "zone.h"
41
42namespace v8 {
43namespace internal {
44
45// Forward declarations.
46class HBasicBlock;
47class HEnvironment;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000048class HInferRepresentationPhase;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000049class HInstruction;
50class HLoopInformation;
51class HValue;
52class LInstruction;
53class LChunkBuilder;
54
55
ricow@chromium.orgdcebac02011-04-20 09:44:50 +000056#define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
ulan@chromium.org837a67e2013-06-11 15:39:48 +000057 V(ArithmeticBinaryOperation) \
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000058 V(BinaryOperation) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000059 V(BitwiseBinaryOperation) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000060 V(ControlInstruction) \
61 V(Instruction) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000062
63
64#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000065 V(AbnormalExit) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000066 V(AccessArgumentsAt) \
67 V(Add) \
danno@chromium.org94b0d6f2013-02-04 13:33:20 +000068 V(Allocate) \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000069 V(AllocateObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000070 V(ApplyArguments) \
71 V(ArgumentsElements) \
72 V(ArgumentsLength) \
73 V(ArgumentsObject) \
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000074 V(Bitwise) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000075 V(BitNot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000076 V(BlockEntry) \
77 V(BoundsCheck) \
svenpanne@chromium.org876cca82013-03-18 14:43:20 +000078 V(BoundsCheckBaseIndexInformation) \
ricow@chromium.org4f693d62011-07-04 14:01:31 +000079 V(Branch) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000080 V(CallConstantFunction) \
81 V(CallFunction) \
82 V(CallGlobal) \
83 V(CallKeyed) \
84 V(CallKnownGlobal) \
85 V(CallNamed) \
86 V(CallNew) \
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000087 V(CallNewArray) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000088 V(CallRuntime) \
89 V(CallStub) \
90 V(Change) \
91 V(CheckFunction) \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000092 V(CheckHeapObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000093 V(CheckInstanceType) \
jkummerow@chromium.org1456e702012-03-30 08:38:13 +000094 V(CheckMaps) \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000095 V(CheckSmi) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000096 V(CheckPrototypeMaps) \
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +000097 V(ClampToUint8) \
ricow@chromium.org4f693d62011-07-04 14:01:31 +000098 V(ClassOfTestAndBranch) \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000099 V(CompareNumericAndBranch) \
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000100 V(CompareGeneric) \
101 V(CompareObjectEqAndBranch) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000102 V(CompareMap) \
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000103 V(CompareConstantEqAndBranch) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000104 V(Constant) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000105 V(Context) \
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000106 V(DebugBreak) \
yangguo@chromium.org56454712012-02-16 15:33:53 +0000107 V(DeclareGlobals) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000108 V(Deoptimize) \
109 V(Div) \
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000110 V(DummyUse) \
whesse@chromium.org7b260152011-06-20 15:33:18 +0000111 V(ElementsKind) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000112 V(EnterInlined) \
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000113 V(EnvironmentMarker) \
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000114 V(ForceRepresentation) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000115 V(FunctionLiteral) \
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000116 V(GetCachedArrayIndex) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117 V(GlobalObject) \
118 V(GlobalReceiver) \
119 V(Goto) \
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000120 V(HasCachedArrayIndexAndBranch) \
121 V(HasInstanceTypeAndBranch) \
ulan@chromium.org2e04b582013-02-21 14:06:02 +0000122 V(InductionVariableAnnotation) \
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000123 V(InnerAllocatedObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000124 V(InstanceOf) \
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000125 V(InstanceOfKnownGlobal) \
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000126 V(InstanceSize) \
danno@chromium.org160a7b02011-04-18 15:51:38 +0000127 V(InvokeFunction) \
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000128 V(IsConstructCallAndBranch) \
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000129 V(IsObjectAndBranch) \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000130 V(IsNumberAndBranch) \
erikcorry0ad885c2011-11-21 13:51:57 +0000131 V(IsStringAndBranch) \
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000132 V(IsSmiAndBranch) \
133 V(IsUndetectableAndBranch) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000134 V(LeaveInlined) \
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000135 V(LoadContextSlot) \
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000136 V(LoadExternalArrayPointer) \
ager@chromium.org378b34e2011-01-28 08:04:38 +0000137 V(LoadFunctionPrototype) \
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000138 V(LoadGlobalCell) \
139 V(LoadGlobalGeneric) \
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000140 V(LoadKeyed) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000141 V(LoadKeyedGeneric) \
142 V(LoadNamedField) \
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000143 V(LoadNamedFieldPolymorphic) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000144 V(LoadNamedGeneric) \
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000145 V(MapEnumLength) \
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000146 V(MathFloorOfDiv) \
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000147 V(MathMinMax) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000148 V(Mod) \
149 V(Mul) \
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000150 V(NumericConstraint) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000151 V(OsrEntry) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000152 V(OuterContext) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000153 V(Parameter) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000154 V(Power) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000155 V(PushArgument) \
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000156 V(Random) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000157 V(RegExpLiteral) \
158 V(Return) \
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000159 V(Ror) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000160 V(Sar) \
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +0000161 V(SeqStringSetChar) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000162 V(Shl) \
163 V(Shr) \
164 V(Simulate) \
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000165 V(SoftDeoptimize) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000166 V(StackCheck) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000167 V(StoreContextSlot) \
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000168 V(StoreGlobalCell) \
169 V(StoreGlobalGeneric) \
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000170 V(StoreKeyed) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000171 V(StoreKeyedGeneric) \
172 V(StoreNamedField) \
173 V(StoreNamedGeneric) \
danno@chromium.org160a7b02011-04-18 15:51:38 +0000174 V(StringAdd) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000175 V(StringCharCodeAt) \
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000176 V(StringCharFromCode) \
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000177 V(StringCompareAndBranch) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000178 V(StringLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000179 V(Sub) \
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000180 V(ThisFunction) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000181 V(Throw) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000182 V(ToFastProperties) \
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000183 V(TransitionElementsKind) \
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000184 V(TrapAllocationMemento) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000185 V(Typeof) \
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000186 V(TypeofIsAndBranch) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000187 V(UnaryMathOperation) \
188 V(UnknownOSRValue) \
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000189 V(UseConst) \
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000190 V(ValueOf) \
191 V(ForInPrepareMap) \
192 V(ForInCacheArray) \
193 V(CheckMapValue) \
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +0000194 V(LoadFieldByIndex) \
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000195 V(DateField) \
196 V(WrapReceiver)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000197
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000198#define GVN_TRACKED_FLAG_LIST(V) \
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000199 V(Maps) \
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000200 V(NewSpacePromotion)
201
202#define GVN_UNTRACKED_FLAG_LIST(V) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000203 V(Calls) \
204 V(InobjectFields) \
205 V(BackingStoreFields) \
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000206 V(DoubleFields) \
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000207 V(ElementsKind) \
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000208 V(ElementsPointer) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000209 V(ArrayElements) \
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000210 V(DoubleArrayElements) \
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000211 V(SpecializedArrayElements) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000212 V(GlobalVars) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000213 V(ArrayLengths) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000214 V(ContextSlots) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000215 V(OsrEntries)
216
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000217#define DECLARE_ABSTRACT_INSTRUCTION(type) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000218 virtual bool Is##type() const { return true; } \
219 static H##type* cast(HValue* value) { \
220 ASSERT(value->Is##type()); \
221 return reinterpret_cast<H##type*>(value); \
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000222 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000223
224
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000225#define DECLARE_CONCRETE_INSTRUCTION(type) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000226 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000227 static H##type* cast(HValue* value) { \
228 ASSERT(value->Is##type()); \
229 return reinterpret_cast<H##type*>(value); \
230 } \
231 virtual Opcode opcode() const { return HValue::k##type; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000232
233
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000234class Range: public ZoneObject {
235 public:
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000236 Range()
237 : lower_(kMinInt),
238 upper_(kMaxInt),
239 next_(NULL),
240 can_be_minus_zero_(false) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000241
242 Range(int32_t lower, int32_t upper)
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000243 : lower_(lower),
244 upper_(upper),
245 next_(NULL),
246 can_be_minus_zero_(false) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000247
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000248 int32_t upper() const { return upper_; }
249 int32_t lower() const { return lower_; }
250 Range* next() const { return next_; }
ulan@chromium.org812308e2012-02-29 15:58:45 +0000251 Range* CopyClearLower(Zone* zone) const {
252 return new(zone) Range(kMinInt, upper_);
253 }
254 Range* CopyClearUpper(Zone* zone) const {
255 return new(zone) Range(lower_, kMaxInt);
256 }
257 Range* Copy(Zone* zone) const {
258 Range* result = new(zone) Range(lower_, upper_);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000259 result->set_can_be_minus_zero(CanBeMinusZero());
260 return result;
261 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000262 int32_t Mask() const;
263 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
264 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
265 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
266 bool CanBeNegative() const { return lower_ < 0; }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000267 bool CanBePositive() const { return upper_ > 0; }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000268 bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000269 bool IsMostGeneric() const {
270 return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
271 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000272 bool IsInSmiRange() const {
273 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000274 }
danno@chromium.org1fd77d52013-06-07 16:01:45 +0000275 void ClampToSmi() {
276 lower_ = Max(lower_, Smi::kMinValue);
277 upper_ = Min(upper_, Smi::kMaxValue);
278 }
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000279 void KeepOrder();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000280#ifdef DEBUG
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000281 void Verify() const;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000282#endif
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000283
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000284 void StackUpon(Range* other) {
285 Intersect(other);
286 next_ = other;
287 }
288
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000289 void Intersect(Range* other);
290 void Union(Range* other);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000291 void CombinedMax(Range* other);
292 void CombinedMin(Range* other);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000293
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000294 void AddConstant(int32_t value);
295 void Sar(int32_t value);
296 void Shl(int32_t value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000297 bool AddAndCheckOverflow(Range* other);
298 bool SubAndCheckOverflow(Range* other);
299 bool MulAndCheckOverflow(Range* other);
300
301 private:
302 int32_t lower_;
303 int32_t upper_;
304 Range* next_;
305 bool can_be_minus_zero_;
306};
307
308
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000309class UniqueValueId {
310 public:
311 UniqueValueId() : raw_address_(NULL) { }
312
313 explicit UniqueValueId(Object* object) {
314 raw_address_ = reinterpret_cast<Address>(object);
315 ASSERT(IsInitialized());
316 }
317
318 explicit UniqueValueId(Handle<Object> handle) {
319 static const Address kEmptyHandleSentinel = reinterpret_cast<Address>(1);
320 if (handle.is_null()) {
321 raw_address_ = kEmptyHandleSentinel;
322 } else {
323 raw_address_ = reinterpret_cast<Address>(*handle);
324 ASSERT_NE(kEmptyHandleSentinel, raw_address_);
325 }
326 ASSERT(IsInitialized());
327 }
328
329 bool IsInitialized() const { return raw_address_ != NULL; }
330
331 bool operator==(const UniqueValueId& other) const {
332 ASSERT(IsInitialized() && other.IsInitialized());
333 return raw_address_ == other.raw_address_;
334 }
335
336 bool operator!=(const UniqueValueId& other) const {
337 ASSERT(IsInitialized() && other.IsInitialized());
338 return raw_address_ != other.raw_address_;
339 }
340
341 intptr_t Hashcode() const {
342 ASSERT(IsInitialized());
343 return reinterpret_cast<intptr_t>(raw_address_);
344 }
345
346 private:
347 Address raw_address_;
348};
349
350
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000351class HType {
352 public:
353 HType() : type_(kUninitialized) { }
354
355 static HType Tagged() { return HType(kTagged); }
356 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
357 static HType TaggedNumber() { return HType(kTaggedNumber); }
358 static HType Smi() { return HType(kSmi); }
359 static HType HeapNumber() { return HType(kHeapNumber); }
360 static HType String() { return HType(kString); }
361 static HType Boolean() { return HType(kBoolean); }
362 static HType NonPrimitive() { return HType(kNonPrimitive); }
363 static HType JSArray() { return HType(kJSArray); }
364 static HType JSObject() { return HType(kJSObject); }
365 static HType Uninitialized() { return HType(kUninitialized); }
366
367 // Return the weakest (least precise) common type.
368 HType Combine(HType other) {
369 return HType(static_cast<Type>(type_ & other.type_));
370 }
371
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000372 bool Equals(const HType& other) const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000373 return type_ == other.type_;
374 }
375
376 bool IsSubtypeOf(const HType& other) {
377 return Combine(other).Equals(other);
378 }
379
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000380 bool IsTagged() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000381 ASSERT(type_ != kUninitialized);
382 return ((type_ & kTagged) == kTagged);
383 }
384
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000385 bool IsTaggedPrimitive() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000386 ASSERT(type_ != kUninitialized);
387 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
388 }
389
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000390 bool IsTaggedNumber() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000391 ASSERT(type_ != kUninitialized);
392 return ((type_ & kTaggedNumber) == kTaggedNumber);
393 }
394
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000395 bool IsSmi() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000396 ASSERT(type_ != kUninitialized);
397 return ((type_ & kSmi) == kSmi);
398 }
399
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000400 bool IsHeapNumber() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000401 ASSERT(type_ != kUninitialized);
402 return ((type_ & kHeapNumber) == kHeapNumber);
403 }
404
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000405 bool IsString() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000406 ASSERT(type_ != kUninitialized);
407 return ((type_ & kString) == kString);
408 }
409
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000410 bool IsBoolean() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000411 ASSERT(type_ != kUninitialized);
412 return ((type_ & kBoolean) == kBoolean);
413 }
414
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000415 bool IsNonPrimitive() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000416 ASSERT(type_ != kUninitialized);
417 return ((type_ & kNonPrimitive) == kNonPrimitive);
418 }
419
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000420 bool IsJSArray() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000421 ASSERT(type_ != kUninitialized);
422 return ((type_ & kJSArray) == kJSArray);
423 }
424
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000425 bool IsJSObject() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000426 ASSERT(type_ != kUninitialized);
427 return ((type_ & kJSObject) == kJSObject);
428 }
429
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000430 bool IsUninitialized() const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000431 return type_ == kUninitialized;
432 }
433
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000434 bool IsHeapObject() const {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000435 ASSERT(type_ != kUninitialized);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000436 return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000437 }
438
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000439 static HType TypeFromValue(Handle<Object> value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000440
441 const char* ToString();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000442
443 private:
444 enum Type {
445 kTagged = 0x1, // 0000 0000 0000 0001
446 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
447 kTaggedNumber = 0xd, // 0000 0000 0000 1101
448 kSmi = 0x1d, // 0000 0000 0001 1101
449 kHeapNumber = 0x2d, // 0000 0000 0010 1101
450 kString = 0x45, // 0000 0000 0100 0101
451 kBoolean = 0x85, // 0000 0000 1000 0101
452 kNonPrimitive = 0x101, // 0000 0001 0000 0001
453 kJSObject = 0x301, // 0000 0011 0000 0001
whesse@chromium.org7b260152011-06-20 15:33:18 +0000454 kJSArray = 0x701, // 0000 0111 0000 0001
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000455 kUninitialized = 0x1fff // 0001 1111 1111 1111
456 };
457
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000458 // Make sure type fits in int16.
459 STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
460
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000461 explicit HType(Type t) : type_(t) { }
462
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000463 int16_t type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000464};
465
466
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000467class HUseListNode: public ZoneObject {
468 public:
469 HUseListNode(HValue* value, int index, HUseListNode* tail)
470 : tail_(tail), value_(value), index_(index) {
471 }
472
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000473 HUseListNode* tail();
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000474 HValue* value() const { return value_; }
475 int index() const { return index_; }
476
477 void set_tail(HUseListNode* list) { tail_ = list; }
478
479#ifdef DEBUG
480 void Zap() {
481 tail_ = reinterpret_cast<HUseListNode*>(1);
482 value_ = NULL;
483 index_ = -1;
484 }
485#endif
486
487 private:
488 HUseListNode* tail_;
489 HValue* value_;
490 int index_;
491};
492
493
494// We reuse use list nodes behind the scenes as uses are added and deleted.
495// This class is the safe way to iterate uses while deleting them.
496class HUseIterator BASE_EMBEDDED {
497 public:
498 bool Done() { return current_ == NULL; }
499 void Advance();
500
501 HValue* value() {
502 ASSERT(!Done());
503 return value_;
504 }
505
506 int index() {
507 ASSERT(!Done());
508 return index_;
509 }
510
511 private:
512 explicit HUseIterator(HUseListNode* head);
513
514 HUseListNode* current_;
515 HUseListNode* next_;
516 HValue* value_;
517 int index_;
518
519 friend class HValue;
520};
521
522
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000523// There must be one corresponding kDepends flag for every kChanges flag and
524// the order of the kChanges flags must be exactly the same as of the kDepends
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000525// flags. All tracked flags should appear before untracked ones.
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000526enum GVNFlag {
527 // Declare global value numbering flags.
528#define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000529 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
530 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000531#undef DECLARE_FLAG
532 kAfterLastFlag,
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000533 kLastFlag = kAfterLastFlag - 1,
534#define COUNT_FLAG(type) + 1
535 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG)
536#undef COUNT_FLAG
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000537};
538
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000539
540class NumericRelation {
541 public:
542 enum Kind { NONE, EQ, GT, GE, LT, LE, NE };
543 static const char* MnemonicFromKind(Kind kind) {
544 switch (kind) {
545 case NONE: return "NONE";
546 case EQ: return "EQ";
547 case GT: return "GT";
548 case GE: return "GE";
549 case LT: return "LT";
550 case LE: return "LE";
551 case NE: return "NE";
552 }
553 UNREACHABLE();
554 return NULL;
555 }
556 const char* Mnemonic() const { return MnemonicFromKind(kind_); }
557
558 static NumericRelation None() { return NumericRelation(NONE); }
559 static NumericRelation Eq() { return NumericRelation(EQ); }
560 static NumericRelation Gt() { return NumericRelation(GT); }
561 static NumericRelation Ge() { return NumericRelation(GE); }
562 static NumericRelation Lt() { return NumericRelation(LT); }
563 static NumericRelation Le() { return NumericRelation(LE); }
564 static NumericRelation Ne() { return NumericRelation(NE); }
565
566 bool IsNone() { return kind_ == NONE; }
567
568 static NumericRelation FromToken(Token::Value token) {
569 switch (token) {
570 case Token::EQ: return Eq();
571 case Token::EQ_STRICT: return Eq();
572 case Token::LT: return Lt();
573 case Token::GT: return Gt();
574 case Token::LTE: return Le();
575 case Token::GTE: return Ge();
576 case Token::NE: return Ne();
577 case Token::NE_STRICT: return Ne();
578 default: return None();
579 }
580 }
581
582 // The semantics of "Reversed" is that if "x rel y" is true then also
583 // "y rel.Reversed() x" is true, and that rel.Reversed().Reversed() == rel.
584 NumericRelation Reversed() {
585 switch (kind_) {
586 case NONE: return None();
587 case EQ: return Eq();
588 case GT: return Lt();
589 case GE: return Le();
590 case LT: return Gt();
591 case LE: return Ge();
592 case NE: return Ne();
593 }
594 UNREACHABLE();
595 return None();
596 }
597
598 // The semantics of "Negated" is that if "x rel y" is true then also
599 // "!(x rel.Negated() y)" is true.
600 NumericRelation Negated() {
601 switch (kind_) {
602 case NONE: return None();
603 case EQ: return Ne();
604 case GT: return Le();
605 case GE: return Lt();
606 case LT: return Ge();
607 case LE: return Gt();
608 case NE: return Eq();
609 }
610 UNREACHABLE();
611 return None();
612 }
613
614 // The semantics of "Implies" is that if "x rel y" is true
615 // then also "x other_relation y" is true.
616 bool Implies(NumericRelation other_relation) {
617 switch (kind_) {
618 case NONE: return false;
619 case EQ: return (other_relation.kind_ == EQ)
620 || (other_relation.kind_ == GE)
621 || (other_relation.kind_ == LE);
622 case GT: return (other_relation.kind_ == GT)
623 || (other_relation.kind_ == GE)
624 || (other_relation.kind_ == NE);
625 case LT: return (other_relation.kind_ == LT)
626 || (other_relation.kind_ == LE)
627 || (other_relation.kind_ == NE);
628 case GE: return (other_relation.kind_ == GE);
629 case LE: return (other_relation.kind_ == LE);
630 case NE: return (other_relation.kind_ == NE);
631 }
632 UNREACHABLE();
633 return false;
634 }
635
636 // The semantics of "IsExtendable" is that if
637 // "rel.IsExtendable(direction)" is true then
638 // "x rel y" implies "(x + direction) rel y" .
639 bool IsExtendable(int direction) {
640 switch (kind_) {
641 case NONE: return false;
642 case EQ: return false;
643 case GT: return (direction >= 0);
644 case GE: return (direction >= 0);
645 case LT: return (direction <= 0);
646 case LE: return (direction <= 0);
647 case NE: return false;
648 }
649 UNREACHABLE();
650 return false;
651 }
652
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000653 // CompoundImplies returns true when
654 // "((x + my_offset) >> my_scale) rel y" implies
655 // "((x + other_offset) >> other_scale) other_relation y".
656 bool CompoundImplies(NumericRelation other_relation,
657 int my_offset,
658 int my_scale,
659 int other_offset = 0,
660 int other_scale = 0) {
661 return Implies(other_relation) && ComponentsImply(
662 my_offset, my_scale, other_offset, other_scale);
663 }
664
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000665 private:
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000666 // ComponentsImply returns true when
667 // "((x + my_offset) >> my_scale) rel y" implies
668 // "((x + other_offset) >> other_scale) rel y".
669 bool ComponentsImply(int my_offset,
670 int my_scale,
671 int other_offset,
672 int other_scale) {
673 switch (kind_) {
674 case NONE: break; // Fall through to UNREACHABLE().
675 case EQ:
676 case NE: return my_offset == other_offset && my_scale == other_scale;
677 case GT:
678 case GE: return my_offset <= other_offset && my_scale >= other_scale;
679 case LT:
680 case LE: return my_offset >= other_offset && my_scale <= other_scale;
681 }
682 UNREACHABLE();
683 return false;
684 }
685
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000686 explicit NumericRelation(Kind kind) : kind_(kind) {}
687
688 Kind kind_;
689};
690
691
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000692class DecompositionResult BASE_EMBEDDED {
693 public:
694 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
695
696 HValue* base() { return base_; }
697 int offset() { return offset_; }
698 int scale() { return scale_; }
699
700 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
701 if (base_ == NULL) {
702 base_ = other_base;
703 offset_ = other_offset;
704 scale_ = other_scale;
705 return true;
706 } else {
707 if (scale_ == 0) {
708 base_ = other_base;
709 offset_ += other_offset;
710 scale_ = other_scale;
711 return true;
712 } else {
713 return false;
714 }
715 }
716 }
717
718 void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
719 swap(&base_, other_base);
720 swap(&offset_, other_offset);
721 swap(&scale_, other_scale);
722 }
723
724 private:
725 template <class T> void swap(T* a, T* b) {
726 T c(*a);
727 *a = *b;
728 *b = c;
729 }
730
731 HValue* base_;
732 int offset_;
733 int scale_;
734};
735
736
737class RangeEvaluationContext BASE_EMBEDDED {
738 public:
739 RangeEvaluationContext(HValue* value, HValue* upper);
740
741 HValue* lower_bound() { return lower_bound_; }
742 HValue* lower_bound_guarantee() { return lower_bound_guarantee_; }
743 HValue* candidate() { return candidate_; }
744 HValue* upper_bound() { return upper_bound_; }
745 HValue* upper_bound_guarantee() { return upper_bound_guarantee_; }
746 int offset() { return offset_; }
747 int scale() { return scale_; }
748
749 bool is_range_satisfied() {
750 return lower_bound_guarantee() != NULL && upper_bound_guarantee() != NULL;
751 }
752
753 void set_lower_bound_guarantee(HValue* guarantee) {
754 lower_bound_guarantee_ = ConvertGuarantee(guarantee);
755 }
756 void set_upper_bound_guarantee(HValue* guarantee) {
757 upper_bound_guarantee_ = ConvertGuarantee(guarantee);
758 }
759
760 void swap_candidate(DecompositionResult* other_candicate) {
761 other_candicate->SwapValues(&candidate_, &offset_, &scale_);
762 }
763
764 private:
765 HValue* ConvertGuarantee(HValue* guarantee);
766
767 HValue* lower_bound_;
768 HValue* lower_bound_guarantee_;
769 HValue* candidate_;
770 HValue* upper_bound_;
771 HValue* upper_bound_guarantee_;
772 int offset_;
773 int scale_;
774};
775
776
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000777typedef EnumSet<GVNFlag> GVNFlagSet;
778
779
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000780class HValue: public ZoneObject {
781 public:
782 static const int kNoNumber = -1;
783
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000784 enum Flag {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000785 kFlexibleRepresentation,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000786 kCannotBeTagged,
whesse@chromium.org7b260152011-06-20 15:33:18 +0000787 // Participate in Global Value Numbering, i.e. elimination of
788 // unnecessary recomputations. If an instruction sets this flag, it must
789 // implement DataEquals(), which will be used to determine if other
790 // occurrences of the instruction are indeed the same.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000791 kUseGVN,
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000792 // Track instructions that are dominating side effects. If an instruction
danno@chromium.org169691d2013-07-15 08:01:13 +0000793 // sets this flag, it must implement HandleSideEffectDominator() and should
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000794 // indicate which side effects to track by setting GVN flags.
795 kTrackSideEffectDominators,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000796 kCanOverflow,
797 kBailoutOnMinusZero,
798 kCanBeDivByZero,
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +0000799 kAllowUndefinedAsNaN,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000800 kIsArguments,
801 kTruncatingToInt32,
ulan@chromium.org837a67e2013-06-11 15:39:48 +0000802 kAllUsesTruncatingToInt32,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000803 // Set after an instruction is killed.
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000804 kIsDead,
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000805 // Instructions that are allowed to produce full range unsigned integer
806 // values are marked with kUint32 flag. If arithmetic shift or a load from
807 // EXTERNAL_UNSIGNED_INT_ELEMENTS array is not marked with this flag
808 // it will deoptimize if result does not fit into signed integer range.
809 // HGraph::ComputeSafeUint32Operations is responsible for setting this
810 // flag.
811 kUint32,
ulan@chromium.org2e04b582013-02-21 14:06:02 +0000812 // If a phi is involved in the evaluation of a numeric constraint the
813 // recursion can cause an endless cycle: we use this flag to exit the loop.
814 kNumericConstraintEvaluationInProgress,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000815 // This flag is set to true after the SetupInformativeDefinitions() pass
816 // has processed this instruction.
817 kIDefsProcessingDone,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000818 kHasNoObservableSideEffects,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000819 // Indicates the instruction is live during dead code elimination.
820 kIsLive,
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000821
822 // HEnvironmentMarkers are deleted before dead code
823 // elimination takes place, so they can repurpose the kIsLive flag:
824 kEndsLiveRange = kIsLive,
825
826 // TODO(everyone): Don't forget to update this!
827 kLastFlag = kIsLive
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000828 };
829
830 STATIC_ASSERT(kLastFlag < kBitsPerInt);
831
832 static const int kChangesToDependsFlagsLeftShift = 1;
833
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000834 static GVNFlag ChangesFlagFromInt(int x) {
835 return static_cast<GVNFlag>(x * 2);
836 }
837 static GVNFlag DependsOnFlagFromInt(int x) {
838 return static_cast<GVNFlag>(x * 2 + 1);
839 }
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000840 static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
841 return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000842 }
843
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000844 static HValue* cast(HValue* value) { return value; }
845
846 enum Opcode {
847 // Declare a unique enum value for each hydrogen instruction.
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000848 #define DECLARE_OPCODE(type) k##type,
849 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
850 kPhi
851 #undef DECLARE_OPCODE
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000852 };
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000853 virtual Opcode opcode() const = 0;
854
855 // Declare a non-virtual predicates for each concrete HInstruction or HValue.
856 #define DECLARE_PREDICATE(type) \
857 bool Is##type() const { return opcode() == k##type; }
858 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
859 #undef DECLARE_PREDICATE
860 bool IsPhi() const { return opcode() == kPhi; }
861
862 // Declare virtual predicates for abstract HInstruction or HValue
863 #define DECLARE_PREDICATE(type) \
864 virtual bool Is##type() const { return false; }
865 HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
866 #undef DECLARE_PREDICATE
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000867
868 HValue() : block_(NULL),
869 id_(kNoNumber),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000870 type_(HType::Tagged()),
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000871 use_list_(NULL),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000872 range_(NULL),
873 flags_(0) {}
874 virtual ~HValue() {}
875
876 HBasicBlock* block() const { return block_; }
877 void SetBlock(HBasicBlock* block);
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000878 int LoopWeight() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000879
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000880 // Note: Never call this method for an unlinked value.
881 Isolate* isolate() const;
882
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000883 int id() const { return id_; }
884 void set_id(int id) { id_ = id; }
885
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000886 HUseIterator uses() const { return HUseIterator(use_list_); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000887
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000888 virtual bool EmitAtUses() { return false; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000889 Representation representation() const { return representation_; }
890 void ChangeRepresentation(Representation r) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000891 ASSERT(CheckFlag(kFlexibleRepresentation));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000892 ASSERT(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000893 RepresentationChanged(r);
894 representation_ = r;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000895 if (r.IsTagged()) {
896 // Tagged is the bottom of the lattice, don't go any further.
897 ClearFlag(kFlexibleRepresentation);
898 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000899 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000900 virtual void AssumeRepresentation(Representation r);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000901
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000902 virtual Representation KnownOptimalRepresentation() {
903 Representation r = representation();
904 if (r.IsTagged()) {
905 HType t = type();
906 if (t.IsSmi()) return Representation::Smi();
907 if (t.IsHeapNumber()) return Representation::Double();
908 if (t.IsHeapObject()) return r;
909 return Representation::None();
910 }
911 return r;
912 }
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +0000913
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000914 HType type() const { return type_; }
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000915 void set_type(HType new_type) {
916 ASSERT(new_type.IsSubtypeOf(type_));
917 type_ = new_type;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000918 }
919
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000920 bool IsHeapObject() {
921 return representation_.IsHeapObject() || type_.IsHeapObject();
922 }
923
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000924 // An operation needs to override this function iff:
925 // 1) it can produce an int32 output.
926 // 2) the true value of its output can potentially be minus zero.
927 // The implementation must set a flag so that it bails out in the case where
928 // it would otherwise output what should be a minus zero as an int32 zero.
929 // If the operation also exists in a form that takes int32 and outputs int32
930 // then the operation should return its input value so that we can propagate
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000931 // back. There are three operations that need to propagate back to more than
932 // one input. They are phi and binary div and mul. They always return NULL
933 // and expect the caller to take care of things.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000934 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
935 visited->Add(id());
936 return NULL;
937 }
938
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000939 // There are HInstructions that do not really change a value, they
940 // only add pieces of information to it (like bounds checks, map checks,
941 // smi checks...).
942 // We call these instructions "informative definitions", or "iDef".
943 // One of the iDef operands is special because it is the value that is
944 // "transferred" to the output, we call it the "redefined operand".
945 // If an HValue is an iDef it must override RedefinedOperandIndex() so that
946 // it does not return kNoRedefinedOperand;
947 static const int kNoRedefinedOperand = -1;
948 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
949 bool IsInformativeDefinition() {
950 return RedefinedOperandIndex() != kNoRedefinedOperand;
951 }
952 HValue* RedefinedOperand() {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000953 return IsInformativeDefinition() ? OperandAt(RedefinedOperandIndex())
954 : NULL;
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000955 }
956
ulan@chromium.org2e04b582013-02-21 14:06:02 +0000957 // A purely informative definition is an idef that will not emit code and
958 // should therefore be removed from the graph in the RestoreActualValues
959 // phase (so that live ranges will be shorter).
960 virtual bool IsPurelyInformativeDefinition() { return false; }
961
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000962 // This method must always return the original HValue SSA definition
963 // (regardless of any iDef of this value).
964 HValue* ActualValue() {
965 return IsInformativeDefinition() ? RedefinedOperand()->ActualValue()
966 : this;
967 }
968
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000969 virtual void AddInformativeDefinitions() {}
970
971 void UpdateRedefinedUsesWhileSettingUpInformativeDefinitions() {
972 UpdateRedefinedUsesInner<TestDominanceUsingProcessedFlag>();
973 }
974 void UpdateRedefinedUses() {
975 UpdateRedefinedUsesInner<Dominates>();
976 }
977
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000978 bool IsInteger32Constant();
979 int32_t GetInteger32Constant();
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000980 bool EqualsInteger32Constant(int32_t value);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000981
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000982 bool IsDefinedAfter(HBasicBlock* other) const;
983
984 // Operands.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000985 virtual int OperandCount() = 0;
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +0000986 virtual HValue* OperandAt(int index) const = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000987 void SetOperandAt(int index, HValue* value);
988
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000989 void DeleteAndReplaceWith(HValue* other);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000990 void ReplaceAllUsesWith(HValue* other);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000991 bool HasNoUses() const { return use_list_ == NULL; }
992 bool HasMultipleUses() const {
993 return use_list_ != NULL && use_list_->tail() != NULL;
994 }
995 int UseCount() const;
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000996
997 // Mark this HValue as dead and to be removed from other HValues' use lists.
998 void Kill();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000999
1000 int flags() const { return flags_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00001001 void SetFlag(Flag f) { flags_ |= (1 << f); }
1002 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
1003 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
1004
ulan@chromium.org812308e2012-02-29 15:58:45 +00001005 // Returns true if the flag specified is set for all uses, false otherwise.
1006 bool CheckUsesForFlag(Flag f);
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001007 // Returns true if the flag specified is set for all uses, and this set
1008 // of uses is non-empty.
1009 bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001010
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001011 GVNFlagSet gvn_flags() const { return gvn_flags_; }
1012 void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
1013 void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
1014 bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
1015 void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
1016 void ClearAllSideEffects() {
1017 gvn_flags_.Remove(AllSideEffectsFlagSet());
1018 }
1019 bool HasSideEffects() const {
1020 return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
1021 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001022 bool HasObservableSideEffects() const {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001023 return !CheckFlag(kHasNoObservableSideEffects) &&
1024 gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001025 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001026
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001027 GVNFlagSet DependsOnFlags() const {
1028 GVNFlagSet result = gvn_flags_;
1029 result.Intersect(AllDependsOnFlagSet());
1030 return result;
1031 }
1032
1033 GVNFlagSet SideEffectFlags() const {
1034 GVNFlagSet result = gvn_flags_;
1035 result.Intersect(AllSideEffectsFlagSet());
1036 return result;
1037 }
1038
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001039 GVNFlagSet ChangesFlags() const {
1040 GVNFlagSet result = gvn_flags_;
1041 result.Intersect(AllChangesFlagSet());
1042 return result;
1043 }
1044
1045 GVNFlagSet ObservableChangesFlags() const {
1046 GVNFlagSet result = gvn_flags_;
1047 result.Intersect(AllChangesFlagSet());
1048 result.Intersect(AllObservableSideEffectsFlagSet());
1049 return result;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001050 }
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001051
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001052 Range* range() const { return range_; }
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001053 // TODO(svenpanne) We should really use the null object pattern here.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001054 bool HasRange() const { return range_ != NULL; }
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001055 bool CanBeNegative() const { return !HasRange() || range()->CanBeNegative(); }
1056 bool CanBeZero() const { return !HasRange() || range()->CanBeZero(); }
1057 bool RangeCanInclude(int value) const {
1058 return !HasRange() || range()->Includes(value);
1059 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00001060 void AddNewRange(Range* r, Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001061 void RemoveLastAddedRange();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001062 void ComputeInitialRange(Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001063
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00001064 // Escape analysis helpers.
1065 virtual bool HasEscapingOperandAt(int index) { return true; }
1066
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001067 // Representation helpers.
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001068 virtual Representation observed_input_representation(int index) {
1069 return Representation::None();
1070 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001071 virtual Representation RequiredInputRepresentation(int index) = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001072 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001073
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001074 // This gives the instruction an opportunity to replace itself with an
1075 // instruction that does the same in some better way. To replace an
1076 // instruction with a new one, first add the new instruction to the graph,
1077 // then return it. Return NULL to have the instruction deleted.
1078 virtual HValue* Canonicalize() { return this; }
1079
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001080 bool Equals(HValue* other);
1081 virtual intptr_t Hashcode();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001082
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001083 // Compute unique ids upfront that is safe wrt GC and parallel recompilation.
1084 virtual void FinalizeUniqueValueId() { }
1085
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001086 // Printing support.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001087 virtual void PrintTo(StringStream* stream) = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001088 void PrintNameTo(StringStream* stream);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001089 void PrintTypeTo(StringStream* stream);
1090 void PrintRangeTo(StringStream* stream);
1091 void PrintChangesTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001092
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001093 const char* Mnemonic() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001094
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00001095 // Type information helpers.
1096 bool HasMonomorphicJSObjectType();
1097
1098 // TODO(mstarzinger): For now instructions can override this function to
1099 // specify statically known types, once HType can convey more information
1100 // it should be based on the HType.
1101 virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
1102
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001103 // Updated the inferred type of this instruction and returns true if
1104 // it has changed.
1105 bool UpdateInferredType();
1106
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001107 virtual HType CalculateInferredType();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001108
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001109 // This function must be overridden for instructions which have the
1110 // kTrackSideEffectDominators flag set, to track instructions that are
1111 // dominating side effects.
danno@chromium.org169691d2013-07-15 08:01:13 +00001112 virtual void HandleSideEffectDominator(GVNFlag side_effect,
1113 HValue* dominator) {
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001114 UNREACHABLE();
1115 }
1116
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001117 // Check if this instruction has some reason that prevents elimination.
1118 bool CannotBeEliminated() const {
1119 return HasObservableSideEffects() || !IsDeletable();
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00001120 }
1121
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001122#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001123 virtual void Verify() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001124#endif
1125
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001126 bool IsRelationTrue(NumericRelation relation,
1127 HValue* other,
1128 int offset = 0,
1129 int scale = 0);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001130
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001131 bool TryGuaranteeRange(HValue* upper_bound);
1132 virtual bool TryDecompose(DecompositionResult* decomposition) {
1133 if (RedefinedOperand() != NULL) {
1134 return RedefinedOperand()->TryDecompose(decomposition);
1135 } else {
1136 return false;
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001137 }
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001138 }
1139
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001140 protected:
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001141 void TryGuaranteeRangeRecursive(RangeEvaluationContext* context);
1142
1143 enum RangeGuaranteeDirection {
1144 DIRECTION_NONE = 0,
1145 DIRECTION_UPPER = 1,
1146 DIRECTION_LOWER = 2,
1147 DIRECTION_BOTH = DIRECTION_UPPER | DIRECTION_LOWER
1148 };
1149 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {}
1150 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) {}
1151
ager@chromium.org378b34e2011-01-28 08:04:38 +00001152 // This function must be overridden for instructions with flag kUseGVN, to
1153 // compare the non-Operand parts of the instruction.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001154 virtual bool DataEquals(HValue* other) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001155 UNREACHABLE();
1156 return false;
1157 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001158
1159 virtual Representation RepresentationFromInputs() {
1160 return representation();
1161 }
1162 Representation RepresentationFromUses();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001163 Representation RepresentationFromUseRequirements();
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001164 virtual void UpdateRepresentation(Representation new_rep,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001165 HInferRepresentationPhase* h_infer,
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001166 const char* reason);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001167 void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001168
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001169 virtual void RepresentationChanged(Representation to) { }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001170
ulan@chromium.org812308e2012-02-29 15:58:45 +00001171 virtual Range* InferRange(Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001172 virtual void DeleteFromGraph() = 0;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001173 virtual void InternalSetOperandAt(int index, HValue* value) = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001174 void clear_block() {
1175 ASSERT(block_ != NULL);
1176 block_ = NULL;
1177 }
1178
1179 void set_representation(Representation r) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001180 ASSERT(representation_.IsNone() && !r.IsNone());
1181 representation_ = r;
1182 }
1183
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001184 // Signature of a function testing if a HValue properly dominates another.
1185 typedef bool (*DominanceTest)(HValue*, HValue*);
1186
1187 // Simple implementation of DominanceTest implemented walking the chain
1188 // of Hinstructions (used in UpdateRedefinedUsesInner).
1189 static bool Dominates(HValue* dominator, HValue* dominated);
1190
1191 // A fast implementation of DominanceTest that works only for the
1192 // "current" instruction in the SetupInformativeDefinitions() phase.
1193 // During that phase we use a flag to mark processed instructions, and by
1194 // checking the flag we can quickly test if an instruction comes before or
1195 // after the "current" one.
1196 static bool TestDominanceUsingProcessedFlag(HValue* dominator,
1197 HValue* dominated);
1198
1199 // If we are redefining an operand, update all its dominated uses (the
1200 // function that checks if a use is dominated is the template argument).
1201 template<DominanceTest TestDominance>
1202 void UpdateRedefinedUsesInner() {
1203 HValue* input = RedefinedOperand();
1204 if (input != NULL) {
1205 for (HUseIterator uses = input->uses(); !uses.Done(); uses.Advance()) {
1206 HValue* use = uses.value();
1207 if (TestDominance(this, use)) {
1208 use->SetOperandAt(uses.index(), this);
1209 }
1210 }
1211 }
1212 }
1213
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001214 // Informative definitions can override this method to state any numeric
1215 // relation they provide on the redefined value.
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001216 // Returns true if it is guaranteed that:
1217 // ((this + offset) >> scale) relation other
1218 virtual bool IsRelationTrueInternal(NumericRelation relation,
1219 HValue* other,
1220 int offset = 0,
1221 int scale = 0) {
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001222 return false;
1223 }
1224
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001225 static GVNFlagSet AllDependsOnFlagSet() {
1226 GVNFlagSet result;
1227 // Create changes mask.
1228#define ADD_FLAG(type) result.Add(kDependsOn##type);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001229 GVN_TRACKED_FLAG_LIST(ADD_FLAG)
1230 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001231#undef ADD_FLAG
1232 return result;
1233 }
1234
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001235 static GVNFlagSet AllChangesFlagSet() {
1236 GVNFlagSet result;
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001237 // Create changes mask.
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001238#define ADD_FLAG(type) result.Add(kChanges##type);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001239 GVN_TRACKED_FLAG_LIST(ADD_FLAG)
1240 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001241#undef ADD_FLAG
1242 return result;
1243 }
1244
ager@chromium.org378b34e2011-01-28 08:04:38 +00001245 // A flag mask to mark an instruction as having arbitrary side effects.
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001246 static GVNFlagSet AllSideEffectsFlagSet() {
1247 GVNFlagSet result = AllChangesFlagSet();
1248 result.Remove(kChangesOsrEntries);
1249 return result;
ager@chromium.org378b34e2011-01-28 08:04:38 +00001250 }
1251
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001252 // A flag mask of all side effects that can make observable changes in
1253 // an executing program (i.e. are not safe to repeat, move or remove);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001254 static GVNFlagSet AllObservableSideEffectsFlagSet() {
1255 GVNFlagSet result = AllChangesFlagSet();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001256 result.Remove(kChangesNewSpacePromotion);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001257 result.Remove(kChangesElementsKind);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001258 result.Remove(kChangesElementsPointer);
1259 result.Remove(kChangesMaps);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001260 return result;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001261 }
1262
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001263 // Remove the matching use from the use list if present. Returns the
1264 // removed list node or NULL.
1265 HUseListNode* RemoveUse(HValue* value, int index);
1266
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001267 void RegisterUse(int index, HValue* new_value);
1268
1269 HBasicBlock* block_;
1270
1271 // The id of this instruction in the hydrogen graph, assigned when first
1272 // added to the graph. Reflects creation order.
1273 int id_;
1274
1275 Representation representation_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001276 HType type_;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001277 HUseListNode* use_list_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001278 Range* range_;
1279 int flags_;
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001280 GVNFlagSet gvn_flags_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001281
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001282 private:
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00001283 virtual bool IsDeletable() const { return false; }
1284
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001285 DISALLOW_COPY_AND_ASSIGN(HValue);
1286};
1287
1288
1289class HInstruction: public HValue {
1290 public:
1291 HInstruction* next() const { return next_; }
1292 HInstruction* previous() const { return previous_; }
1293
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001294 virtual void PrintTo(StringStream* stream);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001295 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001296
1297 bool IsLinked() const { return block() != NULL; }
1298 void Unlink();
1299 void InsertBefore(HInstruction* next);
1300 void InsertAfter(HInstruction* previous);
1301
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001302 // The position is a write-once variable.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001303 int position() const { return position_; }
1304 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001305 void set_position(int position) {
1306 ASSERT(!has_position());
1307 ASSERT(position != RelocInfo::kNoPosition);
1308 position_ = position;
1309 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001310
ulan@chromium.org812308e2012-02-29 15:58:45 +00001311 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
1312
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001313 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
1314
1315#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001316 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001317#endif
1318
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001319 virtual bool IsCall() { return false; }
1320
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001321 DECLARE_ABSTRACT_INSTRUCTION(Instruction)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001322
1323 protected:
1324 HInstruction()
1325 : next_(NULL),
1326 previous_(NULL),
1327 position_(RelocInfo::kNoPosition) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001328 SetGVNFlag(kDependsOnOsrEntries);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001329 }
1330
1331 virtual void DeleteFromGraph() { Unlink(); }
1332
1333 private:
1334 void InitializeAsFirst(HBasicBlock* block) {
1335 ASSERT(!IsLinked());
1336 SetBlock(block);
1337 }
1338
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001339 void PrintMnemonicTo(StringStream* stream);
1340
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001341 HInstruction* next_;
1342 HInstruction* previous_;
1343 int position_;
1344
1345 friend class HBasicBlock;
1346};
1347
1348
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001349template<int V>
1350class HTemplateInstruction : public HInstruction {
1351 public:
1352 int OperandCount() { return V; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00001353 HValue* OperandAt(int i) const { return inputs_[i]; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001354
1355 protected:
1356 void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
1357
1358 private:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001359 EmbeddedContainer<HValue*, V> inputs_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001360};
1361
1362
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001363class HControlInstruction: public HInstruction {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001364 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001365 virtual HBasicBlock* SuccessorAt(int i) = 0;
1366 virtual int SuccessorCount() = 0;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001367 virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001368
1369 virtual void PrintDataTo(StringStream* stream);
1370
1371 HBasicBlock* FirstSuccessor() {
1372 return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1373 }
1374 HBasicBlock* SecondSuccessor() {
1375 return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1376 }
1377
1378 DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
1379};
1380
1381
1382class HSuccessorIterator BASE_EMBEDDED {
1383 public:
1384 explicit HSuccessorIterator(HControlInstruction* instr)
1385 : instr_(instr), current_(0) { }
1386
1387 bool Done() { return current_ >= instr_->SuccessorCount(); }
1388 HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1389 void Advance() { current_++; }
1390
1391 private:
1392 HControlInstruction* instr_;
1393 int current_;
1394};
1395
1396
1397template<int S, int V>
1398class HTemplateControlInstruction: public HControlInstruction {
1399 public:
1400 int SuccessorCount() { return S; }
1401 HBasicBlock* SuccessorAt(int i) { return successors_[i]; }
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001402 void SetSuccessorAt(int i, HBasicBlock* block) { successors_[i] = block; }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001403
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001404 int OperandCount() { return V; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00001405 HValue* OperandAt(int i) const { return inputs_[i]; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001406
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001407
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001408 protected:
1409 void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
1410
1411 private:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001412 EmbeddedContainer<HBasicBlock*, S> successors_;
1413 EmbeddedContainer<HValue*, V> inputs_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001414};
1415
1416
1417class HBlockEntry: public HTemplateInstruction<0> {
1418 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001419 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001420 return Representation::None();
1421 }
1422
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001423 DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001424};
1425
1426
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001427class HDummyUse: public HTemplateInstruction<1> {
1428 public:
1429 explicit HDummyUse(HValue* value) {
1430 SetOperandAt(0, value);
1431 // Pretend to be a Smi so that the HChange instructions inserted
1432 // before any use generate as little code as possible.
1433 set_representation(Representation::Tagged());
1434 set_type(HType::Smi());
1435 }
1436
1437 HValue* value() { return OperandAt(0); }
1438
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00001439 virtual bool HasEscapingOperandAt(int index) { return false; }
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001440 virtual Representation RequiredInputRepresentation(int index) {
1441 return Representation::None();
1442 }
1443
1444 virtual void PrintDataTo(StringStream* stream);
1445
1446 DECLARE_CONCRETE_INSTRUCTION(DummyUse);
1447};
1448
1449
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001450class HNumericConstraint : public HTemplateInstruction<2> {
1451 public:
1452 static HNumericConstraint* AddToGraph(HValue* constrained_value,
1453 NumericRelation relation,
1454 HValue* related_value,
1455 HInstruction* insertion_point = NULL);
1456
1457 HValue* constrained_value() { return OperandAt(0); }
1458 HValue* related_value() { return OperandAt(1); }
1459 NumericRelation relation() { return relation_; }
1460
1461 virtual int RedefinedOperandIndex() { return 0; }
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001462 virtual bool IsPurelyInformativeDefinition() { return true; }
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001463
1464 virtual Representation RequiredInputRepresentation(int index) {
1465 return representation();
1466 }
1467
1468 virtual void PrintDataTo(StringStream* stream);
1469
1470 virtual bool IsRelationTrueInternal(NumericRelation other_relation,
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001471 HValue* other_related_value,
1472 int offset = 0,
1473 int scale = 0) {
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001474 if (related_value() == other_related_value) {
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001475 return relation().CompoundImplies(other_relation, offset, scale);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001476 } else {
1477 return false;
1478 }
1479 }
1480
1481 DECLARE_CONCRETE_INSTRUCTION(NumericConstraint)
1482
1483 private:
1484 HNumericConstraint(HValue* constrained_value,
1485 NumericRelation relation,
1486 HValue* related_value)
1487 : relation_(relation) {
1488 SetOperandAt(0, constrained_value);
1489 SetOperandAt(1, related_value);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001490 }
1491
1492 NumericRelation relation_;
1493};
1494
1495
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00001496// We insert soft-deoptimize when we hit code with unknown typefeedback,
1497// so that we get a chance of re-optimizing with useful typefeedback.
1498// HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
1499class HSoftDeoptimize: public HTemplateInstruction<0> {
1500 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001501 virtual Representation RequiredInputRepresentation(int index) {
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00001502 return Representation::None();
1503 }
1504
1505 DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize)
1506};
1507
1508
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001509// Inserts an int3/stop break instruction for debugging purposes.
1510class HDebugBreak: public HTemplateInstruction<0> {
1511 public:
1512 virtual Representation RequiredInputRepresentation(int index) {
1513 return Representation::None();
1514 }
1515
1516 DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1517};
1518
1519
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001520class HDeoptimize: public HControlInstruction {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001521 public:
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001522 HDeoptimize(int environment_length,
1523 int first_local_index,
1524 int first_expression_index,
1525 Zone* zone)
1526 : values_(environment_length, zone),
1527 first_local_index_(first_local_index),
1528 first_expression_index_(first_expression_index) { }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001529
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001530 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001531 return Representation::None();
1532 }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001533
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001534 virtual int OperandCount() { return values_.length(); }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00001535 virtual HValue* OperandAt(int index) const { return values_[index]; }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00001536 virtual void PrintDataTo(StringStream* stream);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001537
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001538 virtual int SuccessorCount() { return 0; }
1539 virtual HBasicBlock* SuccessorAt(int i) {
1540 UNREACHABLE();
1541 return NULL;
1542 }
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001543 virtual void SetSuccessorAt(int i, HBasicBlock* block) {
1544 UNREACHABLE();
1545 }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001546
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001547 void AddEnvironmentValue(HValue* value, Zone* zone) {
1548 values_.Add(NULL, zone);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001549 SetOperandAt(values_.length() - 1, value);
1550 }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001551 int first_local_index() { return first_local_index_; }
1552 int first_expression_index() { return first_expression_index_; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001553
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001554 DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001555
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001556 enum UseEnvironment {
1557 kNoUses,
1558 kUseAll
1559 };
1560
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001561 protected:
1562 virtual void InternalSetOperandAt(int index, HValue* value) {
1563 values_[index] = value;
1564 }
1565
1566 private:
1567 ZoneList<HValue*> values_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001568 int first_local_index_;
1569 int first_expression_index_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001570};
1571
1572
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001573class HGoto: public HTemplateControlInstruction<1, 0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001574 public:
ager@chromium.org04921a82011-06-27 13:21:41 +00001575 explicit HGoto(HBasicBlock* target) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001576 SetSuccessorAt(0, target);
1577 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001578
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001579 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001580 return Representation::None();
1581 }
1582
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001583 virtual void PrintDataTo(StringStream* stream);
1584
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001585 DECLARE_CONCRETE_INSTRUCTION(Goto)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001586};
1587
1588
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001589class HUnaryControlInstruction: public HTemplateControlInstruction<2, 1> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001590 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001591 HUnaryControlInstruction(HValue* value,
1592 HBasicBlock* true_target,
1593 HBasicBlock* false_target) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001594 SetOperandAt(0, value);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001595 SetSuccessorAt(0, true_target);
1596 SetSuccessorAt(1, false_target);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001597 }
1598
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001599 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001600
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001601 HValue* value() { return OperandAt(0); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001602};
1603
1604
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001605class HBranch: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001606 public:
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001607 HBranch(HValue* value,
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001608 ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
1609 HBasicBlock* true_target = NULL,
1610 HBasicBlock* false_target = NULL)
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001611 : HUnaryControlInstruction(value, true_target, false_target),
1612 expected_input_types_(expected_input_types) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001613 SetFlag(kAllowUndefinedAsNaN);
1614 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001615
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001616 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001617 return Representation::None();
1618 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001619 virtual Representation observed_input_representation(int index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001620
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001621 ToBooleanStub::Types expected_input_types() const {
1622 return expected_input_types_;
1623 }
1624
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001625 DECLARE_CONCRETE_INSTRUCTION(Branch)
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001626
1627 private:
1628 ToBooleanStub::Types expected_input_types_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001629};
1630
1631
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001632class HCompareMap: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001633 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001634 HCompareMap(HValue* value,
1635 Handle<Map> map,
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001636 HBasicBlock* true_target = NULL,
1637 HBasicBlock* false_target = NULL)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001638 : HUnaryControlInstruction(value, true_target, false_target),
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001639 map_(map) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001640 ASSERT(!map.is_null());
1641 }
1642
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001643 virtual void PrintDataTo(StringStream* stream);
whesse@chromium.org023421e2010-12-21 12:19:12 +00001644
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001645 Handle<Map> map() const { return map_; }
1646
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001647 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001648 return Representation::Tagged();
1649 }
1650
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001651 DECLARE_CONCRETE_INSTRUCTION(CompareMap)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001652
1653 private:
1654 Handle<Map> map_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001655};
1656
1657
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001658class HReturn: public HTemplateControlInstruction<0, 3> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001659 public:
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001660 HReturn(HValue* value, HValue* context, HValue* parameter_count) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001661 SetOperandAt(0, value);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001662 SetOperandAt(1, context);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001663 SetOperandAt(2, parameter_count);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001664 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001665
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001666 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001667 return Representation::Tagged();
1668 }
1669
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001670 virtual void PrintDataTo(StringStream* stream);
1671
1672 HValue* value() { return OperandAt(0); }
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001673 HValue* context() { return OperandAt(1); }
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001674 HValue* parameter_count() { return OperandAt(2); }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001675
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001676 DECLARE_CONCRETE_INSTRUCTION(Return)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001677};
1678
1679
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001680class HAbnormalExit: public HTemplateControlInstruction<0, 0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001681 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001682 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001683 return Representation::None();
1684 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001685
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001686 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001687};
1688
1689
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001690class HUnaryOperation: public HTemplateInstruction<1> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001691 public:
1692 explicit HUnaryOperation(HValue* value) {
1693 SetOperandAt(0, value);
1694 }
1695
ricow@chromium.orgc54d3652011-05-30 09:20:16 +00001696 static HUnaryOperation* cast(HValue* value) {
1697 return reinterpret_cast<HUnaryOperation*>(value);
1698 }
1699
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00001700 HValue* value() const { return OperandAt(0); }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001701 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001702};
1703
1704
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001705class HThrow: public HTemplateInstruction<2> {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001706 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001707 HThrow(HValue* context, HValue* value) {
1708 SetOperandAt(0, context);
1709 SetOperandAt(1, value);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001710 SetAllSideEffects();
1711 }
1712
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001713 virtual Representation RequiredInputRepresentation(int index) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001714 return Representation::Tagged();
1715 }
1716
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001717 HValue* context() { return OperandAt(0); }
1718 HValue* value() { return OperandAt(1); }
1719
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001720 DECLARE_CONCRETE_INSTRUCTION(Throw)
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001721};
1722
1723
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001724class HUseConst: public HUnaryOperation {
1725 public:
1726 explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1727
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001728 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001729 return Representation::None();
1730 }
1731
1732 DECLARE_CONCRETE_INSTRUCTION(UseConst)
1733};
1734
1735
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001736class HForceRepresentation: public HTemplateInstruction<1> {
1737 public:
1738 HForceRepresentation(HValue* value, Representation required_representation) {
1739 SetOperandAt(0, value);
1740 set_representation(required_representation);
1741 }
1742
1743 HValue* value() { return OperandAt(0); }
1744
1745 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1746
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001747 virtual Representation RequiredInputRepresentation(int index) {
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001748 return representation(); // Same as the output representation.
1749 }
1750
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001751 virtual void PrintDataTo(StringStream* stream);
1752
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001753 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1754};
1755
1756
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001757class HChange: public HUnaryOperation {
1758 public:
1759 HChange(HValue* value,
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001760 Representation to,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001761 bool is_truncating,
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001762 bool allow_undefined_as_nan)
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001763 : HUnaryOperation(value) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001764 ASSERT(!value->representation().IsNone());
1765 ASSERT(!to.IsNone());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001766 ASSERT(!value->representation().Equals(to));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001767 set_representation(to);
1768 SetFlag(kUseGVN);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001769 if (allow_undefined_as_nan) SetFlag(kAllowUndefinedAsNaN);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001770 if (is_truncating) SetFlag(kTruncatingToInt32);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001771 if (value->representation().IsSmi() || value->type().IsSmi()) {
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00001772 set_type(HType::Smi());
1773 } else {
1774 set_type(HType::TaggedNumber());
1775 if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
1776 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001777 }
1778
1779 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001780 virtual HType CalculateInferredType();
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001781 virtual HValue* Canonicalize();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001782
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00001783 Representation from() const { return value()->representation(); }
1784 Representation to() const { return representation(); }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001785 bool allow_undefined_as_nan() const {
1786 return CheckFlag(kAllowUndefinedAsNaN);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001787 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001788 bool deoptimize_on_minus_zero() const {
1789 return CheckFlag(kBailoutOnMinusZero);
1790 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001791 virtual Representation RequiredInputRepresentation(int index) {
1792 return from();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001793 }
1794
ulan@chromium.org812308e2012-02-29 15:58:45 +00001795 virtual Range* InferRange(Zone* zone);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001796
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001797 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001798
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001799 DECLARE_CONCRETE_INSTRUCTION(Change)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001800
1801 protected:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001802 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00001803
1804 private:
1805 virtual bool IsDeletable() const {
1806 return !from().IsTagged() || value()->type().IsSmi();
1807 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001808};
1809
1810
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001811class HClampToUint8: public HUnaryOperation {
1812 public:
1813 explicit HClampToUint8(HValue* value)
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001814 : HUnaryOperation(value) {
1815 set_representation(Representation::Integer32());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001816 SetFlag(kAllowUndefinedAsNaN);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001817 SetFlag(kUseGVN);
1818 }
1819
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001820 virtual Representation RequiredInputRepresentation(int index) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001821 return Representation::None();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001822 }
1823
1824 DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1825
1826 protected:
1827 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00001828
1829 private:
1830 virtual bool IsDeletable() const { return true; }
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001831};
1832
1833
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001834enum RemovableSimulate {
1835 REMOVABLE_SIMULATE,
1836 FIXED_SIMULATE
1837};
1838
1839
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001840class HSimulate: public HInstruction {
1841 public:
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001842 HSimulate(BailoutId ast_id,
1843 int pop_count,
1844 Zone* zone,
1845 RemovableSimulate removable)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001846 : ast_id_(ast_id),
1847 pop_count_(pop_count),
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001848 values_(2, zone),
1849 assigned_indexes_(2, zone),
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001850 zone_(zone),
1851 removable_(removable) {}
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001852 virtual ~HSimulate() {}
1853
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001854 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001855
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001856 bool HasAstId() const { return !ast_id_.IsNone(); }
1857 BailoutId ast_id() const { return ast_id_; }
1858 void set_ast_id(BailoutId id) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001859 ASSERT(!HasAstId());
1860 ast_id_ = id;
1861 }
1862
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001863 int pop_count() const { return pop_count_; }
1864 const ZoneList<HValue*>* values() const { return &values_; }
1865 int GetAssignedIndexAt(int index) const {
1866 ASSERT(HasAssignedIndexAt(index));
1867 return assigned_indexes_[index];
1868 }
1869 bool HasAssignedIndexAt(int index) const {
1870 return assigned_indexes_[index] != kNoIndex;
1871 }
1872 void AddAssignedValue(int index, HValue* value) {
1873 AddValue(index, value);
1874 }
1875 void AddPushedValue(HValue* value) {
1876 AddValue(kNoIndex, value);
1877 }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001878 int ToOperandIndex(int environment_index) {
1879 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1880 if (assigned_indexes_[i] == environment_index) return i;
1881 }
1882 return -1;
1883 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001884 virtual int OperandCount() { return values_.length(); }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00001885 virtual HValue* OperandAt(int index) const { return values_[index]; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001886
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00001887 virtual bool HasEscapingOperandAt(int index) { return false; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001888 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001889 return Representation::None();
1890 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001891
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001892 void MergeWith(ZoneList<HSimulate*>* list);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001893 bool is_candidate_for_removal() { return removable_ == REMOVABLE_SIMULATE; }
1894
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00001895 DECLARE_CONCRETE_INSTRUCTION(Simulate)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001896
1897#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001898 virtual void Verify();
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001899 void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1900 Handle<JSFunction> closure() const { return closure_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001901#endif
1902
1903 protected:
1904 virtual void InternalSetOperandAt(int index, HValue* value) {
1905 values_[index] = value;
1906 }
1907
1908 private:
1909 static const int kNoIndex = -1;
1910 void AddValue(int index, HValue* value) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001911 assigned_indexes_.Add(index, zone_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001912 // Resize the list of pushed values.
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001913 values_.Add(NULL, zone_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001914 // Set the operand through the base method in HValue to make sure that the
1915 // use lists are correctly updated.
1916 SetOperandAt(values_.length() - 1, value);
1917 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001918 bool HasValueForIndex(int index) {
1919 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1920 if (assigned_indexes_[i] == index) return true;
1921 }
1922 return false;
1923 }
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001924 BailoutId ast_id_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001925 int pop_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001926 ZoneList<HValue*> values_;
1927 ZoneList<int> assigned_indexes_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001928 Zone* zone_;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001929 RemovableSimulate removable_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001930
1931#ifdef DEBUG
1932 Handle<JSFunction> closure_;
1933#endif
1934};
1935
1936
1937class HEnvironmentMarker: public HTemplateInstruction<1> {
1938 public:
1939 enum Kind { BIND, LOOKUP };
1940
1941 HEnvironmentMarker(Kind kind, int index)
1942 : kind_(kind), index_(index), next_simulate_(NULL) { }
1943
1944 Kind kind() { return kind_; }
1945 int index() { return index_; }
1946 HSimulate* next_simulate() { return next_simulate_; }
1947 void set_next_simulate(HSimulate* simulate) {
1948 next_simulate_ = simulate;
1949 }
1950
1951 virtual Representation RequiredInputRepresentation(int index) {
1952 return Representation::None();
1953 }
1954
1955 virtual void PrintDataTo(StringStream* stream);
1956
1957#ifdef DEBUG
1958 void set_closure(Handle<JSFunction> closure) {
1959 ASSERT(closure_.is_null());
1960 ASSERT(!closure.is_null());
1961 closure_ = closure;
1962 }
1963 Handle<JSFunction> closure() const { return closure_; }
1964#endif
1965
1966 DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
1967
1968 private:
1969 Kind kind_;
1970 int index_;
1971 HSimulate* next_simulate_;
1972
1973#ifdef DEBUG
1974 Handle<JSFunction> closure_;
1975#endif
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001976};
1977
1978
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001979class HStackCheck: public HTemplateInstruction<1> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001980 public:
ager@chromium.org04921a82011-06-27 13:21:41 +00001981 enum Type {
1982 kFunctionEntry,
1983 kBackwardsBranch
1984 };
1985
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001986 HStackCheck(HValue* context, Type type) : type_(type) {
1987 SetOperandAt(0, context);
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00001988 SetGVNFlag(kChangesNewSpacePromotion);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001989 }
1990
1991 HValue* context() { return OperandAt(0); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001992
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001993 virtual Representation RequiredInputRepresentation(int index) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001994 return Representation::Tagged();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001995 }
1996
ager@chromium.org04921a82011-06-27 13:21:41 +00001997 void Eliminate() {
1998 // The stack check eliminator might try to eliminate the same stack
1999 // check instruction multiple times.
2000 if (IsLinked()) {
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00002001 DeleteAndReplaceWith(NULL);
ager@chromium.org04921a82011-06-27 13:21:41 +00002002 }
2003 }
2004
2005 bool is_function_entry() { return type_ == kFunctionEntry; }
2006 bool is_backwards_branch() { return type_ == kBackwardsBranch; }
2007
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002008 DECLARE_CONCRETE_INSTRUCTION(StackCheck)
ager@chromium.org04921a82011-06-27 13:21:41 +00002009
2010 private:
2011 Type type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002012};
2013
2014
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002015enum InliningKind {
2016 NORMAL_RETURN, // Normal function/method call and return.
2017 DROP_EXTRA_ON_RETURN, // Drop an extra value from the environment on return.
2018 CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00002019 GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002020 SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
2021};
2022
2023
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002024class HArgumentsObject;
2025
2026
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002027class HEnterInlined: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002028 public:
danno@chromium.org40cb8782011-05-25 07:58:50 +00002029 HEnterInlined(Handle<JSFunction> closure,
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002030 int arguments_count,
danno@chromium.org40cb8782011-05-25 07:58:50 +00002031 FunctionLiteral* function,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002032 InliningKind inlining_kind,
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002033 Variable* arguments_var,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002034 HArgumentsObject* arguments_object,
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002035 bool undefined_receiver,
2036 Zone* zone)
danno@chromium.org40cb8782011-05-25 07:58:50 +00002037 : closure_(closure),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002038 arguments_count_(arguments_count),
ulan@chromium.org56c14af2012-09-20 12:51:09 +00002039 arguments_pushed_(false),
danno@chromium.org40cb8782011-05-25 07:58:50 +00002040 function_(function),
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002041 inlining_kind_(inlining_kind),
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002042 arguments_var_(arguments_var),
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002043 arguments_object_(arguments_object),
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002044 undefined_receiver_(undefined_receiver),
2045 return_targets_(2, zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002046 }
2047
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002048 void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
2049 ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
2050
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002051 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002052
2053 Handle<JSFunction> closure() const { return closure_; }
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002054 int arguments_count() const { return arguments_count_; }
ulan@chromium.org56c14af2012-09-20 12:51:09 +00002055 bool arguments_pushed() const { return arguments_pushed_; }
2056 void set_arguments_pushed() { arguments_pushed_ = true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002057 FunctionLiteral* function() const { return function_; }
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002058 InliningKind inlining_kind() const { return inlining_kind_; }
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002059 bool undefined_receiver() const { return undefined_receiver_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002060
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002061 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002062 return Representation::None();
2063 }
2064
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002065 Variable* arguments_var() { return arguments_var_; }
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002066 HArgumentsObject* arguments_object() { return arguments_object_; }
danno@chromium.org8c0a43f2012-04-03 08:37:53 +00002067
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002068 DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002069
2070 private:
2071 Handle<JSFunction> closure_;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002072 int arguments_count_;
ulan@chromium.org56c14af2012-09-20 12:51:09 +00002073 bool arguments_pushed_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002074 FunctionLiteral* function_;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002075 InliningKind inlining_kind_;
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002076 Variable* arguments_var_;
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002077 HArgumentsObject* arguments_object_;
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002078 bool undefined_receiver_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002079 ZoneList<HBasicBlock*> return_targets_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002080};
2081
2082
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002083class HLeaveInlined: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002084 public:
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002085 HLeaveInlined() { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002086
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002087 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002088 return Representation::None();
2089 }
2090
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002091 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002092};
2093
2094
2095class HPushArgument: public HUnaryOperation {
2096 public:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002097 explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
2098 set_representation(Representation::Tagged());
2099 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002100
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002101 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002102 return Representation::Tagged();
2103 }
2104
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002105 HValue* argument() { return OperandAt(0); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002106
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002107 DECLARE_CONCRETE_INSTRUCTION(PushArgument)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002108};
2109
2110
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00002111class HThisFunction: public HTemplateInstruction<0> {
2112 public:
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00002113 HThisFunction() {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00002114 set_representation(Representation::Tagged());
2115 SetFlag(kUseGVN);
2116 }
2117
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002118 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00002119 return Representation::None();
2120 }
2121
2122 DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
2123
2124 protected:
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00002125 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00002126
2127 private:
2128 virtual bool IsDeletable() const { return true; }
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00002129};
2130
2131
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002132class HContext: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002133 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002134 HContext() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002135 set_representation(Representation::Tagged());
2136 SetFlag(kUseGVN);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002137 }
2138
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002139 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002140 return Representation::None();
2141 }
2142
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00002143 DECLARE_CONCRETE_INSTRUCTION(Context)
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002144
2145 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002146 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00002147
2148 private:
2149 virtual bool IsDeletable() const { return true; }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002150};
2151
2152
2153class HOuterContext: public HUnaryOperation {
2154 public:
2155 explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
2156 set_representation(Representation::Tagged());
2157 SetFlag(kUseGVN);
2158 }
2159
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002160 DECLARE_CONCRETE_INSTRUCTION(OuterContext);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002161
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002162 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002163 return Representation::Tagged();
2164 }
2165
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002166 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002167 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00002168
2169 private:
2170 virtual bool IsDeletable() const { return true; }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002171};
2172
2173
yangguo@chromium.org56454712012-02-16 15:33:53 +00002174class HDeclareGlobals: public HUnaryOperation {
2175 public:
2176 HDeclareGlobals(HValue* context,
2177 Handle<FixedArray> pairs,
2178 int flags)
2179 : HUnaryOperation(context),
2180 pairs_(pairs),
2181 flags_(flags) {
2182 set_representation(Representation::Tagged());
2183 SetAllSideEffects();
2184 }
2185
2186 HValue* context() { return OperandAt(0); }
2187 Handle<FixedArray> pairs() const { return pairs_; }
2188 int flags() const { return flags_; }
2189
2190 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
2191
2192 virtual Representation RequiredInputRepresentation(int index) {
2193 return Representation::Tagged();
2194 }
2195 private:
2196 Handle<FixedArray> pairs_;
2197 int flags_;
2198};
2199
2200
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002201class HGlobalObject: public HUnaryOperation {
2202 public:
2203 explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
2204 set_representation(Representation::Tagged());
2205 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002206 }
2207
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002208 DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
ager@chromium.org378b34e2011-01-28 08:04:38 +00002209
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002210 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002211 return Representation::Tagged();
2212 }
2213
ager@chromium.org378b34e2011-01-28 08:04:38 +00002214 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002215 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00002216
2217 private:
2218 virtual bool IsDeletable() const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002219};
2220
2221
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002222class HGlobalReceiver: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002223 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002224 explicit HGlobalReceiver(HValue* global_object)
2225 : HUnaryOperation(global_object) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002226 set_representation(Representation::Tagged());
2227 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002228 }
2229
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002230 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
ager@chromium.org378b34e2011-01-28 08:04:38 +00002231
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002232 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002233 return Representation::Tagged();
2234 }
2235
ager@chromium.org378b34e2011-01-28 08:04:38 +00002236 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002237 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00002238
2239 private:
2240 virtual bool IsDeletable() const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002241};
2242
2243
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002244template <int V>
2245class HCall: public HTemplateInstruction<V> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002246 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002247 // The argument count includes the receiver.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002248 explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
2249 this->set_representation(Representation::Tagged());
2250 this->SetAllSideEffects();
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002251 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002252
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002253 virtual HType CalculateInferredType() { return HType::Tagged(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002254
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002255 virtual int argument_count() const { return argument_count_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002256
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002257 virtual bool IsCall() { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002258
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002259 private:
2260 int argument_count_;
2261};
2262
2263
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002264class HUnaryCall: public HCall<1> {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002265 public:
2266 HUnaryCall(HValue* value, int argument_count)
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002267 : HCall<1>(argument_count) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002268 SetOperandAt(0, value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002269 }
2270
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002271 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002272 return Representation::Tagged();
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002273 }
2274
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002275 virtual void PrintDataTo(StringStream* stream);
2276
2277 HValue* value() { return OperandAt(0); }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002278};
2279
2280
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002281class HBinaryCall: public HCall<2> {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002282 public:
2283 HBinaryCall(HValue* first, HValue* second, int argument_count)
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002284 : HCall<2>(argument_count) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002285 SetOperandAt(0, first);
2286 SetOperandAt(1, second);
2287 }
2288
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002289 virtual void PrintDataTo(StringStream* stream);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002290
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002291 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002292 return Representation::Tagged();
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002293 }
2294
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002295 HValue* first() { return OperandAt(0); }
2296 HValue* second() { return OperandAt(1); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002297};
2298
2299
danno@chromium.org160a7b02011-04-18 15:51:38 +00002300class HInvokeFunction: public HBinaryCall {
2301 public:
2302 HInvokeFunction(HValue* context, HValue* function, int argument_count)
2303 : HBinaryCall(context, function, argument_count) {
2304 }
2305
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00002306 HInvokeFunction(HValue* context,
2307 HValue* function,
2308 Handle<JSFunction> known_function,
2309 int argument_count)
2310 : HBinaryCall(context, function, argument_count),
2311 known_function_(known_function) {
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002312 formal_parameter_count_ = known_function.is_null()
2313 ? 0 : known_function->shared()->formal_parameter_count();
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00002314 }
2315
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002316 virtual Representation RequiredInputRepresentation(int index) {
danno@chromium.org160a7b02011-04-18 15:51:38 +00002317 return Representation::Tagged();
2318 }
2319
2320 HValue* context() { return first(); }
2321 HValue* function() { return second(); }
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00002322 Handle<JSFunction> known_function() { return known_function_; }
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002323 int formal_parameter_count() const { return formal_parameter_count_; }
danno@chromium.org160a7b02011-04-18 15:51:38 +00002324
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002325 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00002326
2327 private:
2328 Handle<JSFunction> known_function_;
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002329 int formal_parameter_count_;
danno@chromium.org160a7b02011-04-18 15:51:38 +00002330};
2331
2332
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002333class HCallConstantFunction: public HCall<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002334 public:
2335 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002336 : HCall<0>(argument_count),
2337 function_(function),
2338 formal_parameter_count_(function->shared()->formal_parameter_count()) {}
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002339
2340 Handle<JSFunction> function() const { return function_; }
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002341 int formal_parameter_count() const { return formal_parameter_count_; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002342
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002343 bool IsApplyFunction() const {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002344 return function_->code() ==
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002345 Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002346 }
2347
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002348 virtual void PrintDataTo(StringStream* stream);
2349
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002350 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002351 return Representation::None();
2352 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002353
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002354 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002355
2356 private:
2357 Handle<JSFunction> function_;
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002358 int formal_parameter_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002359};
2360
2361
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002362class HCallKeyed: public HBinaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002363 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002364 HCallKeyed(HValue* context, HValue* key, int argument_count)
2365 : HBinaryCall(context, key, argument_count) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002366 }
2367
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002368 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002369 return Representation::Tagged();
2370 }
2371
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002372 HValue* context() { return first(); }
2373 HValue* key() { return second(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002374
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002375 DECLARE_CONCRETE_INSTRUCTION(CallKeyed)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002376};
2377
2378
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002379class HCallNamed: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002380 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002381 HCallNamed(HValue* context, Handle<String> name, int argument_count)
2382 : HUnaryCall(context, argument_count), name_(name) {
2383 }
2384
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002385 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002386
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002387 HValue* context() { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002388 Handle<String> name() const { return name_; }
2389
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002390 DECLARE_CONCRETE_INSTRUCTION(CallNamed)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002391
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002392 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002393 return Representation::Tagged();
2394 }
2395
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002396 private:
2397 Handle<String> name_;
2398};
2399
2400
danno@chromium.orgc612e022011-11-10 11:38:15 +00002401class HCallFunction: public HBinaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002402 public:
danno@chromium.orgc612e022011-11-10 11:38:15 +00002403 HCallFunction(HValue* context, HValue* function, int argument_count)
2404 : HBinaryCall(context, function, argument_count) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002405 }
2406
danno@chromium.orgc612e022011-11-10 11:38:15 +00002407 HValue* context() { return first(); }
2408 HValue* function() { return second(); }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002409
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002410 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002411 return Representation::Tagged();
2412 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002413
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002414 DECLARE_CONCRETE_INSTRUCTION(CallFunction)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002415};
2416
2417
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002418class HCallGlobal: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002419 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002420 HCallGlobal(HValue* context, Handle<String> name, int argument_count)
2421 : HUnaryCall(context, argument_count), name_(name) {
2422 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002423
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002424 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002425
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002426 HValue* context() { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002427 Handle<String> name() const { return name_; }
2428
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002429 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002430 return Representation::Tagged();
2431 }
2432
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002433 DECLARE_CONCRETE_INSTRUCTION(CallGlobal)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002434
2435 private:
2436 Handle<String> name_;
2437};
2438
2439
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002440class HCallKnownGlobal: public HCall<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002441 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002442 HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002443 : HCall<0>(argument_count),
2444 target_(target),
2445 formal_parameter_count_(target->shared()->formal_parameter_count()) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002446
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002447 virtual void PrintDataTo(StringStream* stream);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002448
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002449 Handle<JSFunction> target() const { return target_; }
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002450 int formal_parameter_count() const { return formal_parameter_count_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002451
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002452 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002453 return Representation::None();
2454 }
2455
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002456 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002457
2458 private:
2459 Handle<JSFunction> target_;
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002460 int formal_parameter_count_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002461};
2462
2463
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002464class HCallNew: public HBinaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002465 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002466 HCallNew(HValue* context, HValue* constructor, int argument_count)
2467 : HBinaryCall(context, constructor, argument_count) {
2468 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002469
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002470 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002471 return Representation::Tagged();
2472 }
2473
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002474 HValue* context() { return first(); }
2475 HValue* constructor() { return second(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002476
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002477 DECLARE_CONCRETE_INSTRUCTION(CallNew)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002478};
2479
2480
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002481class HCallNewArray: public HCallNew {
2482 public:
2483 HCallNewArray(HValue* context, HValue* constructor, int argument_count,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002484 Handle<Cell> type_cell, ElementsKind elements_kind)
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002485 : HCallNew(context, constructor, argument_count),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002486 elements_kind_(elements_kind),
2487 type_cell_(type_cell) {}
2488
2489 virtual void PrintDataTo(StringStream* stream);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002490
danno@chromium.org41728482013-06-12 22:31:22 +00002491 Handle<Cell> property_cell() const {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002492 return type_cell_;
2493 }
2494
ulan@chromium.org57ff8812013-05-10 08:16:55 +00002495 ElementsKind elements_kind() const { return elements_kind_; }
2496
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002497 DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2498
2499 private:
ulan@chromium.org57ff8812013-05-10 08:16:55 +00002500 ElementsKind elements_kind_;
danno@chromium.org41728482013-06-12 22:31:22 +00002501 Handle<Cell> type_cell_;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002502};
2503
2504
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002505class HCallRuntime: public HCall<1> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002506 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002507 HCallRuntime(HValue* context,
2508 Handle<String> name,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002509 const Runtime::Function* c_function,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002510 int argument_count)
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002511 : HCall<1>(argument_count), c_function_(c_function), name_(name) {
2512 SetOperandAt(0, context);
2513 }
2514
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002515 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002516
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002517 HValue* context() { return OperandAt(0); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002518 const Runtime::Function* function() const { return c_function_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002519 Handle<String> name() const { return name_; }
2520
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002521 virtual Representation RequiredInputRepresentation(int index) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002522 return Representation::Tagged();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002523 }
2524
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002525 DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002526
2527 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002528 const Runtime::Function* c_function_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002529 Handle<String> name_;
2530};
2531
2532
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00002533class HMapEnumLength: public HUnaryOperation {
2534 public:
2535 explicit HMapEnumLength(HValue* value) : HUnaryOperation(value) {
2536 set_type(HType::Smi());
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002537 set_representation(Representation::Smi());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00002538 SetFlag(kUseGVN);
2539 SetGVNFlag(kDependsOnMaps);
2540 }
2541
2542 virtual Representation RequiredInputRepresentation(int index) {
2543 return Representation::Tagged();
2544 }
2545
2546 DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
2547
2548 protected:
2549 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00002550
2551 private:
2552 virtual bool IsDeletable() const { return true; }
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00002553};
2554
2555
whesse@chromium.org7b260152011-06-20 15:33:18 +00002556class HElementsKind: public HUnaryOperation {
2557 public:
2558 explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
2559 set_representation(Representation::Integer32());
2560 SetFlag(kUseGVN);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00002561 SetGVNFlag(kDependsOnElementsKind);
whesse@chromium.org7b260152011-06-20 15:33:18 +00002562 }
2563
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002564 virtual Representation RequiredInputRepresentation(int index) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00002565 return Representation::Tagged();
2566 }
2567
2568 DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
2569
2570 protected:
2571 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00002572
2573 private:
2574 virtual bool IsDeletable() const { return true; }
whesse@chromium.org7b260152011-06-20 15:33:18 +00002575};
2576
2577
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002578class HBitNot: public HUnaryOperation {
2579 public:
2580 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
2581 set_representation(Representation::Integer32());
2582 SetFlag(kUseGVN);
2583 SetFlag(kTruncatingToInt32);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002584 SetFlag(kAllowUndefinedAsNaN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002585 }
2586
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002587 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002588 return Representation::Integer32();
2589 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00002590 virtual Representation observed_input_representation(int index) {
2591 return Representation::Integer32();
2592 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002593 virtual HType CalculateInferredType();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002594
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +00002595 virtual HValue* Canonicalize();
2596
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002597 DECLARE_CONCRETE_INSTRUCTION(BitNot)
ager@chromium.org378b34e2011-01-28 08:04:38 +00002598
2599 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002600 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00002601
2602 private:
2603 virtual bool IsDeletable() const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002604};
2605
2606
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002607class HUnaryMathOperation: public HTemplateInstruction<2> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002608 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00002609 static HInstruction* New(Zone* zone,
2610 HValue* context,
2611 HValue* value,
2612 BuiltinFunctionId op);
2613
2614 HValue* context() { return OperandAt(0); }
2615 HValue* value() { return OperandAt(1); }
2616
2617 virtual void PrintDataTo(StringStream* stream);
2618
2619 virtual HType CalculateInferredType();
2620
2621 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2622
2623 virtual Representation RequiredInputRepresentation(int index) {
2624 if (index == 0) {
2625 return Representation::Tagged();
2626 } else {
2627 switch (op_) {
2628 case kMathFloor:
2629 case kMathRound:
2630 case kMathSqrt:
2631 case kMathPowHalf:
2632 case kMathLog:
2633 case kMathExp:
2634 case kMathSin:
2635 case kMathCos:
2636 case kMathTan:
2637 return Representation::Double();
2638 case kMathAbs:
2639 return representation();
2640 default:
2641 UNREACHABLE();
2642 return Representation::None();
2643 }
2644 }
2645 }
2646
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002647 virtual Range* InferRange(Zone* zone);
2648
ulan@chromium.org2e04b582013-02-21 14:06:02 +00002649 virtual HValue* Canonicalize();
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002650 virtual Representation RepresentationFromInputs();
ulan@chromium.org2e04b582013-02-21 14:06:02 +00002651
2652 BuiltinFunctionId op() const { return op_; }
2653 const char* OpName() const;
2654
2655 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2656
2657 protected:
2658 virtual bool DataEquals(HValue* other) {
2659 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2660 return op_ == b->op();
2661 }
2662
2663 private:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002664 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
2665 : op_(op) {
2666 SetOperandAt(0, context);
2667 SetOperandAt(1, value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002668 switch (op) {
2669 case kMathFloor:
2670 case kMathRound:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002671 set_representation(Representation::Integer32());
2672 break;
2673 case kMathAbs:
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00002674 // Not setting representation here: it is None intentionally.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002675 SetFlag(kFlexibleRepresentation);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002676 // TODO(svenpanne) This flag is actually only needed if representation()
2677 // is tagged, and not when it is an unboxed double or unboxed integer.
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00002678 SetGVNFlag(kChangesNewSpacePromotion);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002679 break;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002680 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00002681 case kMathSin:
2682 case kMathCos:
ulan@chromium.org9a21ec42012-03-06 08:42:24 +00002683 case kMathTan:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002684 set_representation(Representation::Double());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002685 // These operations use the TranscendentalCache, so they may allocate.
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00002686 SetGVNFlag(kChangesNewSpacePromotion);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002687 break;
danno@chromium.org1f34ad32012-11-26 14:53:56 +00002688 case kMathExp:
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002689 case kMathSqrt:
2690 case kMathPowHalf:
danno@chromium.org1f34ad32012-11-26 14:53:56 +00002691 set_representation(Representation::Double());
2692 break;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002693 default:
2694 UNREACHABLE();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002695 }
2696 SetFlag(kUseGVN);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002697 SetFlag(kAllowUndefinedAsNaN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002698 }
2699
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00002700 virtual bool IsDeletable() const { return true; }
2701
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002702 BuiltinFunctionId op_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002703};
2704
2705
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002706class HLoadExternalArrayPointer: public HUnaryOperation {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002707 public:
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002708 explicit HLoadExternalArrayPointer(HValue* value)
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002709 : HUnaryOperation(value) {
2710 set_representation(Representation::External());
2711 // The result of this instruction is idempotent as long as its inputs don't
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002712 // change. The external array of a specialized array elements object cannot
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002713 // change once set, so it's no necessary to introduce any additional
2714 // dependencies on top of the inputs.
2715 SetFlag(kUseGVN);
2716 }
2717
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002718 virtual Representation RequiredInputRepresentation(int index) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002719 return Representation::Tagged();
2720 }
2721
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002722 DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002723
2724 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002725 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00002726
2727 private:
2728 virtual bool IsDeletable() const { return true; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002729};
2730
2731
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002732class HCheckMaps: public HTemplateInstruction<2> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002733 public:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002734 static HCheckMaps* New(HValue* value, Handle<Map> map, Zone* zone,
2735 HValue *typecheck = NULL) {
2736 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
2737 check_map->map_set_.Add(map, zone);
2738 return check_map;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002739 }
2740
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002741 static HCheckMaps* New(HValue* value, SmallMapList* maps, Zone* zone,
2742 HValue *typecheck = NULL) {
2743 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
2744 for (int i = 0; i < maps->length(); i++) {
2745 check_map->map_set_.Add(maps->at(i), zone);
2746 }
2747 check_map->map_set_.Sort();
2748 return check_map;
2749 }
2750
2751 static HCheckMaps* NewWithTransitions(HValue* value, Handle<Map> map,
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002752 Zone* zone) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002753 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, value);
2754 check_map->map_set_.Add(map, zone);
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002755
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00002756 // Since transitioned elements maps of the initial map don't fail the map
2757 // check, the CheckMaps instruction doesn't need to depend on ElementsKinds.
2758 check_map->ClearGVNFlag(kDependsOnElementsKind);
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002759
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00002760 ElementsKind kind = map->elements_kind();
2761 bool packed = IsFastPackedElementsKind(kind);
2762 while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
2763 kind = GetNextMoreGeneralFastElementsKind(kind, packed);
2764 Map* transitioned_map =
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002765 map->LookupElementsTransitionMap(kind);
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00002766 if (transitioned_map) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002767 check_map->map_set_.Add(Handle<Map>(transitioned_map), zone);
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00002768 }
2769 };
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002770 check_map->map_set_.Sort();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002771 return check_map;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002772 }
2773
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00002774 virtual bool HasEscapingOperandAt(int index) { return false; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002775 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002776 return Representation::Tagged();
2777 }
danno@chromium.org169691d2013-07-15 08:01:13 +00002778 virtual void HandleSideEffectDominator(GVNFlag side_effect,
2779 HValue* dominator);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002780 virtual void PrintDataTo(StringStream* stream);
2781 virtual HType CalculateInferredType();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002782
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002783 HValue* value() { return OperandAt(0); }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002784 SmallMapList* map_set() { return &map_set_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002785
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002786 virtual void FinalizeUniqueValueId();
2787
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002788 DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002789
2790 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002791 virtual bool DataEquals(HValue* other) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002792 ASSERT_EQ(map_set_.length(), map_unique_ids_.length());
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002793 HCheckMaps* b = HCheckMaps::cast(other);
2794 // Relies on the fact that map_set has been sorted before.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002795 if (map_unique_ids_.length() != b->map_unique_ids_.length()) {
2796 return false;
2797 }
2798 for (int i = 0; i < map_unique_ids_.length(); i++) {
2799 if (map_unique_ids_.at(i) != b->map_unique_ids_.at(i)) {
2800 return false;
2801 }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002802 }
2803 return true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002804 }
2805
2806 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002807 // Clients should use one of the static New* methods above.
2808 HCheckMaps(HValue* value, Zone *zone, HValue* typecheck)
2809 : map_unique_ids_(0, zone) {
2810 SetOperandAt(0, value);
2811 // Use the object value for the dependency if NULL is passed.
2812 // TODO(titzer): do GVN flags already express this dependency?
2813 SetOperandAt(1, typecheck != NULL ? typecheck : value);
2814 set_representation(Representation::Tagged());
2815 SetFlag(kUseGVN);
2816 SetFlag(kTrackSideEffectDominators);
2817 SetGVNFlag(kDependsOnMaps);
2818 SetGVNFlag(kDependsOnElementsKind);
2819 }
2820
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002821 SmallMapList map_set_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002822 ZoneList<UniqueValueId> map_unique_ids_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002823};
2824
2825
2826class HCheckFunction: public HUnaryOperation {
2827 public:
2828 HCheckFunction(HValue* value, Handle<JSFunction> function)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002829 : HUnaryOperation(value), target_(function), target_unique_id_() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002830 set_representation(Representation::Tagged());
2831 SetFlag(kUseGVN);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002832 target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002833 }
2834
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002835 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002836 return Representation::Tagged();
2837 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002838 virtual void PrintDataTo(StringStream* stream);
2839 virtual HType CalculateInferredType();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002840
2841#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00002842 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002843#endif
2844
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002845 virtual void FinalizeUniqueValueId() {
2846 target_unique_id_ = UniqueValueId(target_);
2847 }
2848
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002849 Handle<JSFunction> target() const { return target_; }
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002850 bool target_in_new_space() const { return target_in_new_space_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002851
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002852 DECLARE_CONCRETE_INSTRUCTION(CheckFunction)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002853
2854 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002855 virtual bool DataEquals(HValue* other) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002856 HCheckFunction* b = HCheckFunction::cast(other);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002857 return target_unique_id_ == b->target_unique_id_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002858 }
2859
2860 private:
2861 Handle<JSFunction> target_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002862 UniqueValueId target_unique_id_;
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002863 bool target_in_new_space_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002864};
2865
2866
2867class HCheckInstanceType: public HUnaryOperation {
2868 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002869 static HCheckInstanceType* NewIsSpecObject(HValue* value, Zone* zone) {
2870 return new(zone) HCheckInstanceType(value, IS_SPEC_OBJECT);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002871 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002872 static HCheckInstanceType* NewIsJSArray(HValue* value, Zone* zone) {
2873 return new(zone) HCheckInstanceType(value, IS_JS_ARRAY);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002874 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002875 static HCheckInstanceType* NewIsString(HValue* value, Zone* zone) {
2876 return new(zone) HCheckInstanceType(value, IS_STRING);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002877 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002878 static HCheckInstanceType* NewIsInternalizedString(
2879 HValue* value, Zone* zone) {
2880 return new(zone) HCheckInstanceType(value, IS_INTERNALIZED_STRING);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002881 }
2882
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002883 virtual void PrintDataTo(StringStream* stream);
2884
2885 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002886 return Representation::Tagged();
2887 }
2888
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002889 virtual HValue* Canonicalize();
danno@chromium.org160a7b02011-04-18 15:51:38 +00002890
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002891 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2892 void GetCheckInterval(InstanceType* first, InstanceType* last);
2893 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002894
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00002895 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002896
2897 protected:
2898 // TODO(ager): It could be nice to allow the ommision of instance
2899 // type checks if we have already performed an instance type check
2900 // with a larger range.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002901 virtual bool DataEquals(HValue* other) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002902 HCheckInstanceType* b = HCheckInstanceType::cast(other);
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002903 return check_ == b->check_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002904 }
2905
2906 private:
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002907 enum Check {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00002908 IS_SPEC_OBJECT,
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002909 IS_JS_ARRAY,
2910 IS_STRING,
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002911 IS_INTERNALIZED_STRING,
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002912 LAST_INTERVAL_CHECK = IS_JS_ARRAY
2913 };
2914
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002915 const char* GetCheckName();
2916
karlklose@chromium.org83a47282011-05-11 11:54:09 +00002917 HCheckInstanceType(HValue* value, Check check)
2918 : HUnaryOperation(value), check_(check) {
2919 set_representation(Representation::Tagged());
2920 SetFlag(kUseGVN);
2921 }
2922
2923 const Check check_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002924};
2925
2926
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002927class HCheckSmi: public HUnaryOperation {
2928 public:
2929 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
2930 set_representation(Representation::Smi());
2931 SetFlag(kUseGVN);
2932 }
2933
2934 virtual Representation RequiredInputRepresentation(int index) {
2935 return Representation::Tagged();
2936 }
2937
2938 virtual HType CalculateInferredType();
2939
2940 virtual HValue* Canonicalize() {
2941 HType value_type = value()->type();
2942 if (value_type.IsSmi()) {
2943 return NULL;
2944 }
2945 return this;
2946 }
2947
2948 DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2949
2950 protected:
2951 virtual bool DataEquals(HValue* other) { return true; }
2952};
2953
2954
2955class HIsNumberAndBranch: public HUnaryControlInstruction {
2956 public:
2957 explicit HIsNumberAndBranch(HValue* value)
2958 : HUnaryControlInstruction(value, NULL, NULL) {
2959 SetFlag(kFlexibleRepresentation);
2960 }
2961
2962 virtual Representation RequiredInputRepresentation(int index) {
2963 return Representation::None();
2964 }
2965
2966 DECLARE_CONCRETE_INSTRUCTION(IsNumberAndBranch)
2967};
2968
2969
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002970class HCheckHeapObject: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002971 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002972 explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002973 set_representation(Representation::Tagged());
2974 SetFlag(kUseGVN);
2975 }
2976
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002977 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002978 return Representation::Tagged();
2979 }
2980
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002981 virtual HType CalculateInferredType();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002982
2983#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00002984 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002985#endif
2986
danno@chromium.org160a7b02011-04-18 15:51:38 +00002987 virtual HValue* Canonicalize() {
2988 HType value_type = value()->type();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002989 if (!value_type.IsUninitialized() && value_type.IsHeapObject()) {
danno@chromium.org160a7b02011-04-18 15:51:38 +00002990 return NULL;
2991 }
2992 return this;
2993 }
2994
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002995 DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
ager@chromium.org378b34e2011-01-28 08:04:38 +00002996
2997 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002998 virtual bool DataEquals(HValue* other) { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002999};
3000
3001
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003002class HCheckPrototypeMaps: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003003 public:
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +00003004 HCheckPrototypeMaps(Handle<JSObject> prototype,
3005 Handle<JSObject> holder,
danno@chromium.org41728482013-06-12 22:31:22 +00003006 Zone* zone,
3007 CompilationInfo* info)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003008 : prototypes_(2, zone),
3009 maps_(2, zone),
3010 first_prototype_unique_id_(),
danno@chromium.org41728482013-06-12 22:31:22 +00003011 last_prototype_unique_id_(),
3012 can_omit_prototype_maps_(true) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003013 SetFlag(kUseGVN);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00003014 SetGVNFlag(kDependsOnMaps);
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +00003015 // Keep a list of all objects on the prototype chain up to the holder
3016 // and the expected maps.
3017 while (true) {
3018 prototypes_.Add(prototype, zone);
danno@chromium.org41728482013-06-12 22:31:22 +00003019 Handle<Map> map(prototype->map());
3020 maps_.Add(map, zone);
3021 can_omit_prototype_maps_ &= map->CanOmitPrototypeChecks();
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +00003022 if (prototype.is_identical_to(holder)) break;
3023 prototype = Handle<JSObject>(JSObject::cast(prototype->GetPrototype()));
3024 }
danno@chromium.org41728482013-06-12 22:31:22 +00003025 if (can_omit_prototype_maps_) {
3026 // Mark in-flight compilation as dependent on those maps.
3027 for (int i = 0; i < maps()->length(); i++) {
3028 Handle<Map> map = maps()->at(i);
3029 map->AddDependentCompilationInfo(DependentCode::kPrototypeCheckGroup,
3030 info);
3031 }
3032 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003033 }
3034
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +00003035 ZoneList<Handle<JSObject> >* prototypes() { return &prototypes_; }
3036
3037 ZoneList<Handle<Map> >* maps() { return &maps_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003038
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00003039 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003040
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003041 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003042 return Representation::None();
3043 }
3044
danno@chromium.org81cac2b2012-07-10 11:28:27 +00003045 virtual void PrintDataTo(StringStream* stream);
3046
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003047 virtual intptr_t Hashcode() {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003048 return first_prototype_unique_id_.Hashcode() * 17 +
3049 last_prototype_unique_id_.Hashcode();
3050 }
3051
3052 virtual void FinalizeUniqueValueId() {
3053 first_prototype_unique_id_ = UniqueValueId(prototypes_.first());
3054 last_prototype_unique_id_ = UniqueValueId(prototypes_.last());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003055 }
3056
danno@chromium.org41728482013-06-12 22:31:22 +00003057 bool CanOmitPrototypeChecks() { return can_omit_prototype_maps_; }
ulan@chromium.org2e04b582013-02-21 14:06:02 +00003058
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003059 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003060 virtual bool DataEquals(HValue* other) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003061 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003062 return first_prototype_unique_id_ == b->first_prototype_unique_id_ &&
3063 last_prototype_unique_id_ == b->last_prototype_unique_id_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003064 }
3065
3066 private:
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +00003067 ZoneList<Handle<JSObject> > prototypes_;
3068 ZoneList<Handle<Map> > maps_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003069 UniqueValueId first_prototype_unique_id_;
3070 UniqueValueId last_prototype_unique_id_;
danno@chromium.org41728482013-06-12 22:31:22 +00003071 bool can_omit_prototype_maps_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003072};
3073
3074
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003075class HPhi: public HValue {
3076 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +00003077 HPhi(int merged_index, Zone* zone)
3078 : inputs_(2, zone),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003079 merged_index_(merged_index),
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00003080 phi_id_(-1) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003081 for (int i = 0; i < Representation::kNumRepresentations; i++) {
3082 non_phi_uses_[i] = 0;
3083 indirect_uses_[i] = 0;
3084 }
3085 ASSERT(merged_index >= 0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003086 SetFlag(kFlexibleRepresentation);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003087 SetFlag(kAllowUndefinedAsNaN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003088 }
3089
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003090 virtual Representation RepresentationFromInputs();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003091
ulan@chromium.org812308e2012-02-29 15:58:45 +00003092 virtual Range* InferRange(Zone* zone);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003093 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003094 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003095 return representation();
3096 }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00003097 virtual Representation KnownOptimalRepresentation() {
3098 return representation();
3099 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003100 virtual HType CalculateInferredType();
3101 virtual int OperandCount() { return inputs_.length(); }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00003102 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003103 HValue* GetRedundantReplacement();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003104 void AddInput(HValue* value);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00003105 bool HasRealUses();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003106
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00003107 bool IsReceiver() const { return merged_index_ == 0; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003108
3109 int merged_index() const { return merged_index_; }
3110
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00003111 virtual void AddInformativeDefinitions();
3112
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003113 virtual void PrintTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003114
3115#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00003116 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003117#endif
3118
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003119 void InitRealUses(int id);
3120 void AddNonPhiUsesFrom(HPhi* other);
3121 void AddIndirectUsesTo(int* use_count);
3122
3123 int tagged_non_phi_uses() const {
3124 return non_phi_uses_[Representation::kTagged];
3125 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00003126 int smi_non_phi_uses() const {
3127 return non_phi_uses_[Representation::kSmi];
3128 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003129 int int32_non_phi_uses() const {
3130 return non_phi_uses_[Representation::kInteger32];
3131 }
3132 int double_non_phi_uses() const {
3133 return non_phi_uses_[Representation::kDouble];
3134 }
3135 int tagged_indirect_uses() const {
3136 return indirect_uses_[Representation::kTagged];
3137 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00003138 int smi_indirect_uses() const {
3139 return indirect_uses_[Representation::kSmi];
3140 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003141 int int32_indirect_uses() const {
3142 return indirect_uses_[Representation::kInteger32];
3143 }
3144 int double_indirect_uses() const {
3145 return indirect_uses_[Representation::kDouble];
3146 }
3147 int phi_id() { return phi_id_; }
3148
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00003149 static HPhi* cast(HValue* value) {
3150 ASSERT(value->IsPhi());
3151 return reinterpret_cast<HPhi*>(value);
3152 }
3153 virtual Opcode opcode() const { return HValue::kPhi; }
3154
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003155 void SimplifyConstantInputs();
3156
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00003157 // TODO(titzer): we can't eliminate the receiver for generating backtraces
3158 virtual bool IsDeletable() const { return !IsReceiver(); }
3159
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003160 protected:
3161 virtual void DeleteFromGraph();
3162 virtual void InternalSetOperandAt(int index, HValue* value) {
3163 inputs_[index] = value;
3164 }
3165
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00003166 virtual bool IsRelationTrueInternal(NumericRelation relation,
3167 HValue* other,
3168 int offset = 0,
3169 int scale = 0);
ulan@chromium.org2e04b582013-02-21 14:06:02 +00003170
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003171 private:
3172 ZoneList<HValue*> inputs_;
3173 int merged_index_;
3174
3175 int non_phi_uses_[Representation::kNumRepresentations];
3176 int indirect_uses_[Representation::kNumRepresentations];
3177 int phi_id_;
3178};
3179
3180
ulan@chromium.org2e04b582013-02-21 14:06:02 +00003181class HInductionVariableAnnotation : public HUnaryOperation {
3182 public:
3183 static HInductionVariableAnnotation* AddToGraph(HPhi* phi,
3184 NumericRelation relation,
3185 int operand_index);
3186
3187 NumericRelation relation() { return relation_; }
3188 HValue* induction_base() { return phi_->OperandAt(operand_index_); }
3189
3190 virtual int RedefinedOperandIndex() { return 0; }
3191 virtual bool IsPurelyInformativeDefinition() { return true; }
3192 virtual Representation RequiredInputRepresentation(int index) {
3193 return representation();
3194 }
3195
3196 virtual void PrintDataTo(StringStream* stream);
3197
3198 virtual bool IsRelationTrueInternal(NumericRelation other_relation,
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00003199 HValue* other_related_value,
3200 int offset = 0,
3201 int scale = 0) {
ulan@chromium.org2e04b582013-02-21 14:06:02 +00003202 if (induction_base() == other_related_value) {
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00003203 return relation().CompoundImplies(other_relation, offset, scale);
ulan@chromium.org2e04b582013-02-21 14:06:02 +00003204 } else {
3205 return false;
3206 }
3207 }
3208
3209 DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation)
3210
3211 private:
3212 HInductionVariableAnnotation(HPhi* phi,
3213 NumericRelation relation,
3214 int operand_index)
3215 : HUnaryOperation(phi),
3216 phi_(phi), relation_(relation), operand_index_(operand_index) {
ulan@chromium.org2e04b582013-02-21 14:06:02 +00003217 }
3218
3219 // We need to store the phi both here and in the instruction operand because
3220 // the operand can change if a new idef of the phi is added between the phi
3221 // and this instruction (inserting an idef updates every use).
3222 HPhi* phi_;
3223 NumericRelation relation_;
3224 int operand_index_;
3225};
3226
3227
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003228class HArgumentsObject: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003229 public:
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00003230 HArgumentsObject(int count, Zone* zone) : values_(count, zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003231 set_representation(Representation::Tagged());
3232 SetFlag(kIsArguments);
3233 }
3234
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00003235 const ZoneList<HValue*>* arguments_values() const { return &values_; }
3236 int arguments_count() const { return values_.length(); }
3237
3238 void AddArgument(HValue* argument, Zone* zone) {
3239 values_.Add(NULL, zone); // Resize list.
3240 SetOperandAt(values_.length() - 1, argument);
3241 }
3242
3243 virtual int OperandCount() { return values_.length(); }
3244 virtual HValue* OperandAt(int index) const { return values_[index]; }
3245
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00003246 virtual bool HasEscapingOperandAt(int index) { return false; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003247 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003248 return Representation::None();
3249 }
3250
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00003251 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00003252
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00003253 protected:
3254 virtual void InternalSetOperandAt(int index, HValue* value) {
3255 values_[index] = value;
3256 }
3257
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00003258 private:
3259 virtual bool IsDeletable() const { return true; }
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00003260
3261 ZoneList<HValue*> values_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003262};
3263
3264
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003265class HConstant: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003266 public:
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00003267 HConstant(Handle<Object> handle, Representation r = Representation::None());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003268 HConstant(int32_t value,
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003269 Representation r = Representation::None(),
danno@chromium.orgf005df62013-04-30 16:36:45 +00003270 bool is_not_in_new_space = true,
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003271 Handle<Object> optional_handle = Handle<Object>::null());
3272 HConstant(double value,
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003273 Representation r = Representation::None(),
danno@chromium.orgf005df62013-04-30 16:36:45 +00003274 bool is_not_in_new_space = true,
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003275 Handle<Object> optional_handle = Handle<Object>::null());
3276 HConstant(Handle<Object> handle,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003277 UniqueValueId unique_id,
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003278 Representation r,
3279 HType type,
3280 bool is_internalized_string,
danno@chromium.orgf005df62013-04-30 16:36:45 +00003281 bool is_not_in_new_space,
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003282 bool is_cell,
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003283 bool boolean_value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003284
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003285 Handle<Object> handle() {
3286 if (handle_.is_null()) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00003287 Factory* factory = Isolate::Current()->factory();
danno@chromium.orgf005df62013-04-30 16:36:45 +00003288 // Default arguments to is_not_in_new_space depend on this heap number
3289 // to be tenured so that it's guaranteed not be be located in new space.
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00003290 handle_ = factory->NewNumber(double_value_, TENURED);
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003291 }
rossberg@chromium.org79e79022013-06-03 15:43:46 +00003292 AllowDeferredHandleDereference smi_check;
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003293 ASSERT(has_int32_value_ || !handle_->IsSmi());
3294 return handle_;
3295 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003296
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003297 bool IsSpecialDouble() const {
3298 return has_double_value_ &&
3299 (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
3300 FixedDoubleArray::is_the_hole_nan(double_value_) ||
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00003301 std::isnan(double_value_));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003302 }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00003303
danno@chromium.orgf005df62013-04-30 16:36:45 +00003304 bool NotInNewSpace() const {
3305 return is_not_in_new_space_;
3306 }
3307
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003308 bool ImmortalImmovable() const {
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003309 if (has_int32_value_) {
3310 return false;
3311 }
3312 if (has_double_value_) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003313 if (IsSpecialDouble()) {
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003314 return true;
3315 }
3316 return false;
3317 }
3318
3319 ASSERT(!handle_.is_null());
ulan@chromium.org09d7ab52013-02-25 15:50:35 +00003320 Heap* heap = isolate()->heap();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003321 ASSERT(unique_id_ != UniqueValueId(heap->minus_zero_value()));
3322 ASSERT(unique_id_ != UniqueValueId(heap->nan_value()));
3323 return unique_id_ == UniqueValueId(heap->undefined_value()) ||
3324 unique_id_ == UniqueValueId(heap->null_value()) ||
3325 unique_id_ == UniqueValueId(heap->true_value()) ||
3326 unique_id_ == UniqueValueId(heap->false_value()) ||
3327 unique_id_ == UniqueValueId(heap->the_hole_value()) ||
3328 unique_id_ == UniqueValueId(heap->empty_string());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003329 }
3330
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003331 bool IsCell() const {
3332 return is_cell_;
3333 }
3334
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003335 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003336 return Representation::None();
3337 }
3338
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00003339 virtual Representation KnownOptimalRepresentation() {
3340 if (HasSmiValue()) return Representation::Smi();
3341 if (HasInteger32Value()) return Representation::Integer32();
3342 if (HasNumberValue()) return Representation::Double();
3343 return Representation::Tagged();
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00003344 }
3345
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003346 virtual bool EmitAtUses();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003347 virtual void PrintDataTo(StringStream* stream);
3348 virtual HType CalculateInferredType();
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003349 bool IsInteger() { return handle()->IsSmi(); }
mmassi@chromium.org7028c052012-06-13 11:51:58 +00003350 HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
3351 HConstant* CopyToTruncatedInt32(Zone* zone) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003352 bool HasInteger32Value() const { return has_int32_value_; }
3353 int32_t Integer32Value() const {
3354 ASSERT(HasInteger32Value());
3355 return int32_value_;
3356 }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00003357 bool HasSmiValue() const { return has_smi_value_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003358 bool HasDoubleValue() const { return has_double_value_; }
3359 double DoubleValue() const {
3360 ASSERT(HasDoubleValue());
3361 return double_value_;
3362 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003363 bool IsTheHole() const {
3364 if (HasDoubleValue() && FixedDoubleArray::is_the_hole_nan(double_value_)) {
3365 return true;
3366 }
3367 Heap* heap = isolate()->heap();
3368 if (!handle_.is_null() && *handle_ == heap->the_hole_value()) {
3369 return true;
3370 }
3371 return false;
3372 }
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003373 bool HasNumberValue() const { return has_double_value_; }
erikcorry0ad885c2011-11-21 13:51:57 +00003374 int32_t NumberValueAsInteger32() const {
3375 ASSERT(HasNumberValue());
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003376 // Irrespective of whether a numeric HConstant can be safely
3377 // represented as an int32, we store the (in some cases lossy)
3378 // representation of the number in int32_value_.
3379 return int32_value_;
erikcorry0ad885c2011-11-21 13:51:57 +00003380 }
ulan@chromium.org2e04b582013-02-21 14:06:02 +00003381 bool HasStringValue() const {
3382 if (has_double_value_ || has_int32_value_) return false;
3383 ASSERT(!handle_.is_null());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003384 return type_from_value_.IsString();
ulan@chromium.org2e04b582013-02-21 14:06:02 +00003385 }
3386 Handle<String> StringValue() const {
3387 ASSERT(HasStringValue());
3388 return Handle<String>::cast(handle_);
3389 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003390 bool HasInternalizedStringValue() const {
3391 return HasStringValue() && is_internalized_string_;
3392 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003393
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003394 bool BooleanValue() const { return boolean_value_; }
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00003395
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003396 virtual intptr_t Hashcode() {
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003397 if (has_int32_value_) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003398 return static_cast<intptr_t>(int32_value_);
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003399 } else if (has_double_value_) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003400 return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003401 } else {
3402 ASSERT(!handle_.is_null());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003403 return unique_id_.Hashcode();
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003404 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003405 }
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003406
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003407 virtual void FinalizeUniqueValueId() {
3408 if (!has_double_value_) {
3409 ASSERT(!handle_.is_null());
3410 unique_id_ = UniqueValueId(handle_);
3411 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003412 }
3413
3414#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00003415 virtual void Verify() { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003416#endif
3417
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00003418 DECLARE_CONCRETE_INSTRUCTION(Constant)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003419
3420 protected:
ulan@chromium.org812308e2012-02-29 15:58:45 +00003421 virtual Range* InferRange(Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003422
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003423 virtual bool DataEquals(HValue* other) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003424 HConstant* other_constant = HConstant::cast(other);
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003425 if (has_int32_value_) {
3426 return other_constant->has_int32_value_ &&
3427 int32_value_ == other_constant->int32_value_;
3428 } else if (has_double_value_) {
3429 return other_constant->has_double_value_ &&
3430 BitCast<int64_t>(double_value_) ==
3431 BitCast<int64_t>(other_constant->double_value_);
3432 } else {
3433 ASSERT(!handle_.is_null());
3434 return !other_constant->handle_.is_null() &&
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003435 unique_id_ == other_constant->unique_id_;
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003436 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003437 }
3438
3439 private:
hpayer@chromium.org8432c912013-02-28 15:55:26 +00003440 void Initialize(Representation r);
3441
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00003442 virtual bool IsDeletable() const { return true; }
3443
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003444 // If this is a numerical constant, handle_ either points to to the
3445 // HeapObject the constant originated from or is null. If the
3446 // constant is non-numeric, handle_ always points to a valid
3447 // constant HeapObject.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003448 Handle<Object> handle_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003449 UniqueValueId unique_id_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003450
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00003451 // We store the HConstant in the most specific form safely possible.
3452 // The two flags, has_int32_value_ and has_double_value_ tell us if
3453 // int32_value_ and double_value_ hold valid, safe representations
3454 // of the constant. has_int32_value_ implies has_double_value_ but
3455 // not the converse.
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00003456 bool has_smi_value_ : 1;
danno@chromium.org160a7b02011-04-18 15:51:38 +00003457 bool has_int32_value_ : 1;
3458 bool has_double_value_ : 1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003459 bool is_internalized_string_ : 1; // TODO(yangguo): make this part of HType.
danno@chromium.orgf005df62013-04-30 16:36:45 +00003460 bool is_not_in_new_space_ : 1;
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003461 bool is_cell_ : 1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003462 bool boolean_value_ : 1;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003463 int32_t int32_value_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003464 double double_value_;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003465 HType type_from_value_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003466};
3467
3468
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003469class HBinaryOperation: public HTemplateInstruction<3> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003470 public:
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003471 HBinaryOperation(HValue* context, HValue* left, HValue* right)
3472 : observed_output_representation_(Representation::None()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003473 ASSERT(left != NULL && right != NULL);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003474 SetOperandAt(0, context);
3475 SetOperandAt(1, left);
3476 SetOperandAt(2, right);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003477 observed_input_representation_[0] = Representation::None();
3478 observed_input_representation_[1] = Representation::None();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003479 }
3480
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003481 HValue* context() { return OperandAt(0); }
3482 HValue* left() { return OperandAt(1); }
3483 HValue* right() { return OperandAt(2); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003484
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003485 // True if switching left and right operands likely generates better code.
3486 bool AreOperandsBetterSwitched() {
3487 if (!IsCommutative()) return false;
3488
3489 // Constant operands are better off on the right, they can be inlined in
3490 // many situations on most platforms.
3491 if (left()->IsConstant()) return true;
3492 if (right()->IsConstant()) return false;
3493
3494 // Otherwise, if there is only one use of the right operand, it would be
3495 // better off on the left for platforms that only have 2-arg arithmetic
3496 // ops (e.g ia32, x64) that clobber the left operand.
3497 return (right()->UseCount() == 1);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003498 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +00003499
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003500 HValue* BetterLeftOperand() {
3501 return AreOperandsBetterSwitched() ? right() : left();
3502 }
3503
3504 HValue* BetterRightOperand() {
3505 return AreOperandsBetterSwitched() ? left() : right();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003506 }
3507
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003508 void set_observed_input_representation(int index, Representation rep) {
3509 ASSERT(index >= 1 && index <= 2);
3510 observed_input_representation_[index - 1] = rep;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003511 }
3512
3513 virtual void initialize_output_representation(Representation observed) {
3514 observed_output_representation_ = observed;
3515 }
3516
3517 virtual Representation observed_input_representation(int index) {
3518 if (index == 0) return Representation::Tagged();
3519 return observed_input_representation_[index - 1];
3520 }
3521
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003522 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003523 virtual Representation RepresentationFromInputs();
3524 virtual void AssumeRepresentation(Representation r);
3525
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00003526 virtual void UpdateRepresentation(Representation new_rep,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003527 HInferRepresentationPhase* h_infer,
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00003528 const char* reason) {
3529 // By default, binary operations don't handle Smis.
3530 if (new_rep.IsSmi()) {
3531 new_rep = Representation::Integer32();
3532 }
3533 HValue::UpdateRepresentation(new_rep, h_infer, reason);
3534 }
3535
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003536 virtual bool IsCommutative() const { return false; }
3537
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003538 virtual void PrintDataTo(StringStream* stream);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00003539
3540 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003541
3542 private:
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00003543 bool IgnoreObservedOutputRepresentation(Representation current_rep);
3544
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003545 Representation observed_input_representation_[2];
3546 Representation observed_output_representation_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003547};
3548
3549
yangguo@chromium.org154ff992012-03-13 08:09:54 +00003550class HWrapReceiver: public HTemplateInstruction<2> {
3551 public:
3552 HWrapReceiver(HValue* receiver, HValue* function) {
3553 set_representation(Representation::Tagged());
3554 SetOperandAt(0, receiver);
3555 SetOperandAt(1, function);
3556 }
3557
3558 virtual Representation RequiredInputRepresentation(int index) {
3559 return Representation::Tagged();
3560 }
3561
3562 HValue* receiver() { return OperandAt(0); }
3563 HValue* function() { return OperandAt(1); }
3564
3565 virtual HValue* Canonicalize();
3566
yangguo@chromium.org39110192013-01-16 09:55:08 +00003567 virtual void PrintDataTo(StringStream* stream);
3568
yangguo@chromium.org154ff992012-03-13 08:09:54 +00003569 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3570};
3571
3572
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003573class HApplyArguments: public HTemplateInstruction<4> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003574 public:
3575 HApplyArguments(HValue* function,
3576 HValue* receiver,
3577 HValue* length,
3578 HValue* elements) {
3579 set_representation(Representation::Tagged());
3580 SetOperandAt(0, function);
3581 SetOperandAt(1, receiver);
3582 SetOperandAt(2, length);
3583 SetOperandAt(3, elements);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003584 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003585 }
3586
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003587 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003588 // The length is untagged, all other inputs are tagged.
3589 return (index == 2)
3590 ? Representation::Integer32()
3591 : Representation::Tagged();
3592 }
3593
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003594 HValue* function() { return OperandAt(0); }
3595 HValue* receiver() { return OperandAt(1); }
3596 HValue* length() { return OperandAt(2); }
3597 HValue* elements() { return OperandAt(3); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003598
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00003599 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003600};
3601
3602
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003603class HArgumentsElements: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003604 public:
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00003605 explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003606 // The value produced by this instruction is a pointer into the stack
3607 // that looks as if it was a smi because of alignment.
3608 set_representation(Representation::Tagged());
3609 SetFlag(kUseGVN);
3610 }
3611
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00003612 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
ager@chromium.org378b34e2011-01-28 08:04:38 +00003613
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003614 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003615 return Representation::None();
3616 }
3617
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00003618 bool from_inlined() const { return from_inlined_; }
3619
ager@chromium.org378b34e2011-01-28 08:04:38 +00003620 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003621 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00003622
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00003623 private:
3624 virtual bool IsDeletable() const { return true; }
3625
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00003626 bool from_inlined_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003627};
3628
3629
3630class HArgumentsLength: public HUnaryOperation {
3631 public:
3632 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3633 set_representation(Representation::Integer32());
3634 SetFlag(kUseGVN);
3635 }
3636
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003637 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003638 return Representation::Tagged();
3639 }
3640
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00003641 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
ager@chromium.org378b34e2011-01-28 08:04:38 +00003642
3643 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003644 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00003645
3646 private:
3647 virtual bool IsDeletable() const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003648};
3649
3650
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003651class HAccessArgumentsAt: public HTemplateInstruction<3> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003652 public:
3653 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
3654 set_representation(Representation::Tagged());
3655 SetFlag(kUseGVN);
3656 SetOperandAt(0, arguments);
3657 SetOperandAt(1, length);
3658 SetOperandAt(2, index);
3659 }
3660
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003661 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003662
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003663 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003664 // The arguments elements is considered tagged.
3665 return index == 0
3666 ? Representation::Tagged()
3667 : Representation::Integer32();
3668 }
3669
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003670 HValue* arguments() { return OperandAt(0); }
3671 HValue* length() { return OperandAt(1); }
3672 HValue* index() { return OperandAt(2); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003673
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00003674 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003675
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003676 virtual bool DataEquals(HValue* other) { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003677};
3678
3679
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00003680class HBoundsCheckBaseIndexInformation;
3681
3682
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003683class HBoundsCheck: public HTemplateInstruction<2> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003684 public:
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00003685 // Normally HBoundsCheck should be created using the
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00003686 // HGraphBuilder::AddBoundsCheck() helper.
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00003687 // However when building stubs, where we know that the arguments are Int32,
3688 // it makes sense to invoke this constructor directly.
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003689 HBoundsCheck(HValue* index, HValue* length)
3690 : skip_check_(false),
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00003691 base_(NULL), offset_(0), scale_(0),
3692 responsibility_direction_(DIRECTION_NONE) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003693 SetOperandAt(0, index);
3694 SetOperandAt(1, length);
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00003695 SetFlag(kFlexibleRepresentation);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003696 SetFlag(kUseGVN);
3697 }
3698
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00003699 bool skip_check() { return skip_check_; }
3700 void set_skip_check(bool skip_check) { skip_check_ = skip_check; }
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00003701 HValue* base() { return base_; }
3702 int offset() { return offset_; }
3703 int scale() { return scale_; }
3704 bool index_can_increase() {
3705 return (responsibility_direction_ & DIRECTION_LOWER) == 0;
3706 }
3707 bool index_can_decrease() {
3708 return (responsibility_direction_ & DIRECTION_UPPER) == 0;
3709 }
3710
3711 void ApplyIndexChange();
3712 bool DetectCompoundIndex() {
3713 ASSERT(base() == NULL);
3714
3715 DecompositionResult decomposition;
3716 if (index()->TryDecompose(&decomposition)) {
3717 base_ = decomposition.base();
3718 offset_ = decomposition.offset();
3719 scale_ = decomposition.scale();
3720 return true;
3721 } else {
3722 base_ = index();
3723 offset_ = 0;
3724 scale_ = 0;
3725 return false;
3726 }
3727 }
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00003728
yangguo@chromium.org304cc332012-07-24 07:59:48 +00003729 virtual Representation RequiredInputRepresentation(int arg_index) {
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00003730 return representation();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003731 }
3732
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00003733 virtual bool IsRelationTrueInternal(NumericRelation relation,
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00003734 HValue* related_value,
3735 int offset = 0,
3736 int scale = 0);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00003737
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00003738 virtual void PrintDataTo(StringStream* stream);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003739 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00003740
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003741 HValue* index() { return OperandAt(0); }
3742 HValue* length() { return OperandAt(1); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003743
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00003744 virtual int RedefinedOperandIndex() { return 0; }
ulan@chromium.org2e04b582013-02-21 14:06:02 +00003745 virtual bool IsPurelyInformativeDefinition() { return skip_check(); }
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00003746 virtual void AddInformativeDefinitions();
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00003747
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00003748 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
ager@chromium.org378b34e2011-01-28 08:04:38 +00003749
3750 protected:
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00003751 friend class HBoundsCheckBaseIndexInformation;
3752
3753 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {
3754 responsibility_direction_ = static_cast<RangeGuaranteeDirection>(
3755 responsibility_direction_ | direction);
3756 }
3757
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003758 virtual bool DataEquals(HValue* other) { return true; }
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00003759 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00003760 bool skip_check_;
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00003761 HValue* base_;
3762 int offset_;
3763 int scale_;
3764 RangeGuaranteeDirection responsibility_direction_;
3765};
3766
3767
3768class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> {
3769 public:
3770 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
3771 DecompositionResult decomposition;
3772 if (check->index()->TryDecompose(&decomposition)) {
3773 SetOperandAt(0, decomposition.base());
3774 SetOperandAt(1, check);
3775 } else {
3776 UNREACHABLE();
3777 }
3778 }
3779
3780 HValue* base_index() { return OperandAt(0); }
3781 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
3782
3783 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
3784
3785 virtual Representation RequiredInputRepresentation(int arg_index) {
3786 return representation();
3787 }
3788
3789 virtual bool IsRelationTrueInternal(NumericRelation relation,
3790 HValue* related_value,
3791 int offset = 0,
3792 int scale = 0);
3793 virtual void PrintDataTo(StringStream* stream);
3794
3795 virtual int RedefinedOperandIndex() { return 0; }
3796 virtual bool IsPurelyInformativeDefinition() { return true; }
3797
3798 protected:
3799 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {
3800 bounds_check()->SetResponsibilityForRange(direction);
3801 }
3802 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) {
3803 bounds_check()->TryGuaranteeRangeChanging(context);
3804 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003805};
3806
3807
3808class HBitwiseBinaryOperation: public HBinaryOperation {
3809 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003810 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right)
3811 : HBinaryOperation(context, left, right) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003812 SetFlag(kFlexibleRepresentation);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003813 SetFlag(kTruncatingToInt32);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003814 SetFlag(kAllowUndefinedAsNaN);
ager@chromium.org378b34e2011-01-28 08:04:38 +00003815 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003816 }
3817
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003818 virtual Representation RequiredInputRepresentation(int index) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003819 return index == 0
3820 ? Representation::Tagged()
3821 : representation();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003822 }
3823
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003824 virtual void RepresentationChanged(Representation to) {
3825 if (!to.IsTagged()) {
3826 ASSERT(to.IsInteger32());
ager@chromium.org378b34e2011-01-28 08:04:38 +00003827 ClearAllSideEffects();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003828 SetFlag(kUseGVN);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003829 } else {
3830 SetAllSideEffects();
3831 ClearFlag(kUseGVN);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003832 }
3833 }
3834
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003835 virtual void UpdateRepresentation(Representation new_rep,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003836 HInferRepresentationPhase* h_infer,
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003837 const char* reason) {
3838 // We only generate either int32 or generic tagged bitwise operations.
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00003839 if (new_rep.IsSmi() || new_rep.IsDouble()) {
3840 new_rep = Representation::Integer32();
3841 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003842 HValue::UpdateRepresentation(new_rep, h_infer, reason);
3843 }
3844
3845 virtual void initialize_output_representation(Representation observed) {
3846 if (observed.IsDouble()) observed = Representation::Integer32();
3847 HBinaryOperation::initialize_output_representation(observed);
3848 }
3849
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003850 virtual HType CalculateInferredType();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003851
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00003852 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
mmassi@chromium.org7028c052012-06-13 11:51:58 +00003853
3854 private:
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00003855 virtual bool IsDeletable() const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003856};
3857
3858
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +00003859class HMathFloorOfDiv: public HBinaryOperation {
3860 public:
3861 HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
3862 : HBinaryOperation(context, left, right) {
3863 set_representation(Representation::Integer32());
3864 SetFlag(kUseGVN);
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00003865 SetFlag(kCanOverflow);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00003866 if (!right->IsConstant()) {
3867 SetFlag(kCanBeDivByZero);
3868 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003869 SetFlag(kAllowUndefinedAsNaN);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +00003870 }
3871
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00003872 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3873
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +00003874 virtual Representation RequiredInputRepresentation(int index) {
3875 return Representation::Integer32();
3876 }
3877
3878 DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
3879
3880 protected:
3881 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00003882
3883 private:
3884 virtual bool IsDeletable() const { return true; }
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +00003885};
3886
3887
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003888class HArithmeticBinaryOperation: public HBinaryOperation {
3889 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003890 HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
3891 : HBinaryOperation(context, left, right) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00003892 SetAllSideEffects();
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003893 SetFlag(kFlexibleRepresentation);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003894 SetFlag(kAllowUndefinedAsNaN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003895 }
3896
3897 virtual void RepresentationChanged(Representation to) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003898 if (to.IsTagged()) {
3899 SetAllSideEffects();
3900 ClearFlag(kUseGVN);
3901 } else {
ager@chromium.org378b34e2011-01-28 08:04:38 +00003902 ClearAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003903 SetFlag(kUseGVN);
3904 }
3905 }
3906
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003907 virtual HType CalculateInferredType();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003908 virtual Representation RequiredInputRepresentation(int index) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003909 return index == 0
3910 ? Representation::Tagged()
3911 : representation();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003912 }
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003913
ulan@chromium.org837a67e2013-06-11 15:39:48 +00003914 DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00003915
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00003916 private:
3917 virtual bool IsDeletable() const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003918};
3919
3920
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003921class HCompareGeneric: public HBinaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003922 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00003923 HCompareGeneric(HValue* context,
3924 HValue* left,
3925 HValue* right,
3926 Token::Value token)
3927 : HBinaryOperation(context, left, right), token_(token) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003928 ASSERT(Token::IsCompareOp(token));
3929 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00003930 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003931 }
3932
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003933 virtual Representation RequiredInputRepresentation(int index) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003934 return index == 0
3935 ? Representation::Tagged()
3936 : representation();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003937 }
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003938
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003939 Token::Value token() const { return token_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003940 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003941
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00003942 virtual HType CalculateInferredType();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003943
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003944 DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
3945
3946 private:
3947 Token::Value token_;
3948};
3949
3950
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003951class HCompareNumericAndBranch: public HTemplateControlInstruction<2, 2> {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003952 public:
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003953 HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token)
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003954 : token_(token) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003955 SetFlag(kFlexibleRepresentation);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003956 ASSERT(Token::IsCompareOp(token));
3957 SetOperandAt(0, left);
3958 SetOperandAt(1, right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003959 }
3960
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003961 HValue* left() { return OperandAt(0); }
3962 HValue* right() { return OperandAt(1); }
3963 Token::Value token() const { return token_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003964
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003965 void set_observed_input_representation(Representation left,
3966 Representation right) {
3967 observed_input_representation_[0] = left;
3968 observed_input_representation_[1] = right;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003969 }
3970
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003971 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003972
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003973 virtual Representation RequiredInputRepresentation(int index) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003974 return representation();
3975 }
3976 virtual Representation observed_input_representation(int index) {
3977 return observed_input_representation_[index];
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003978 }
3979 virtual void PrintDataTo(StringStream* stream);
3980
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00003981 virtual void AddInformativeDefinitions();
3982
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003983 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003984
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003985 private:
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00003986 Representation observed_input_representation_[2];
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003987 Token::Value token_;
3988};
3989
3990
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003991class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003992 public:
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003993 HCompareObjectEqAndBranch(HValue* left, HValue* right) {
3994 SetOperandAt(0, left);
3995 SetOperandAt(1, right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003996 }
3997
ricow@chromium.org4f693d62011-07-04 14:01:31 +00003998 HValue* left() { return OperandAt(0); }
3999 HValue* right() { return OperandAt(1); }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00004000
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004001 virtual void PrintDataTo(StringStream* stream);
4002
4003 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004004 return Representation::Tagged();
4005 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004006
danno@chromium.orgca29dd82013-04-26 11:59:48 +00004007 virtual Representation observed_input_representation(int index) {
4008 return Representation::Tagged();
4009 }
4010
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004011 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004012};
4013
4014
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004015class HCompareConstantEqAndBranch: public HUnaryControlInstruction {
whesse@chromium.org7b260152011-06-20 15:33:18 +00004016 public:
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004017 HCompareConstantEqAndBranch(HValue* left, int right, Token::Value op)
4018 : HUnaryControlInstruction(left, NULL, NULL), op_(op), right_(right) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00004019 ASSERT(op == Token::EQ_STRICT);
whesse@chromium.org7b260152011-06-20 15:33:18 +00004020 }
4021
4022 Token::Value op() const { return op_; }
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004023 HValue* left() { return value(); }
whesse@chromium.org7b260152011-06-20 15:33:18 +00004024 int right() const { return right_; }
4025
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004026 virtual Representation RequiredInputRepresentation(int index) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00004027 return Representation::Integer32();
4028 }
4029
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004030 DECLARE_CONCRETE_INSTRUCTION(CompareConstantEqAndBranch);
whesse@chromium.org7b260152011-06-20 15:33:18 +00004031
4032 private:
4033 const Token::Value op_;
4034 const int right_;
4035};
4036
4037
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004038class HIsObjectAndBranch: public HUnaryControlInstruction {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004039 public:
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004040 explicit HIsObjectAndBranch(HValue* value)
4041 : HUnaryControlInstruction(value, NULL, NULL) { }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004042
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004043 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004044 return Representation::Tagged();
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00004045 }
4046
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004047 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
4048};
4049
erikcorry0ad885c2011-11-21 13:51:57 +00004050class HIsStringAndBranch: public HUnaryControlInstruction {
4051 public:
4052 explicit HIsStringAndBranch(HValue* value)
4053 : HUnaryControlInstruction(value, NULL, NULL) { }
4054
4055 virtual Representation RequiredInputRepresentation(int index) {
4056 return Representation::Tagged();
4057 }
4058
4059 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
4060};
4061
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004062
4063class HIsSmiAndBranch: public HUnaryControlInstruction {
4064 public:
4065 explicit HIsSmiAndBranch(HValue* value)
4066 : HUnaryControlInstruction(value, NULL, NULL) { }
4067
4068 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
4069
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004070 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004071 return Representation::Tagged();
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00004072 }
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00004073
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004074 protected:
4075 virtual bool DataEquals(HValue* other) { return true; }
4076};
4077
4078
4079class HIsUndetectableAndBranch: public HUnaryControlInstruction {
4080 public:
4081 explicit HIsUndetectableAndBranch(HValue* value)
4082 : HUnaryControlInstruction(value, NULL, NULL) { }
4083
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004084 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004085 return Representation::Tagged();
4086 }
4087
4088 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
4089};
4090
4091
erikcorry0ad885c2011-11-21 13:51:57 +00004092class HStringCompareAndBranch: public HTemplateControlInstruction<2, 3> {
4093 public:
4094 HStringCompareAndBranch(HValue* context,
4095 HValue* left,
4096 HValue* right,
4097 Token::Value token)
4098 : token_(token) {
4099 ASSERT(Token::IsCompareOp(token));
4100 SetOperandAt(0, context);
4101 SetOperandAt(1, left);
4102 SetOperandAt(2, right);
4103 set_representation(Representation::Tagged());
4104 }
4105
4106 HValue* context() { return OperandAt(0); }
4107 HValue* left() { return OperandAt(1); }
4108 HValue* right() { return OperandAt(2); }
4109 Token::Value token() const { return token_; }
4110
4111 virtual void PrintDataTo(StringStream* stream);
4112
4113 virtual Representation RequiredInputRepresentation(int index) {
4114 return Representation::Tagged();
4115 }
4116
4117 Representation GetInputRepresentation() const {
4118 return Representation::Tagged();
4119 }
4120
4121 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
4122
4123 private:
4124 Token::Value token_;
4125};
4126
4127
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004128class HIsConstructCallAndBranch: public HTemplateControlInstruction<2, 0> {
4129 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004130 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004131 return Representation::None();
4132 }
4133
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004134 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00004135};
4136
4137
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004138class HHasInstanceTypeAndBranch: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004139 public:
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004140 HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4141 : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
4142 HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
4143 : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004144 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
4145 }
4146
4147 InstanceType from() { return from_; }
4148 InstanceType to() { return to_; }
4149
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004150 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004151
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004152 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004153 return Representation::Tagged();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004154 }
4155
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004156 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4157
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004158 private:
4159 InstanceType from_;
4160 InstanceType to_; // Inclusive range, not all combinations work.
4161};
4162
4163
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004164class HHasCachedArrayIndexAndBranch: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004165 public:
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004166 explicit HHasCachedArrayIndexAndBranch(HValue* value)
4167 : HUnaryControlInstruction(value, NULL, NULL) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004168
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004169 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004170 return Representation::Tagged();
4171 }
ager@chromium.org378b34e2011-01-28 08:04:38 +00004172
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004173 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004174};
4175
4176
vegorov@chromium.org3cf47312011-06-29 13:20:01 +00004177class HGetCachedArrayIndex: public HUnaryOperation {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004178 public:
vegorov@chromium.org3cf47312011-06-29 13:20:01 +00004179 explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
4180 set_representation(Representation::Tagged());
4181 SetFlag(kUseGVN);
4182 }
4183
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004184 virtual Representation RequiredInputRepresentation(int index) {
vegorov@chromium.org3cf47312011-06-29 13:20:01 +00004185 return Representation::Tagged();
4186 }
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004187
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004188 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004189
4190 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004191 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00004192
4193 private:
4194 virtual bool IsDeletable() const { return true; }
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004195};
4196
4197
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004198class HClassOfTestAndBranch: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004199 public:
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004200 HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
4201 : HUnaryControlInstruction(value, NULL, NULL),
4202 class_name_(class_name) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004203
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004204 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4205
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004206 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004207 return Representation::Tagged();
4208 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004209
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004210 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004211
4212 Handle<String> class_name() const { return class_name_; }
4213
4214 private:
4215 Handle<String> class_name_;
4216};
4217
4218
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004219class HTypeofIsAndBranch: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004220 public:
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004221 HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
4222 : HUnaryControlInstruction(value, NULL, NULL),
4223 type_literal_(type_literal) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004224
4225 Handle<String> type_literal() { return type_literal_; }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004226 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004227
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004228 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004229
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004230 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00004231 return Representation::Tagged();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004232 }
4233
4234 private:
4235 Handle<String> type_literal_;
4236};
4237
4238
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004239class HInstanceOf: public HBinaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004240 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004241 HInstanceOf(HValue* context, HValue* left, HValue* right)
4242 : HBinaryOperation(context, left, right) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004243 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00004244 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004245 }
4246
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004247 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004248 return Representation::Tagged();
4249 }
4250
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00004251 virtual HType CalculateInferredType();
4252
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004253 virtual void PrintDataTo(StringStream* stream);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00004254
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004255 DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004256};
4257
4258
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004259class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00004260 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004261 HInstanceOfKnownGlobal(HValue* context,
4262 HValue* left,
4263 Handle<JSFunction> right)
4264 : function_(right) {
4265 SetOperandAt(0, context);
4266 SetOperandAt(1, left);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00004267 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00004268 SetAllSideEffects();
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00004269 }
4270
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004271 HValue* context() { return OperandAt(0); }
4272 HValue* left() { return OperandAt(1); }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00004273 Handle<JSFunction> function() { return function_; }
4274
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004275 virtual Representation RequiredInputRepresentation(int index) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00004276 return Representation::Tagged();
4277 }
4278
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00004279 virtual HType CalculateInferredType();
4280
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004281 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00004282
4283 private:
4284 Handle<JSFunction> function_;
4285};
4286
4287
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00004288// TODO(mstarzinger): This instruction should be modeled as a load of the map
4289// field followed by a load of the instance size field once HLoadNamedField is
4290// flexible enough to accommodate byte-field loads.
4291class HInstanceSize: public HTemplateInstruction<1> {
4292 public:
4293 explicit HInstanceSize(HValue* object) {
4294 SetOperandAt(0, object);
4295 set_representation(Representation::Integer32());
4296 }
4297
4298 HValue* object() { return OperandAt(0); }
4299
4300 virtual Representation RequiredInputRepresentation(int index) {
4301 return Representation::Tagged();
4302 }
4303
4304 DECLARE_CONCRETE_INSTRUCTION(InstanceSize)
4305};
4306
4307
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004308class HPower: public HTemplateInstruction<2> {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004309 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004310 static HInstruction* New(Zone* zone, HValue* left, HValue* right);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004311
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004312 HValue* left() { return OperandAt(0); }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00004313 HValue* right() const { return OperandAt(1); }
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004314
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004315 virtual Representation RequiredInputRepresentation(int index) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004316 return index == 0
4317 ? Representation::Double()
4318 : Representation::None();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004319 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00004320 virtual Representation observed_input_representation(int index) {
4321 return RequiredInputRepresentation(index);
4322 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004323
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004324 DECLARE_CONCRETE_INSTRUCTION(Power)
ager@chromium.org378b34e2011-01-28 08:04:38 +00004325
4326 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004327 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00004328
4329 private:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004330 HPower(HValue* left, HValue* right) {
4331 SetOperandAt(0, left);
4332 SetOperandAt(1, right);
4333 set_representation(Representation::Double());
4334 SetFlag(kUseGVN);
4335 SetGVNFlag(kChangesNewSpacePromotion);
4336 }
4337
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00004338 virtual bool IsDeletable() const {
4339 return !right()->representation().IsTagged();
4340 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00004341};
4342
4343
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00004344class HRandom: public HTemplateInstruction<1> {
4345 public:
4346 explicit HRandom(HValue* global_object) {
4347 SetOperandAt(0, global_object);
4348 set_representation(Representation::Double());
4349 }
4350
4351 HValue* global_object() { return OperandAt(0); }
4352
4353 virtual Representation RequiredInputRepresentation(int index) {
4354 return Representation::Tagged();
4355 }
4356
4357 DECLARE_CONCRETE_INSTRUCTION(Random)
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00004358
4359 private:
4360 virtual bool IsDeletable() const { return true; }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00004361};
4362
4363
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004364class HAdd: public HArithmeticBinaryOperation {
4365 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004366 static HInstruction* New(Zone* zone,
4367 HValue* context,
4368 HValue* left,
4369 HValue* right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004370
4371 // Add is only commutative if two integer values are added and not if two
4372 // tagged values are added (because it might be a String concatenation).
4373 virtual bool IsCommutative() const {
4374 return !representation().IsTagged();
4375 }
4376
4377 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
4378
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004379 virtual HType CalculateInferredType();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004380
ulan@chromium.org812308e2012-02-29 15:58:45 +00004381 virtual HValue* Canonicalize();
4382
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00004383 virtual bool TryDecompose(DecompositionResult* decomposition) {
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00004384 if (left()->IsInteger32Constant()) {
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00004385 decomposition->Apply(right(), left()->GetInteger32Constant());
4386 return true;
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00004387 } else if (right()->IsInteger32Constant()) {
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00004388 decomposition->Apply(left(), right()->GetInteger32Constant());
4389 return true;
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00004390 } else {
4391 return false;
4392 }
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00004393 }
4394
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004395 DECLARE_CONCRETE_INSTRUCTION(Add)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004396
4397 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004398 virtual bool DataEquals(HValue* other) { return true; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00004399
ulan@chromium.org812308e2012-02-29 15:58:45 +00004400 virtual Range* InferRange(Zone* zone);
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004401
4402 private:
4403 HAdd(HValue* context, HValue* left, HValue* right)
4404 : HArithmeticBinaryOperation(context, left, right) {
4405 SetFlag(kCanOverflow);
4406 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004407};
4408
4409
4410class HSub: public HArithmeticBinaryOperation {
4411 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004412 static HInstruction* New(Zone* zone,
4413 HValue* context,
4414 HValue* left,
4415 HValue* right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004416
4417 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
4418
ulan@chromium.org812308e2012-02-29 15:58:45 +00004419 virtual HValue* Canonicalize();
4420
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00004421 virtual bool TryDecompose(DecompositionResult* decomposition) {
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00004422 if (right()->IsInteger32Constant()) {
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00004423 decomposition->Apply(left(), -right()->GetInteger32Constant());
4424 return true;
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00004425 } else {
4426 return false;
4427 }
4428 }
4429
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004430 DECLARE_CONCRETE_INSTRUCTION(Sub)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004431
4432 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004433 virtual bool DataEquals(HValue* other) { return true; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00004434
ulan@chromium.org812308e2012-02-29 15:58:45 +00004435 virtual Range* InferRange(Zone* zone);
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004436
4437 private:
4438 HSub(HValue* context, HValue* left, HValue* right)
4439 : HArithmeticBinaryOperation(context, left, right) {
4440 SetFlag(kCanOverflow);
4441 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004442};
4443
4444
4445class HMul: public HArithmeticBinaryOperation {
4446 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004447 static HInstruction* New(Zone* zone,
4448 HValue* context,
4449 HValue* left,
4450 HValue* right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004451
danno@chromium.orgca29dd82013-04-26 11:59:48 +00004452 static HInstruction* NewImul(Zone* zone,
4453 HValue* context,
4454 HValue* left,
4455 HValue* right) {
4456 HMul* mul = new(zone) HMul(context, left, right);
4457 // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4458 mul->AssumeRepresentation(Representation::Integer32());
4459 mul->ClearFlag(HValue::kCanOverflow);
4460 return mul;
4461 }
4462
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004463 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
4464
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00004465 virtual HValue* Canonicalize();
4466
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004467 // Only commutative if it is certain that not two objects are multiplicated.
4468 virtual bool IsCommutative() const {
4469 return !representation().IsTagged();
4470 }
4471
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004472 DECLARE_CONCRETE_INSTRUCTION(Mul)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004473
4474 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004475 virtual bool DataEquals(HValue* other) { return true; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00004476
ulan@chromium.org812308e2012-02-29 15:58:45 +00004477 virtual Range* InferRange(Zone* zone);
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004478
4479 private:
4480 HMul(HValue* context, HValue* left, HValue* right)
4481 : HArithmeticBinaryOperation(context, left, right) {
4482 SetFlag(kCanOverflow);
4483 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004484};
4485
4486
4487class HMod: public HArithmeticBinaryOperation {
4488 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004489 static HInstruction* New(Zone* zone,
4490 HValue* context,
4491 HValue* left,
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00004492 HValue* right,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004493 Maybe<int> fixed_right_arg);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00004494
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004495 Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004496
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00004497 bool HasPowerOf2Divisor() {
4498 if (right()->IsConstant() &&
4499 HConstant::cast(right())->HasInteger32Value()) {
4500 int32_t value = HConstant::cast(right())->Integer32Value();
4501 return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
4502 }
4503
4504 return false;
4505 }
4506
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004507 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
4508
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004509 virtual HValue* Canonicalize();
4510
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004511 DECLARE_CONCRETE_INSTRUCTION(Mod)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004512
4513 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004514 virtual bool DataEquals(HValue* other) { return true; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00004515
ulan@chromium.org812308e2012-02-29 15:58:45 +00004516 virtual Range* InferRange(Zone* zone);
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004517
4518 private:
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00004519 HMod(HValue* context,
4520 HValue* left,
4521 HValue* right,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004522 Maybe<int> fixed_right_arg)
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00004523 : HArithmeticBinaryOperation(context, left, right),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004524 fixed_right_arg_(fixed_right_arg) {
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004525 SetFlag(kCanBeDivByZero);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004526 SetFlag(kCanOverflow);
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004527 }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00004528
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004529 const Maybe<int> fixed_right_arg_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004530};
4531
4532
4533class HDiv: public HArithmeticBinaryOperation {
4534 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004535 static HInstruction* New(Zone* zone,
4536 HValue* context,
4537 HValue* left,
4538 HValue* right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004539
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +00004540 bool HasPowerOf2Divisor() {
ulan@chromium.org837a67e2013-06-11 15:39:48 +00004541 if (right()->IsInteger32Constant()) {
4542 int32_t value = right()->GetInteger32Constant();
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +00004543 return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
4544 }
4545
4546 return false;
4547 }
4548
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004549 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
4550
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004551 virtual HValue* Canonicalize();
4552
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004553 DECLARE_CONCRETE_INSTRUCTION(Div)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004554
4555 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004556 virtual bool DataEquals(HValue* other) { return true; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00004557
ulan@chromium.org812308e2012-02-29 15:58:45 +00004558 virtual Range* InferRange(Zone* zone);
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004559
4560 private:
4561 HDiv(HValue* context, HValue* left, HValue* right)
4562 : HArithmeticBinaryOperation(context, left, right) {
4563 SetFlag(kCanBeDivByZero);
4564 SetFlag(kCanOverflow);
4565 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004566};
4567
4568
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00004569class HMathMinMax: public HArithmeticBinaryOperation {
4570 public:
4571 enum Operation { kMathMin, kMathMax };
4572
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004573 static HInstruction* New(Zone* zone,
4574 HValue* context,
4575 HValue* left,
4576 HValue* right,
4577 Operation op);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00004578
4579 virtual Representation RequiredInputRepresentation(int index) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00004580 return index == 0 ? Representation::Tagged()
4581 : representation();
4582 }
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00004583
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00004584 virtual Representation observed_input_representation(int index) {
4585 return RequiredInputRepresentation(index);
4586 }
4587
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004588 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +00004589
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00004590 virtual Representation RepresentationFromInputs() {
4591 Representation left_rep = left()->representation();
4592 Representation right_rep = right()->representation();
4593 if ((left_rep.IsNone() || left_rep.IsInteger32()) &&
4594 (right_rep.IsNone() || right_rep.IsInteger32())) {
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00004595 return Representation::Integer32();
4596 }
4597 return Representation::Double();
4598 }
4599
4600 virtual bool IsCommutative() const { return true; }
4601
4602 Operation operation() { return operation_; }
4603
4604 DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
4605
4606 protected:
4607 virtual bool DataEquals(HValue* other) {
4608 return other->IsMathMinMax() &&
4609 HMathMinMax::cast(other)->operation_ == operation_;
4610 }
4611
4612 virtual Range* InferRange(Zone* zone);
4613
4614 private:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004615 HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
4616 : HArithmeticBinaryOperation(context, left, right),
4617 operation_(op) { }
4618
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00004619 Operation operation_;
4620};
4621
4622
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00004623class HBitwise: public HBitwiseBinaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004624 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004625 static HInstruction* New(Zone* zone,
4626 Token::Value op,
4627 HValue* context,
4628 HValue* left,
4629 HValue* right);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00004630
4631 Token::Value op() const { return op_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004632
4633 virtual bool IsCommutative() const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004634
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00004635 virtual HValue* Canonicalize();
4636
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00004637 virtual void PrintDataTo(StringStream* stream);
4638
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00004639 DECLARE_CONCRETE_INSTRUCTION(Bitwise)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004640
4641 protected:
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00004642 virtual bool DataEquals(HValue* other) {
4643 return op() == HBitwise::cast(other)->op();
4644 }
ager@chromium.org378b34e2011-01-28 08:04:38 +00004645
ulan@chromium.org812308e2012-02-29 15:58:45 +00004646 virtual Range* InferRange(Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004647
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00004648 private:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004649 HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right)
4650 : HBitwiseBinaryOperation(context, left, right), op_(op) {
4651 ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
4652 }
4653
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00004654 Token::Value op_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004655};
4656
4657
4658class HShl: public HBitwiseBinaryOperation {
4659 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004660 static HInstruction* New(Zone* zone,
4661 HValue* context,
4662 HValue* left,
4663 HValue* right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004664
ulan@chromium.org812308e2012-02-29 15:58:45 +00004665 virtual Range* InferRange(Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004666
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004667 DECLARE_CONCRETE_INSTRUCTION(Shl)
ager@chromium.org378b34e2011-01-28 08:04:38 +00004668
4669 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004670 virtual bool DataEquals(HValue* other) { return true; }
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004671
4672 private:
4673 HShl(HValue* context, HValue* left, HValue* right)
4674 : HBitwiseBinaryOperation(context, left, right) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004675};
4676
4677
4678class HShr: public HBitwiseBinaryOperation {
4679 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004680 static HInstruction* New(Zone* zone,
4681 HValue* context,
4682 HValue* left,
4683 HValue* right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004684
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00004685 virtual bool TryDecompose(DecompositionResult* decomposition) {
4686 if (right()->IsInteger32Constant()) {
4687 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
4688 // This is intended to look for HAdd and HSub, to handle compounds
4689 // like ((base + offset) >> scale) with one single decomposition.
4690 left()->TryDecompose(decomposition);
4691 return true;
4692 }
4693 }
4694 return false;
4695 }
4696
ulan@chromium.org812308e2012-02-29 15:58:45 +00004697 virtual Range* InferRange(Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004698
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004699 DECLARE_CONCRETE_INSTRUCTION(Shr)
ager@chromium.org378b34e2011-01-28 08:04:38 +00004700
4701 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004702 virtual bool DataEquals(HValue* other) { return true; }
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004703
4704 private:
4705 HShr(HValue* context, HValue* left, HValue* right)
4706 : HBitwiseBinaryOperation(context, left, right) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004707};
4708
4709
4710class HSar: public HBitwiseBinaryOperation {
4711 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004712 static HInstruction* New(Zone* zone,
4713 HValue* context,
4714 HValue* left,
4715 HValue* right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004716
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00004717 virtual bool TryDecompose(DecompositionResult* decomposition) {
4718 if (right()->IsInteger32Constant()) {
4719 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
4720 // This is intended to look for HAdd and HSub, to handle compounds
4721 // like ((base + offset) >> scale) with one single decomposition.
4722 left()->TryDecompose(decomposition);
4723 return true;
4724 }
4725 }
4726 return false;
4727 }
4728
ulan@chromium.org812308e2012-02-29 15:58:45 +00004729 virtual Range* InferRange(Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004730
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004731 DECLARE_CONCRETE_INSTRUCTION(Sar)
ager@chromium.org378b34e2011-01-28 08:04:38 +00004732
4733 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004734 virtual bool DataEquals(HValue* other) { return true; }
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004735
4736 private:
4737 HSar(HValue* context, HValue* left, HValue* right)
4738 : HBitwiseBinaryOperation(context, left, right) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004739};
4740
4741
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00004742class HRor: public HBitwiseBinaryOperation {
4743 public:
4744 HRor(HValue* context, HValue* left, HValue* right)
ulan@chromium.org2e04b582013-02-21 14:06:02 +00004745 : HBitwiseBinaryOperation(context, left, right) {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00004746 ChangeRepresentation(Representation::Integer32());
4747 }
4748
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00004749 DECLARE_CONCRETE_INSTRUCTION(Ror)
4750
4751 protected:
4752 virtual bool DataEquals(HValue* other) { return true; }
4753};
4754
4755
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004756class HOsrEntry: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004757 public:
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00004758 explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00004759 SetGVNFlag(kChangesOsrEntries);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00004760 SetGVNFlag(kChangesNewSpacePromotion);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004761 }
4762
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00004763 BailoutId ast_id() const { return ast_id_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004764
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004765 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004766 return Representation::None();
4767 }
4768
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004769 DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004770
4771 private:
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00004772 BailoutId ast_id_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004773};
4774
4775
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004776class HParameter: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004777 public:
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00004778 enum ParameterKind {
4779 STACK_PARAMETER,
4780 REGISTER_PARAMETER
4781 };
4782
4783 explicit HParameter(unsigned index,
4784 ParameterKind kind = STACK_PARAMETER)
4785 : index_(index),
4786 kind_(kind) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004787 set_representation(Representation::Tagged());
4788 }
4789
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00004790 explicit HParameter(unsigned index,
4791 ParameterKind kind,
4792 Representation r)
4793 : index_(index),
4794 kind_(kind) {
4795 set_representation(r);
4796 }
4797
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004798 unsigned index() const { return index_; }
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00004799 ParameterKind kind() const { return kind_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004800
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004801 virtual void PrintDataTo(StringStream* stream);
4802
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004803 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004804 return Representation::None();
4805 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004806
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004807 DECLARE_CONCRETE_INSTRUCTION(Parameter)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004808
4809 private:
4810 unsigned index_;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00004811 ParameterKind kind_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004812};
4813
4814
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00004815class HCallStub: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004816 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00004817 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
4818 : HUnaryCall(context, argument_count),
4819 major_key_(major_key),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004820 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004821 }
4822
4823 CodeStub::Major major_key() { return major_key_; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00004824
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004825 HValue* context() { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004826
4827 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
4828 transcendental_type_ = transcendental_type;
4829 }
4830 TranscendentalCache::Type transcendental_type() {
4831 return transcendental_type_;
4832 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00004833
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004834 virtual void PrintDataTo(StringStream* stream);
4835
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004836 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004837 return Representation::Tagged();
4838 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004839
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004840 DECLARE_CONCRETE_INSTRUCTION(CallStub)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004841
4842 private:
4843 CodeStub::Major major_key_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004844 TranscendentalCache::Type transcendental_type_;
4845};
4846
4847
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004848class HUnknownOSRValue: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004849 public:
rossberg@chromium.org2c067b12012-03-19 11:01:52 +00004850 HUnknownOSRValue()
4851 : incoming_value_(NULL) {
4852 set_representation(Representation::Tagged());
4853 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004854
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004855 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004856 return Representation::None();
4857 }
4858
rossberg@chromium.org2c067b12012-03-19 11:01:52 +00004859 void set_incoming_value(HPhi* value) {
4860 incoming_value_ = value;
4861 }
4862
4863 HPhi* incoming_value() {
4864 return incoming_value_;
4865 }
4866
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00004867 virtual Representation KnownOptimalRepresentation() {
4868 if (incoming_value_ == NULL) return Representation::None();
4869 return incoming_value_->KnownOptimalRepresentation();
4870 }
4871
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004872 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
rossberg@chromium.org2c067b12012-03-19 11:01:52 +00004873
4874 private:
4875 HPhi* incoming_value_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004876};
4877
4878
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00004879class HLoadGlobalCell: public HTemplateInstruction<0> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004880 public:
danno@chromium.org41728482013-06-12 22:31:22 +00004881 HLoadGlobalCell(Handle<Cell> cell, PropertyDetails details)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00004882 : cell_(cell), details_(details), unique_id_() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004883 set_representation(Representation::Tagged());
4884 SetFlag(kUseGVN);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00004885 SetGVNFlag(kDependsOnGlobalVars);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004886 }
4887
danno@chromium.org41728482013-06-12 22:31:22 +00004888 Handle<Cell> cell() const { return cell_; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00004889 bool RequiresHoleCheck() const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004890
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004891 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004892
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004893 virtual intptr_t Hashcode() {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00004894 return unique_id_.Hashcode();
4895 }
4896
4897 virtual void FinalizeUniqueValueId() {
4898 unique_id_ = UniqueValueId(cell_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004899 }
4900
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004901 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004902 return Representation::None();
4903 }
4904
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004905 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004906
4907 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00004908 virtual bool DataEquals(HValue* other) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00004909 HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00004910 return unique_id_ == b->unique_id_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004911 }
4912
4913 private:
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00004914 virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
4915
danno@chromium.org41728482013-06-12 22:31:22 +00004916 Handle<Cell> cell_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004917 PropertyDetails details_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00004918 UniqueValueId unique_id_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00004919};
4920
4921
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004922class HLoadGlobalGeneric: public HTemplateInstruction<2> {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00004923 public:
4924 HLoadGlobalGeneric(HValue* context,
4925 HValue* global_object,
4926 Handle<Object> name,
4927 bool for_typeof)
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004928 : name_(name),
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00004929 for_typeof_(for_typeof) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00004930 SetOperandAt(0, context);
4931 SetOperandAt(1, global_object);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00004932 set_representation(Representation::Tagged());
4933 SetAllSideEffects();
4934 }
4935
4936 HValue* context() { return OperandAt(0); }
4937 HValue* global_object() { return OperandAt(1); }
4938 Handle<Object> name() const { return name_; }
4939 bool for_typeof() const { return for_typeof_; }
4940
4941 virtual void PrintDataTo(StringStream* stream);
4942
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00004943 virtual Representation RequiredInputRepresentation(int index) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00004944 return Representation::Tagged();
4945 }
4946
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00004947 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00004948
4949 private:
4950 Handle<Object> name_;
4951 bool for_typeof_;
4952};
4953
4954
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004955class HAllocateObject: public HTemplateInstruction<1> {
4956 public:
4957 HAllocateObject(HValue* context, Handle<JSFunction> constructor)
4958 : constructor_(constructor) {
4959 SetOperandAt(0, context);
4960 set_representation(Representation::Tagged());
4961 SetGVNFlag(kChangesNewSpacePromotion);
4962 constructor_initial_map_ = constructor->has_initial_map()
4963 ? Handle<Map>(constructor->initial_map())
4964 : Handle<Map>::null();
4965 // If slack tracking finished, the instance size and property counts
4966 // remain unchanged so that we can allocate memory for the object.
4967 ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
4968 }
4969
4970 // Maximum instance size for which allocations will be inlined.
4971 static const int kMaxSize = 64 * kPointerSize;
4972
4973 HValue* context() { return OperandAt(0); }
4974 Handle<JSFunction> constructor() { return constructor_; }
4975 Handle<Map> constructor_initial_map() { return constructor_initial_map_; }
4976
4977 virtual Representation RequiredInputRepresentation(int index) {
4978 return Representation::Tagged();
4979 }
danno@chromium.org169691d2013-07-15 08:01:13 +00004980
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004981 virtual Handle<Map> GetMonomorphicJSObjectMap() {
4982 ASSERT(!constructor_initial_map_.is_null());
4983 return constructor_initial_map_;
4984 }
danno@chromium.org169691d2013-07-15 08:01:13 +00004985
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004986 virtual HType CalculateInferredType();
4987
4988 DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
4989
4990 private:
4991 // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
4992 // virtual bool IsDeletable() const { return true; }
4993
4994 Handle<JSFunction> constructor_;
4995 Handle<Map> constructor_initial_map_;
4996};
4997
4998
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00004999class HAllocate: public HTemplateInstruction<2> {
5000 public:
5001 enum Flags {
5002 CAN_ALLOCATE_IN_NEW_SPACE = 1 << 0,
5003 CAN_ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
5004 CAN_ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
5005 ALLOCATE_DOUBLE_ALIGNED = 1 << 3
5006 };
5007
5008 HAllocate(HValue* context, HValue* size, HType type, Flags flags)
5009 : type_(type),
5010 flags_(flags) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005011 SetOperandAt(0, context);
5012 SetOperandAt(1, size);
5013 set_representation(Representation::Tagged());
danno@chromium.org169691d2013-07-15 08:01:13 +00005014 SetFlag(kTrackSideEffectDominators);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005015 SetGVNFlag(kChangesNewSpacePromotion);
danno@chromium.org169691d2013-07-15 08:01:13 +00005016 SetGVNFlag(kDependsOnNewSpacePromotion);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005017 }
5018
danno@chromium.orgca29dd82013-04-26 11:59:48 +00005019 static Flags DefaultFlags() {
5020 return CAN_ALLOCATE_IN_NEW_SPACE;
5021 }
5022
5023 static Flags DefaultFlags(ElementsKind kind) {
5024 Flags flags = CAN_ALLOCATE_IN_NEW_SPACE;
5025 if (IsFastDoubleElementsKind(kind)) {
5026 flags = static_cast<HAllocate::Flags>(
5027 flags | HAllocate::ALLOCATE_DOUBLE_ALIGNED);
5028 }
5029 return flags;
5030 }
5031
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005032 HValue* context() { return OperandAt(0); }
5033 HValue* size() { return OperandAt(1); }
danno@chromium.org169691d2013-07-15 08:01:13 +00005034 HType type() { return type_; }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005035
5036 virtual Representation RequiredInputRepresentation(int index) {
5037 if (index == 0) {
5038 return Representation::Tagged();
5039 } else {
5040 return Representation::Integer32();
5041 }
5042 }
5043
5044 virtual HType CalculateInferredType();
5045
5046 bool CanAllocateInNewSpace() const {
5047 return (flags_ & CAN_ALLOCATE_IN_NEW_SPACE) != 0;
5048 }
5049
5050 bool CanAllocateInOldDataSpace() const {
5051 return (flags_ & CAN_ALLOCATE_IN_OLD_DATA_SPACE) != 0;
5052 }
5053
5054 bool CanAllocateInOldPointerSpace() const {
5055 return (flags_ & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
5056 }
5057
5058 bool CanAllocateInOldSpace() const {
5059 return CanAllocateInOldDataSpace() ||
5060 CanAllocateInOldPointerSpace();
5061 }
5062
5063 bool GuaranteedInNewSpace() const {
5064 return CanAllocateInNewSpace() && !CanAllocateInOldSpace();
5065 }
5066
5067 bool MustAllocateDoubleAligned() const {
5068 return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
5069 }
5070
danno@chromium.org169691d2013-07-15 08:01:13 +00005071 void UpdateSize(HValue* size) {
5072 SetOperandAt(1, size);
5073 }
5074
5075 virtual void HandleSideEffectDominator(GVNFlag side_effect,
5076 HValue* dominator);
5077
ulan@chromium.org750145a2013-03-07 15:14:13 +00005078 virtual void PrintDataTo(StringStream* stream);
5079
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005080 DECLARE_CONCRETE_INSTRUCTION(Allocate)
5081
5082 private:
5083 HType type_;
5084 Flags flags_;
5085};
5086
5087
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005088class HInnerAllocatedObject: public HTemplateInstruction<1> {
5089 public:
danno@chromium.org169691d2013-07-15 08:01:13 +00005090 HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged())
5091 : offset_(offset),
5092 type_(type) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005093 ASSERT(value->IsAllocate());
5094 SetOperandAt(0, value);
5095 set_representation(Representation::Tagged());
5096 }
5097
5098 HValue* base_object() { return OperandAt(0); }
5099 int offset() { return offset_; }
5100
5101 virtual Representation RequiredInputRepresentation(int index) {
5102 return Representation::Tagged();
5103 }
5104
danno@chromium.org169691d2013-07-15 08:01:13 +00005105 virtual HType CalculateInferredType() { return type_; }
5106
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005107 virtual void PrintDataTo(StringStream* stream);
5108
5109 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
5110
5111 private:
5112 int offset_;
danno@chromium.org169691d2013-07-15 08:01:13 +00005113 HType type_;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005114};
5115
5116
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00005117inline bool StoringValueNeedsWriteBarrier(HValue* value) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00005118 return !value->type().IsBoolean()
5119 && !value->type().IsSmi()
5120 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
5121}
5122
5123
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00005124inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
5125 HValue* new_space_dominator) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005126 if (object->IsInnerAllocatedObject()) {
5127 return ReceiverObjectNeedsWriteBarrier(
5128 HInnerAllocatedObject::cast(object)->base_object(),
5129 new_space_dominator);
5130 }
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005131 if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
5132 return false;
5133 }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005134 if (object != new_space_dominator) return true;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005135 if (object->IsAllocateObject()) return false;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005136 if (object->IsAllocate()) {
5137 return !HAllocate::cast(object)->GuaranteedInNewSpace();
5138 }
5139 return true;
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00005140}
5141
5142
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00005143class HStoreGlobalCell: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005144 public:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00005145 HStoreGlobalCell(HValue* value,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00005146 Handle<PropertyCell> cell,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005147 PropertyDetails details)
ager@chromium.org378b34e2011-01-28 08:04:38 +00005148 : HUnaryOperation(value),
5149 cell_(cell),
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005150 details_(details) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00005151 SetGVNFlag(kChangesGlobalVars);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005152 }
5153
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00005154 Handle<PropertyCell> cell() const { return cell_; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005155 bool RequiresHoleCheck() {
5156 return !details_.IsDontDelete() || details_.IsReadOnly();
5157 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00005158 bool NeedsWriteBarrier() {
5159 return StoringValueNeedsWriteBarrier(value());
5160 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005161
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005162 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005163 return Representation::Tagged();
5164 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005165 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005166
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005167 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005168
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005169 private:
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00005170 Handle<PropertyCell> cell_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005171 PropertyDetails details_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005172};
5173
5174
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00005175class HStoreGlobalGeneric: public HTemplateInstruction<3> {
5176 public:
5177 HStoreGlobalGeneric(HValue* context,
5178 HValue* global_object,
5179 Handle<Object> name,
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00005180 HValue* value,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00005181 StrictModeFlag strict_mode_flag)
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00005182 : name_(name),
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00005183 strict_mode_flag_(strict_mode_flag) {
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00005184 SetOperandAt(0, context);
5185 SetOperandAt(1, global_object);
5186 SetOperandAt(2, value);
5187 set_representation(Representation::Tagged());
5188 SetAllSideEffects();
5189 }
5190
5191 HValue* context() { return OperandAt(0); }
5192 HValue* global_object() { return OperandAt(1); }
5193 Handle<Object> name() const { return name_; }
5194 HValue* value() { return OperandAt(2); }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00005195 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00005196
5197 virtual void PrintDataTo(StringStream* stream);
5198
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005199 virtual Representation RequiredInputRepresentation(int index) {
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00005200 return Representation::Tagged();
5201 }
5202
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005203 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00005204
5205 private:
5206 Handle<Object> name_;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00005207 StrictModeFlag strict_mode_flag_;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00005208};
5209
5210
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005211class HLoadContextSlot: public HUnaryOperation {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005212 public:
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005213 enum Mode {
5214 // Perform a normal load of the context slot without checking its value.
ricow@chromium.org7ad65222011-12-19 12:13:11 +00005215 kNoCheck,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005216 // Load and check the value of the context slot. Deoptimize if it's the
5217 // hole value. This is used for checking for loading of uninitialized
5218 // harmony bindings where we deoptimize into full-codegen generated code
5219 // which will subsequently throw a reference error.
ricow@chromium.org7ad65222011-12-19 12:13:11 +00005220 kCheckDeoptimize,
5221 // Load and check the value of the context slot. Return undefined if it's
5222 // the hole value. This is used for non-harmony const assignments
5223 kCheckReturnUndefined
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005224 };
5225
5226 HLoadContextSlot(HValue* context, Variable* var)
5227 : HUnaryOperation(context), slot_index_(var->index()) {
5228 ASSERT(var->IsContextSlot());
ricow@chromium.org7ad65222011-12-19 12:13:11 +00005229 switch (var->mode()) {
5230 case LET:
5231 case CONST_HARMONY:
5232 mode_ = kCheckDeoptimize;
5233 break;
5234 case CONST:
5235 mode_ = kCheckReturnUndefined;
5236 break;
5237 default:
5238 mode_ = kNoCheck;
5239 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005240 set_representation(Representation::Tagged());
5241 SetFlag(kUseGVN);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00005242 SetGVNFlag(kDependsOnContextSlots);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005243 }
5244
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005245 int slot_index() const { return slot_index_; }
ricow@chromium.org7ad65222011-12-19 12:13:11 +00005246 Mode mode() const { return mode_; }
5247
5248 bool DeoptimizesOnHole() {
5249 return mode_ == kCheckDeoptimize;
5250 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005251
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00005252 bool RequiresHoleCheck() const {
ricow@chromium.org7ad65222011-12-19 12:13:11 +00005253 return mode_ != kNoCheck;
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005254 }
5255
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005256 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005257 return Representation::Tagged();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005258 }
5259
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005260 virtual void PrintDataTo(StringStream* stream);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005261
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005262 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005263
5264 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005265 virtual bool DataEquals(HValue* other) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005266 HLoadContextSlot* b = HLoadContextSlot::cast(other);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005267 return (slot_index() == b->slot_index());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005268 }
5269
5270 private:
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00005271 virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
5272
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005273 int slot_index_;
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005274 Mode mode_;
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005275};
5276
5277
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005278class HStoreContextSlot: public HTemplateInstruction<2> {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005279 public:
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005280 enum Mode {
5281 // Perform a normal store to the context slot without checking its previous
5282 // value.
ricow@chromium.org7ad65222011-12-19 12:13:11 +00005283 kNoCheck,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005284 // Check the previous value of the context slot and deoptimize if it's the
5285 // hole value. This is used for checking for assignments to uninitialized
5286 // harmony bindings where we deoptimize into full-codegen generated code
5287 // which will subsequently throw a reference error.
ricow@chromium.org7ad65222011-12-19 12:13:11 +00005288 kCheckDeoptimize,
5289 // Check the previous value and ignore assignment if it isn't a hole value
5290 kCheckIgnoreAssignment
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005291 };
5292
5293 HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5294 : slot_index_(slot_index), mode_(mode) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005295 SetOperandAt(0, context);
5296 SetOperandAt(1, value);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00005297 SetGVNFlag(kChangesContextSlots);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005298 }
5299
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005300 HValue* context() { return OperandAt(0); }
5301 HValue* value() { return OperandAt(1); }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005302 int slot_index() const { return slot_index_; }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005303 Mode mode() const { return mode_; }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005304
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005305 bool NeedsWriteBarrier() {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005306 return StoringValueNeedsWriteBarrier(value());
5307 }
5308
ricow@chromium.org7ad65222011-12-19 12:13:11 +00005309 bool DeoptimizesOnHole() {
5310 return mode_ == kCheckDeoptimize;
5311 }
5312
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005313 bool RequiresHoleCheck() {
ricow@chromium.org7ad65222011-12-19 12:13:11 +00005314 return mode_ != kNoCheck;
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005315 }
5316
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005317 virtual Representation RequiredInputRepresentation(int index) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005318 return Representation::Tagged();
5319 }
5320
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005321 virtual void PrintDataTo(StringStream* stream);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005322
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005323 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005324
5325 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005326 int slot_index_;
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00005327 Mode mode_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00005328};
5329
5330
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005331// Represents an access to a portion of an object, such as the map pointer,
5332// array elements pointer, etc, but not accesses to array elements themselves.
5333class HObjectAccess {
5334 public:
5335 inline bool IsInobject() const {
5336 return portion() != kBackingStore;
5337 }
5338
5339 inline int offset() const {
5340 return OffsetField::decode(value_);
5341 }
5342
5343 inline Handle<String> name() const {
5344 return name_;
5345 }
5346
5347 static HObjectAccess ForHeapNumberValue() {
5348 return HObjectAccess(kDouble, HeapNumber::kValueOffset);
5349 }
5350
5351 static HObjectAccess ForElementsPointer() {
5352 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5353 }
5354
5355 static HObjectAccess ForArrayLength() {
5356 return HObjectAccess(kArrayLengths, JSArray::kLengthOffset);
5357 }
5358
danno@chromium.orgbee51992013-07-10 14:57:15 +00005359 static HObjectAccess ForAllocationSiteTransitionInfo() {
5360 return HObjectAccess(kInobject, AllocationSite::kTransitionInfoOffset);
5361 }
5362
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005363 static HObjectAccess ForFixedArrayLength() {
5364 return HObjectAccess(kArrayLengths, FixedArray::kLengthOffset);
5365 }
5366
5367 static HObjectAccess ForPropertiesPointer() {
5368 return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
5369 }
5370
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00005371 static HObjectAccess ForPrototypeOrInitialMap() {
5372 return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
5373 }
5374
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005375 static HObjectAccess ForMap() {
5376 return HObjectAccess(kMaps, JSObject::kMapOffset);
5377 }
5378
danno@chromium.orgbee51992013-07-10 14:57:15 +00005379 static HObjectAccess ForPropertyCellValue() {
5380 return HObjectAccess(kInobject, PropertyCell::kValueOffset);
5381 }
5382
5383 static HObjectAccess ForCellValue() {
5384 return HObjectAccess(kInobject, Cell::kValueOffset);
5385 }
5386
5387 static HObjectAccess ForAllocationSiteInfoSite() {
5388 return HObjectAccess(kInobject, AllocationSiteInfo::kAllocationSiteOffset);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005389 }
5390
5391 // Create an access to an offset in a fixed array header.
5392 static HObjectAccess ForFixedArrayHeader(int offset);
5393
5394 // Create an access to an in-object property in a JSObject.
5395 static HObjectAccess ForJSObjectOffset(int offset);
5396
5397 // Create an access to an in-object property in a JSArray.
5398 static HObjectAccess ForJSArrayOffset(int offset);
5399
5400 // Create an access to the backing store of an object.
5401 static HObjectAccess ForBackingStoreOffset(int offset);
5402
5403 // Create an access to a resolved field (in-object or backing store).
5404 static HObjectAccess ForField(Handle<Map> map,
5405 LookupResult *lookup, Handle<String> name = Handle<String>::null());
5406
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005407 // Create an access for the payload of a Cell or JSGlobalPropertyCell.
5408 static HObjectAccess ForCellPayload(Isolate* isolate);
5409
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005410 void PrintTo(StringStream* stream);
5411
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00005412 inline bool Equals(HObjectAccess that) const {
5413 return value_ == that.value_; // portion and offset must match
5414 }
5415
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005416 protected:
5417 void SetGVNFlags(HValue *instr, bool is_store);
5418
5419 private:
5420 // internal use only; different parts of an object or array
5421 enum Portion {
5422 kMaps, // map of an object
5423 kArrayLengths, // the length of an array
5424 kElementsPointer, // elements pointer
5425 kBackingStore, // some field in the backing store
5426 kDouble, // some double field
5427 kInobject // some other in-object field
5428 };
5429
5430 HObjectAccess(Portion portion, int offset,
5431 Handle<String> name = Handle<String>::null())
5432 : value_(PortionField::encode(portion) | OffsetField::encode(offset)),
5433 name_(name) {
5434 ASSERT(this->offset() == offset); // offset should decode correctly
5435 ASSERT(this->portion() == portion); // portion should decode correctly
5436 }
5437
5438 class PortionField : public BitField<Portion, 0, 3> {};
5439 class OffsetField : public BitField<int, 3, 29> {};
5440
5441 uint32_t value_; // encodes both portion and offset
5442 Handle<String> name_;
5443
5444 friend class HLoadNamedField;
5445 friend class HStoreNamedField;
5446
5447 inline Portion portion() const {
5448 return PortionField::decode(value_);
5449 }
5450};
5451
5452
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00005453class HLoadNamedField: public HTemplateInstruction<2> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005454 public:
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005455 HLoadNamedField(HValue* object,
5456 HObjectAccess access,
5457 HValue* typecheck = NULL,
5458 Representation field_representation
5459 = Representation::Tagged())
5460 : access_(access),
5461 field_representation_(field_representation) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00005462 ASSERT(object != NULL);
5463 SetOperandAt(0, object);
5464 SetOperandAt(1, typecheck != NULL ? typecheck : object);
5465
danno@chromium.orgf005df62013-04-30 16:36:45 +00005466 if (FLAG_track_fields && field_representation.IsSmi()) {
5467 set_type(HType::Smi());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005468 set_representation(field_representation);
danno@chromium.orgf005df62013-04-30 16:36:45 +00005469 } else if (FLAG_track_double_fields && field_representation.IsDouble()) {
5470 set_representation(field_representation);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005471 } else if (FLAG_track_heap_object_fields &&
5472 field_representation.IsHeapObject()) {
5473 set_type(HType::NonPrimitive());
5474 set_representation(Representation::Tagged());
danno@chromium.orgf005df62013-04-30 16:36:45 +00005475 } else {
5476 set_representation(Representation::Tagged());
5477 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005478 access.SetGVNFlags(this, false);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00005479 }
5480
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005481 HValue* object() { return OperandAt(0); }
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00005482 HValue* typecheck() {
5483 ASSERT(HasTypeCheck());
5484 return OperandAt(1);
5485 }
5486
5487 bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005488 HObjectAccess access() const { return access_; }
danno@chromium.orgf005df62013-04-30 16:36:45 +00005489 Representation field_representation() const { return representation_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005490
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005491 virtual bool HasEscapingOperandAt(int index) { return false; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005492 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005493 return Representation::Tagged();
5494 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005495 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005496
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005497 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005498
5499 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005500 virtual bool DataEquals(HValue* other) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005501 HLoadNamedField* b = HLoadNamedField::cast(other);
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00005502 return access_.Equals(b->access_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005503 }
5504
5505 private:
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00005506 virtual bool IsDeletable() const { return true; }
5507
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005508 HObjectAccess access_;
danno@chromium.orgf005df62013-04-30 16:36:45 +00005509 Representation field_representation_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005510};
5511
5512
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005513class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00005514 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005515 HLoadNamedFieldPolymorphic(HValue* context,
5516 HValue* object,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00005517 SmallMapList* types,
mmassi@chromium.org7028c052012-06-13 11:51:58 +00005518 Handle<String> name,
5519 Zone* zone);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00005520
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005521 HValue* context() { return OperandAt(0); }
5522 HValue* object() { return OperandAt(1); }
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00005523 SmallMapList* types() { return &types_; }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00005524 Handle<String> name() { return name_; }
5525 bool need_generic() { return need_generic_; }
5526
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005527 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00005528 return Representation::Tagged();
5529 }
5530
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00005531 virtual void PrintDataTo(StringStream* stream);
5532
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005533 DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00005534
5535 static const int kMaxLoadPolymorphism = 4;
5536
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00005537 virtual void FinalizeUniqueValueId();
5538
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00005539 protected:
5540 virtual bool DataEquals(HValue* value);
5541
5542 private:
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00005543 SmallMapList types_;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00005544 Handle<String> name_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00005545 ZoneList<UniqueValueId> types_unique_ids_;
5546 UniqueValueId name_unique_id_;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00005547 bool need_generic_;
5548};
5549
5550
5551
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005552class HLoadNamedGeneric: public HTemplateInstruction<2> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005553 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00005554 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005555 : name_(name) {
5556 SetOperandAt(0, context);
5557 SetOperandAt(1, object);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005558 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00005559 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005560 }
5561
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005562 HValue* context() { return OperandAt(0); }
5563 HValue* object() { return OperandAt(1); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005564 Handle<Object> name() const { return name_; }
5565
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005566 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005567 return Representation::Tagged();
5568 }
5569
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00005570 virtual void PrintDataTo(StringStream* stream);
5571
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005572 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005573
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005574 private:
5575 Handle<Object> name_;
5576};
5577
5578
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00005579class HLoadFunctionPrototype: public HUnaryOperation {
5580 public:
5581 explicit HLoadFunctionPrototype(HValue* function)
5582 : HUnaryOperation(function) {
5583 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00005584 SetFlag(kUseGVN);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00005585 SetGVNFlag(kDependsOnCalls);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00005586 }
5587
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005588 HValue* function() { return OperandAt(0); }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00005589
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005590 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00005591 return Representation::Tagged();
5592 }
5593
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005594 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00005595
5596 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005597 virtual bool DataEquals(HValue* other) { return true; }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00005598};
5599
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +00005600class ArrayInstructionInterface {
5601 public:
5602 virtual HValue* GetKey() = 0;
5603 virtual void SetKey(HValue* key) = 0;
5604 virtual void SetIndexOffset(uint32_t index_offset) = 0;
5605 virtual bool IsDehoisted() = 0;
5606 virtual void SetDehoisted(bool is_dehoisted) = 0;
5607 virtual ~ArrayInstructionInterface() { };
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00005608
5609 static Representation KeyedAccessIndexRequirement(Representation r) {
5610 return r.IsInteger32() ? Representation::Integer32()
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005611 : Representation::Smi();
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00005612 }
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +00005613};
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00005614
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005615
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005616enum LoadKeyedHoleMode {
5617 NEVER_RETURN_HOLE,
5618 ALLOW_RETURN_HOLE
5619};
5620
5621
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005622class HLoadKeyed
yangguo@chromium.org304cc332012-07-24 07:59:48 +00005623 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005624 public:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005625 HLoadKeyed(HValue* obj,
5626 HValue* key,
5627 HValue* dependency,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005628 ElementsKind elements_kind,
5629 LoadKeyedHoleMode mode = NEVER_RETURN_HOLE)
mmassi@chromium.org7028c052012-06-13 11:51:58 +00005630 : bit_field_(0) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005631 bit_field_ = ElementsKindField::encode(elements_kind) |
5632 HoleModeField::encode(mode);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005633
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005634 SetOperandAt(0, obj);
5635 SetOperandAt(1, key);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00005636 SetOperandAt(2, dependency != NULL ? dependency : obj);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005637
5638 if (!is_external()) {
5639 // I can detect the case between storing double (holey and fast) and
5640 // smi/object by looking at elements_kind_.
5641 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
5642 IsFastDoubleElementsKind(elements_kind));
5643
5644 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00005645 if (IsFastSmiElementsKind(elements_kind) &&
5646 (!IsHoleyElementsKind(elements_kind) ||
5647 mode == NEVER_RETURN_HOLE)) {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005648 set_type(HType::Smi());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005649 set_representation(Representation::Smi());
5650 } else {
5651 set_representation(Representation::Tagged());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005652 }
5653
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005654 SetGVNFlag(kDependsOnArrayElements);
5655 } else {
5656 set_representation(Representation::Double());
5657 SetGVNFlag(kDependsOnDoubleArrayElements);
5658 }
5659 } else {
5660 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
5661 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
5662 set_representation(Representation::Double());
5663 } else {
5664 set_representation(Representation::Integer32());
5665 }
5666
5667 SetGVNFlag(kDependsOnSpecializedArrayElements);
5668 // Native code could change the specialized array.
5669 SetGVNFlag(kDependsOnCalls);
5670 }
5671
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005672 SetFlag(kUseGVN);
5673 }
5674
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005675 bool is_external() const {
5676 return IsExternalArrayElementsKind(elements_kind());
5677 }
5678 HValue* elements() { return OperandAt(0); }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005679 HValue* key() { return OperandAt(1); }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00005680 HValue* dependency() {
5681 ASSERT(HasDependency());
5682 return OperandAt(2);
5683 }
5684 bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
mmassi@chromium.org7028c052012-06-13 11:51:58 +00005685 uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); }
5686 void SetIndexOffset(uint32_t index_offset) {
5687 bit_field_ = IndexOffsetField::update(bit_field_, index_offset);
5688 }
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +00005689 HValue* GetKey() { return key(); }
5690 void SetKey(HValue* key) { SetOperandAt(1, key); }
mmassi@chromium.org7028c052012-06-13 11:51:58 +00005691 bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); }
5692 void SetDehoisted(bool is_dehoisted) {
5693 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
5694 }
5695 ElementsKind elements_kind() const {
5696 return ElementsKindField::decode(bit_field_);
5697 }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005698 LoadKeyedHoleMode hole_mode() const {
5699 return HoleModeField::decode(bit_field_);
5700 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005701
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005702 virtual Representation RequiredInputRepresentation(int index) {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005703 // kind_fast: tagged[int32] (none)
5704 // kind_double: tagged[int32] (none)
5705 // kind_external: external[int32] (none)
5706 if (index == 0) {
5707 return is_external() ? Representation::External()
5708 : Representation::Tagged();
5709 }
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00005710 if (index == 1) {
5711 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
5712 OperandAt(1)->representation());
5713 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +00005714 return Representation::None();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005715 }
5716
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00005717 virtual Representation observed_input_representation(int index) {
5718 return RequiredInputRepresentation(index);
5719 }
5720
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005721 virtual void PrintDataTo(StringStream* stream);
5722
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005723 bool UsesMustHandleHole() const;
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005724 bool AllUsesCanTreatHoleAsNaN() const;
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00005725 bool RequiresHoleCheck() const;
karlklose@chromium.org83a47282011-05-11 11:54:09 +00005726
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005727 virtual Range* InferRange(Zone* zone);
5728
5729 DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
ager@chromium.org378b34e2011-01-28 08:04:38 +00005730
5731 protected:
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00005732 virtual bool DataEquals(HValue* other) {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005733 if (!other->IsLoadKeyed()) return false;
5734 HLoadKeyed* other_load = HLoadKeyed::cast(other);
5735
mmassi@chromium.org7028c052012-06-13 11:51:58 +00005736 if (IsDehoisted() && index_offset() != other_load->index_offset())
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +00005737 return false;
mmassi@chromium.org7028c052012-06-13 11:51:58 +00005738 return elements_kind() == other_load->elements_kind();
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00005739 }
5740
5741 private:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005742 virtual bool IsDeletable() const {
5743 return !RequiresHoleCheck();
5744 }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00005745
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005746 // Establish some checks around our packed fields
5747 enum LoadKeyedBits {
5748 kBitsForElementsKind = 5,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005749 kBitsForHoleMode = 1,
5750 kBitsForIndexOffset = 25,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005751 kBitsForIsDehoisted = 1,
5752
5753 kStartElementsKind = 0,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005754 kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
5755 kStartIndexOffset = kStartHoleMode + kBitsForHoleMode,
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005756 kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset
5757 };
5758
5759 STATIC_ASSERT((kBitsForElementsKind + kBitsForIndexOffset +
5760 kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
5761 STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
5762 class ElementsKindField:
5763 public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
5764 {}; // NOLINT
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005765 class HoleModeField:
5766 public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
5767 {}; // NOLINT
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005768 class IndexOffsetField:
5769 public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset>
5770 {}; // NOLINT
5771 class IsDehoistedField:
5772 public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
5773 {}; // NOLINT
mmassi@chromium.org7028c052012-06-13 11:51:58 +00005774 uint32_t bit_field_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005775};
5776
5777
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005778class HLoadKeyedGeneric: public HTemplateInstruction<3> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005779 public:
karlklose@chromium.org83a47282011-05-11 11:54:09 +00005780 HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005781 set_representation(Representation::Tagged());
5782 SetOperandAt(0, obj);
5783 SetOperandAt(1, key);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00005784 SetOperandAt(2, context);
ager@chromium.org378b34e2011-01-28 08:04:38 +00005785 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005786 }
5787
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005788 HValue* object() { return OperandAt(0); }
5789 HValue* key() { return OperandAt(1); }
5790 HValue* context() { return OperandAt(2); }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00005791
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005792 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005793
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005794 virtual Representation RequiredInputRepresentation(int index) {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005795 // tagged[tagged]
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005796 return Representation::Tagged();
5797 }
5798
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00005799 virtual HValue* Canonicalize();
5800
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005801 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005802};
5803
5804
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005805class HStoreNamedField: public HTemplateInstruction<2> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005806 public:
5807 HStoreNamedField(HValue* obj,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005808 HObjectAccess access,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005809 HValue* val,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005810 Representation field_representation
5811 = Representation::Tagged())
5812 : access_(access),
danno@chromium.orgf005df62013-04-30 16:36:45 +00005813 field_representation_(field_representation),
danno@chromium.org41728482013-06-12 22:31:22 +00005814 transition_(),
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00005815 transition_unique_id_(),
danno@chromium.orgbee51992013-07-10 14:57:15 +00005816 new_space_dominator_(NULL),
5817 write_barrier_mode_(UPDATE_WRITE_BARRIER) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00005818 SetOperandAt(0, obj);
5819 SetOperandAt(1, val);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005820 access.SetGVNFlags(this, true);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005821 }
5822
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005823 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005824
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005825 virtual bool HasEscapingOperandAt(int index) { return index == 1; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005826 virtual Representation RequiredInputRepresentation(int index) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +00005827 if (FLAG_track_double_fields &&
5828 index == 1 && field_representation_.IsDouble()) {
5829 return field_representation_;
5830 } else if (FLAG_track_fields &&
5831 index == 1 && field_representation_.IsSmi()) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005832 return field_representation_;
danno@chromium.orgf005df62013-04-30 16:36:45 +00005833 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005834 return Representation::Tagged();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005835 }
danno@chromium.org169691d2013-07-15 08:01:13 +00005836 virtual void HandleSideEffectDominator(GVNFlag side_effect,
5837 HValue* dominator) {
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00005838 ASSERT(side_effect == kChangesNewSpacePromotion);
5839 new_space_dominator_ = dominator;
5840 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005841 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005842
danno@chromium.orgbee51992013-07-10 14:57:15 +00005843 void SkipWriteBarrier() { write_barrier_mode_ = SKIP_WRITE_BARRIER; }
5844 bool IsSkipWriteBarrier() const {
5845 return write_barrier_mode_ == SKIP_WRITE_BARRIER;
5846 }
5847
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005848 HValue* object() { return OperandAt(0); }
5849 HValue* value() { return OperandAt(1); }
5850
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005851 HObjectAccess access() const { return access_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005852 Handle<Map> transition() const { return transition_; }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00005853 UniqueValueId transition_unique_id() const { return transition_unique_id_; }
danno@chromium.org41728482013-06-12 22:31:22 +00005854 void SetTransition(Handle<Map> map, CompilationInfo* info) {
5855 ASSERT(transition_.is_null()); // Only set once.
5856 if (map->CanBeDeprecated()) {
5857 map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info);
5858 }
5859 transition_ = map;
5860 }
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00005861 HValue* new_space_dominator() const { return new_space_dominator_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005862
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005863 bool NeedsWriteBarrier() {
ulan@chromium.org57ff8812013-05-10 08:16:55 +00005864 ASSERT(!(FLAG_track_double_fields && field_representation_.IsDouble()) ||
5865 transition_.is_null());
danno@chromium.orgbee51992013-07-10 14:57:15 +00005866 if (IsSkipWriteBarrier()) return false;
danno@chromium.orgf005df62013-04-30 16:36:45 +00005867 return (!FLAG_track_fields || !field_representation_.IsSmi()) &&
ulan@chromium.org57ff8812013-05-10 08:16:55 +00005868 // If there is a transition, a new storage object needs to be allocated.
5869 !(FLAG_track_double_fields && field_representation_.IsDouble()) &&
danno@chromium.orgf005df62013-04-30 16:36:45 +00005870 StoringValueNeedsWriteBarrier(value()) &&
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00005871 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
ricow@chromium.org83aa5492011-02-07 12:42:56 +00005872 }
5873
verwaest@chromium.org37141392012-05-31 13:27:02 +00005874 bool NeedsWriteBarrierForMap() {
danno@chromium.orgbee51992013-07-10 14:57:15 +00005875 if (IsSkipWriteBarrier()) return false;
verwaest@chromium.org37141392012-05-31 13:27:02 +00005876 return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
5877 }
5878
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00005879 virtual void FinalizeUniqueValueId() {
5880 transition_unique_id_ = UniqueValueId(transition_);
5881 }
5882
danno@chromium.orgf005df62013-04-30 16:36:45 +00005883 Representation field_representation() const {
5884 return field_representation_;
5885 }
5886
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005887 private:
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005888 HObjectAccess access_;
danno@chromium.orgf005df62013-04-30 16:36:45 +00005889 Representation field_representation_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005890 Handle<Map> transition_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00005891 UniqueValueId transition_unique_id_;
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00005892 HValue* new_space_dominator_;
danno@chromium.orgbee51992013-07-10 14:57:15 +00005893 WriteBarrierMode write_barrier_mode_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005894};
5895
5896
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005897class HStoreNamedGeneric: public HTemplateInstruction<3> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005898 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00005899 HStoreNamedGeneric(HValue* context,
5900 HValue* object,
5901 Handle<String> name,
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00005902 HValue* value,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00005903 StrictModeFlag strict_mode_flag)
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00005904 : name_(name),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00005905 strict_mode_flag_(strict_mode_flag) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005906 SetOperandAt(0, object);
5907 SetOperandAt(1, value);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00005908 SetOperandAt(2, context);
ager@chromium.org378b34e2011-01-28 08:04:38 +00005909 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005910 }
5911
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005912 HValue* object() { return OperandAt(0); }
5913 HValue* value() { return OperandAt(1); }
5914 HValue* context() { return OperandAt(2); }
5915 Handle<String> name() { return name_; }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00005916 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00005917
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005918 virtual void PrintDataTo(StringStream* stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005919
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005920 virtual Representation RequiredInputRepresentation(int index) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005921 return Representation::Tagged();
5922 }
5923
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00005924 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005925
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005926 private:
5927 Handle<String> name_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00005928 StrictModeFlag strict_mode_flag_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005929};
5930
5931
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005932class HStoreKeyed
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +00005933 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005934 public:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005935 HStoreKeyed(HValue* obj, HValue* key, HValue* val,
5936 ElementsKind elements_kind)
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005937 : elements_kind_(elements_kind),
5938 index_offset_(0),
5939 is_dehoisted_(false),
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00005940 is_uninitialized_(false),
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005941 new_space_dominator_(NULL) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00005942 SetOperandAt(0, obj);
5943 SetOperandAt(1, key);
5944 SetOperandAt(2, val);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005945
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00005946 if (IsFastObjectElementsKind(elements_kind)) {
5947 SetFlag(kTrackSideEffectDominators);
5948 SetGVNFlag(kDependsOnNewSpacePromotion);
5949 }
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005950 if (is_external()) {
5951 SetGVNFlag(kChangesSpecializedArrayElements);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005952 SetFlag(kAllowUndefinedAsNaN);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005953 } else if (IsFastDoubleElementsKind(elements_kind)) {
5954 SetGVNFlag(kChangesDoubleArrayElements);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005955 } else if (IsFastSmiElementsKind(elements_kind)) {
5956 SetGVNFlag(kChangesArrayElements);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005957 } else {
5958 SetGVNFlag(kChangesArrayElements);
5959 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00005960
5961 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
5962 if (elements_kind >= EXTERNAL_BYTE_ELEMENTS &&
5963 elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) {
5964 SetFlag(kTruncatingToInt32);
5965 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005966 }
5967
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005968 virtual bool HasEscapingOperandAt(int index) { return index != 0; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005969 virtual Representation RequiredInputRepresentation(int index) {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005970 // kind_fast: tagged[int32] = tagged
5971 // kind_double: tagged[int32] = double
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00005972 // kind_smi : tagged[int32] = smi
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005973 // kind_external: external[int32] = (double | int32)
5974 if (index == 0) {
5975 return is_external() ? Representation::External()
5976 : Representation::Tagged();
5977 } else if (index == 1) {
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00005978 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
5979 OperandAt(1)->representation());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005980 }
5981
5982 ASSERT_EQ(index, 2);
5983 if (IsDoubleOrFloatElementsKind(elements_kind())) {
5984 return Representation::Double();
5985 }
5986
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00005987 if (IsFastSmiElementsKind(elements_kind())) {
5988 return Representation::Smi();
5989 }
5990
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005991 return is_external() ? Representation::Integer32()
5992 : Representation::Tagged();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00005993 }
5994
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00005995 bool is_external() const {
5996 return IsExternalArrayElementsKind(elements_kind());
5997 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00005998
5999 virtual Representation observed_input_representation(int index) {
6000 if (index < 2) return RequiredInputRepresentation(index);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00006001 if (IsUninitialized()) {
6002 return Representation::None();
6003 }
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00006004 if (IsFastSmiElementsKind(elements_kind())) {
6005 return Representation::Smi();
6006 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00006007 if (IsDoubleOrFloatElementsKind(elements_kind())) {
6008 return Representation::Double();
6009 }
6010 if (is_external()) {
6011 return Representation::Integer32();
6012 }
6013 // For fast object elements kinds, don't assume anything.
6014 return Representation::None();
6015 }
6016
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00006017 HValue* elements() { return OperandAt(0); }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006018 HValue* key() { return OperandAt(1); }
6019 HValue* value() { return OperandAt(2); }
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00006020 bool value_is_smi() const {
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00006021 return IsFastSmiElementsKind(elements_kind_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006022 }
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00006023 ElementsKind elements_kind() const { return elements_kind_; }
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +00006024 uint32_t index_offset() { return index_offset_; }
6025 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
6026 HValue* GetKey() { return key(); }
6027 void SetKey(HValue* key) { SetOperandAt(1, key); }
6028 bool IsDehoisted() { return is_dehoisted_; }
6029 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00006030 bool IsUninitialized() { return is_uninitialized_; }
6031 void SetUninitialized(bool is_uninitialized) {
6032 is_uninitialized_ = is_uninitialized;
6033 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006034
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00006035 bool IsConstantHoleStore() {
6036 return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
6037 }
6038
danno@chromium.org169691d2013-07-15 08:01:13 +00006039 virtual void HandleSideEffectDominator(GVNFlag side_effect,
6040 HValue* dominator) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00006041 ASSERT(side_effect == kChangesNewSpacePromotion);
6042 new_space_dominator_ = dominator;
6043 }
6044
6045 HValue* new_space_dominator() const { return new_space_dominator_; }
6046
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006047 bool NeedsWriteBarrier() {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006048 if (value_is_smi()) {
6049 return false;
6050 } else {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00006051 return StoringValueNeedsWriteBarrier(value()) &&
6052 ReceiverObjectNeedsWriteBarrier(elements(), new_space_dominator());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006053 }
6054 }
6055
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00006056 bool NeedsCanonicalization();
6057
rossberg@chromium.org717967f2011-07-20 13:44:42 +00006058 virtual void PrintDataTo(StringStream* stream);
6059
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00006060 DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006061
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006062 private:
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00006063 ElementsKind elements_kind_;
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +00006064 uint32_t index_offset_;
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00006065 bool is_dehoisted_ : 1;
6066 bool is_uninitialized_ : 1;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00006067 HValue* new_space_dominator_;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006068};
6069
6070
6071class HStoreKeyedGeneric: public HTemplateInstruction<4> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006072 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00006073 HStoreKeyedGeneric(HValue* context,
6074 HValue* object,
6075 HValue* key,
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00006076 HValue* value,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00006077 StrictModeFlag strict_mode_flag)
6078 : strict_mode_flag_(strict_mode_flag) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006079 SetOperandAt(0, object);
6080 SetOperandAt(1, key);
6081 SetOperandAt(2, value);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00006082 SetOperandAt(3, context);
ager@chromium.org378b34e2011-01-28 08:04:38 +00006083 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006084 }
6085
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006086 HValue* object() { return OperandAt(0); }
6087 HValue* key() { return OperandAt(1); }
6088 HValue* value() { return OperandAt(2); }
6089 HValue* context() { return OperandAt(3); }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00006090 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00006091
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006092 virtual Representation RequiredInputRepresentation(int index) {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00006093 // tagged[tagged] = tagged
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006094 return Representation::Tagged();
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00006095 }
6096
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006097 virtual void PrintDataTo(StringStream* stream);
6098
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006099 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00006100
6101 private:
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00006102 StrictModeFlag strict_mode_flag_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006103};
6104
6105
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00006106class HTransitionElementsKind: public HTemplateInstruction<2> {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006107 public:
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00006108 HTransitionElementsKind(HValue* context,
6109 HValue* object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006110 Handle<Map> original_map,
6111 Handle<Map> transitioned_map)
6112 : original_map_(original_map),
yangguo@chromium.org003650e2013-01-24 16:31:08 +00006113 transitioned_map_(transitioned_map),
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00006114 original_map_unique_id_(),
6115 transitioned_map_unique_id_(),
yangguo@chromium.org003650e2013-01-24 16:31:08 +00006116 from_kind_(original_map->elements_kind()),
6117 to_kind_(transitioned_map->elements_kind()) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006118 SetOperandAt(0, object);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00006119 SetOperandAt(1, context);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006120 SetFlag(kUseGVN);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00006121 SetGVNFlag(kChangesElementsKind);
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00006122 if (original_map->has_fast_double_elements()) {
6123 SetGVNFlag(kChangesElementsPointer);
6124 SetGVNFlag(kChangesNewSpacePromotion);
6125 }
6126 if (transitioned_map->has_fast_double_elements()) {
6127 SetGVNFlag(kChangesElementsPointer);
6128 SetGVNFlag(kChangesNewSpacePromotion);
6129 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006130 set_representation(Representation::Tagged());
6131 }
6132
6133 virtual Representation RequiredInputRepresentation(int index) {
6134 return Representation::Tagged();
6135 }
6136
6137 HValue* object() { return OperandAt(0); }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00006138 HValue* context() { return OperandAt(1); }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006139 Handle<Map> original_map() { return original_map_; }
6140 Handle<Map> transitioned_map() { return transitioned_map_; }
yangguo@chromium.org003650e2013-01-24 16:31:08 +00006141 ElementsKind from_kind() { return from_kind_; }
6142 ElementsKind to_kind() { return to_kind_; }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006143
6144 virtual void PrintDataTo(StringStream* stream);
6145
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00006146 virtual void FinalizeUniqueValueId() {
6147 original_map_unique_id_ = UniqueValueId(original_map_);
6148 transitioned_map_unique_id_ = UniqueValueId(transitioned_map_);
6149 }
6150
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006151 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
6152
6153 protected:
6154 virtual bool DataEquals(HValue* other) {
6155 HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00006156 return original_map_unique_id_ == instr->original_map_unique_id_ &&
6157 transitioned_map_unique_id_ == instr->transitioned_map_unique_id_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006158 }
6159
6160 private:
6161 Handle<Map> original_map_;
6162 Handle<Map> transitioned_map_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00006163 UniqueValueId original_map_unique_id_;
6164 UniqueValueId transitioned_map_unique_id_;
yangguo@chromium.org003650e2013-01-24 16:31:08 +00006165 ElementsKind from_kind_;
6166 ElementsKind to_kind_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006167};
6168
6169
danno@chromium.org160a7b02011-04-18 15:51:38 +00006170class HStringAdd: public HBinaryOperation {
6171 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00006172 static HInstruction* New(Zone* zone,
6173 HValue* context,
6174 HValue* left,
6175 HValue* right);
danno@chromium.org160a7b02011-04-18 15:51:38 +00006176
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006177 virtual Representation RequiredInputRepresentation(int index) {
danno@chromium.org160a7b02011-04-18 15:51:38 +00006178 return Representation::Tagged();
6179 }
6180
6181 virtual HType CalculateInferredType() {
6182 return HType::String();
6183 }
6184
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006185 DECLARE_CONCRETE_INSTRUCTION(StringAdd)
danno@chromium.org160a7b02011-04-18 15:51:38 +00006186
6187 protected:
6188 virtual bool DataEquals(HValue* other) { return true; }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006189
ulan@chromium.org2e04b582013-02-21 14:06:02 +00006190
6191 private:
6192 HStringAdd(HValue* context, HValue* left, HValue* right)
6193 : HBinaryOperation(context, left, right) {
6194 set_representation(Representation::Tagged());
6195 SetFlag(kUseGVN);
6196 SetGVNFlag(kDependsOnMaps);
6197 SetGVNFlag(kChangesNewSpacePromotion);
6198 }
6199
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006200 // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006201 // virtual bool IsDeletable() const { return true; }
danno@chromium.org160a7b02011-04-18 15:51:38 +00006202};
6203
6204
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006205class HStringCharCodeAt: public HTemplateInstruction<3> {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006206 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006207 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
6208 SetOperandAt(0, context);
6209 SetOperandAt(1, string);
6210 SetOperandAt(2, index);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006211 set_representation(Representation::Integer32());
6212 SetFlag(kUseGVN);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00006213 SetGVNFlag(kDependsOnMaps);
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00006214 SetGVNFlag(kChangesNewSpacePromotion);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006215 }
6216
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006217 virtual Representation RequiredInputRepresentation(int index) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006218 // The index is supposed to be Integer32.
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006219 return index == 2
6220 ? Representation::Integer32()
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006221 : Representation::Tagged();
6222 }
6223
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006224 HValue* context() { return OperandAt(0); }
6225 HValue* string() { return OperandAt(1); }
6226 HValue* index() { return OperandAt(2); }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006227
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006228 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006229
6230 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006231 virtual bool DataEquals(HValue* other) { return true; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00006232
ulan@chromium.org812308e2012-02-29 15:58:45 +00006233 virtual Range* InferRange(Zone* zone) {
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006234 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006235 }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006236
6237 // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
6238 // private:
6239 // virtual bool IsDeletable() const { return true; }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006240};
6241
6242
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006243class HStringCharFromCode: public HTemplateInstruction<2> {
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00006244 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00006245 static HInstruction* New(Zone* zone,
6246 HValue* context,
6247 HValue* char_code);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00006248
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006249 virtual Representation RequiredInputRepresentation(int index) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006250 return index == 0
6251 ? Representation::Tagged()
6252 : Representation::Integer32();
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00006253 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006254 virtual HType CalculateInferredType();
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00006255
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006256 HValue* context() { return OperandAt(0); }
6257 HValue* value() { return OperandAt(1); }
6258
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00006259 virtual bool DataEquals(HValue* other) { return true; }
6260
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006261 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006262
ulan@chromium.org2e04b582013-02-21 14:06:02 +00006263 private:
6264 HStringCharFromCode(HValue* context, HValue* char_code) {
6265 SetOperandAt(0, context);
6266 SetOperandAt(1, char_code);
6267 set_representation(Representation::Tagged());
6268 SetFlag(kUseGVN);
6269 SetGVNFlag(kChangesNewSpacePromotion);
6270 }
6271
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006272 // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
ulan@chromium.org2e04b582013-02-21 14:06:02 +00006273 // virtual bool IsDeletable() const { return true; }
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00006274};
6275
6276
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006277class HStringLength: public HUnaryOperation {
6278 public:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00006279 static HInstruction* New(Zone* zone, HValue* string);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006280
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006281 virtual Representation RequiredInputRepresentation(int index) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006282 return Representation::Tagged();
6283 }
6284
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006285 virtual HType CalculateInferredType() {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006286 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
6287 return HType::Smi();
6288 }
6289
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006290 DECLARE_CONCRETE_INSTRUCTION(StringLength)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006291
6292 protected:
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006293 virtual bool DataEquals(HValue* other) { return true; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00006294
ulan@chromium.org812308e2012-02-29 15:58:45 +00006295 virtual Range* InferRange(Zone* zone) {
6296 return new(zone) Range(0, String::kMaxLength);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006297 }
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006298
6299 private:
ulan@chromium.org2e04b582013-02-21 14:06:02 +00006300 explicit HStringLength(HValue* string) : HUnaryOperation(string) {
6301 set_representation(Representation::Tagged());
6302 SetFlag(kUseGVN);
6303 SetGVNFlag(kDependsOnMaps);
6304 }
6305
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006306 virtual bool IsDeletable() const { return true; }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00006307};
6308
6309
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006310template <int V>
6311class HMaterializedLiteral: public HTemplateInstruction<V> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006312 public:
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00006313 HMaterializedLiteral<V>(int index, int depth, AllocationSiteMode mode)
6314 : literal_index_(index), depth_(depth), allocation_site_mode_(mode) {
6315 this->set_representation(Representation::Tagged());
6316 }
6317
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006318 HMaterializedLiteral<V>(int index, int depth)
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00006319 : literal_index_(index), depth_(depth),
6320 allocation_site_mode_(DONT_TRACK_ALLOCATION_SITE) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006321 this->set_representation(Representation::Tagged());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006322 }
6323
6324 int literal_index() const { return literal_index_; }
6325 int depth() const { return depth_; }
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00006326 AllocationSiteMode allocation_site_mode() const {
6327 return allocation_site_mode_;
6328 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006329
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006330 private:
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006331 virtual bool IsDeletable() const { return true; }
6332
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006333 int literal_index_;
6334 int depth_;
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00006335 AllocationSiteMode allocation_site_mode_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006336};
6337
6338
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006339class HRegExpLiteral: public HMaterializedLiteral<1> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006340 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006341 HRegExpLiteral(HValue* context,
yangguo@chromium.org9c741c82012-06-28 15:04:22 +00006342 Handle<FixedArray> literals,
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006343 Handle<String> pattern,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006344 Handle<String> flags,
6345 int literal_index)
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006346 : HMaterializedLiteral<1>(literal_index, 0),
yangguo@chromium.org9c741c82012-06-28 15:04:22 +00006347 literals_(literals),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006348 pattern_(pattern),
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006349 flags_(flags) {
6350 SetOperandAt(0, context);
ricow@chromium.org27bf2882011-11-17 08:34:43 +00006351 SetAllSideEffects();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006352 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006353
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006354 HValue* context() { return OperandAt(0); }
yangguo@chromium.org9c741c82012-06-28 15:04:22 +00006355 Handle<FixedArray> literals() { return literals_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006356 Handle<String> pattern() { return pattern_; }
6357 Handle<String> flags() { return flags_; }
6358
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006359 virtual Representation RequiredInputRepresentation(int index) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006360 return Representation::Tagged();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006361 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006362 virtual HType CalculateInferredType();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006363
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006364 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006365
6366 private:
yangguo@chromium.org9c741c82012-06-28 15:04:22 +00006367 Handle<FixedArray> literals_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006368 Handle<String> pattern_;
6369 Handle<String> flags_;
6370};
6371
6372
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006373class HFunctionLiteral: public HTemplateInstruction<1> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006374 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006375 HFunctionLiteral(HValue* context,
6376 Handle<SharedFunctionInfo> shared,
6377 bool pretenure)
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00006378 : shared_info_(shared),
6379 pretenure_(pretenure),
6380 has_no_literals_(shared->num_literals() == 0),
6381 is_generator_(shared->is_generator()),
6382 language_mode_(shared->language_mode()) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006383 SetOperandAt(0, context);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006384 set_representation(Representation::Tagged());
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00006385 SetGVNFlag(kChangesNewSpacePromotion);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006386 }
6387
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006388 HValue* context() { return OperandAt(0); }
6389
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006390 virtual Representation RequiredInputRepresentation(int index) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006391 return Representation::Tagged();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006392 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006393 virtual HType CalculateInferredType();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006394
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006395 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006396
6397 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
6398 bool pretenure() const { return pretenure_; }
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00006399 bool has_no_literals() const { return has_no_literals_; }
6400 bool is_generator() const { return is_generator_; }
6401 LanguageMode language_mode() const { return language_mode_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006402
6403 private:
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006404 virtual bool IsDeletable() const { return true; }
6405
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006406 Handle<SharedFunctionInfo> shared_info_;
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00006407 bool pretenure_ : 1;
6408 bool has_no_literals_ : 1;
6409 bool is_generator_ : 1;
6410 LanguageMode language_mode_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006411};
6412
6413
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006414class HTypeof: public HTemplateInstruction<2> {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006415 public:
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006416 explicit HTypeof(HValue* context, HValue* value) {
6417 SetOperandAt(0, context);
6418 SetOperandAt(1, value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006419 set_representation(Representation::Tagged());
6420 }
6421
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00006422 HValue* context() { return OperandAt(0); }
6423 HValue* value() { return OperandAt(1); }
6424
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006425 virtual void PrintDataTo(StringStream* stream);
6426
6427 virtual Representation RequiredInputRepresentation(int index) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00006428 return Representation::Tagged();
6429 }
6430
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006431 DECLARE_CONCRETE_INSTRUCTION(Typeof)
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006432
6433 private:
6434 virtual bool IsDeletable() const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006435};
6436
6437
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00006438class HTrapAllocationMemento : public HTemplateInstruction<1> {
6439 public:
6440 explicit HTrapAllocationMemento(HValue* obj) {
6441 SetOperandAt(0, obj);
6442 }
6443
6444 virtual Representation RequiredInputRepresentation(int index) {
6445 return Representation::Tagged();
6446 }
6447
6448 HValue* object() { return OperandAt(0); }
6449
6450 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
6451};
6452
6453
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00006454class HToFastProperties: public HUnaryOperation {
6455 public:
6456 explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
6457 // This instruction is not marked as having side effects, but
6458 // changes the map of the input operand. Use it only when creating
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00006459 // object literals via a runtime call.
6460 ASSERT(value->IsCallRuntime());
6461#ifdef DEBUG
6462 const Runtime::Function* function = HCallRuntime::cast(value)->function();
6463 ASSERT(function->function_id == Runtime::kCreateObjectLiteral ||
6464 function->function_id == Runtime::kCreateObjectLiteralShallow);
6465#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00006466 set_representation(Representation::Tagged());
6467 }
6468
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006469 virtual Representation RequiredInputRepresentation(int index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00006470 return Representation::Tagged();
6471 }
6472
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006473 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006474
6475 private:
6476 virtual bool IsDeletable() const { return true; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00006477};
6478
6479
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006480class HValueOf: public HUnaryOperation {
6481 public:
6482 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
6483 set_representation(Representation::Tagged());
6484 }
6485
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006486 virtual Representation RequiredInputRepresentation(int index) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00006487 return Representation::Tagged();
6488 }
6489
ricow@chromium.orgdcebac02011-04-20 09:44:50 +00006490 DECLARE_CONCRETE_INSTRUCTION(ValueOf)
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006491
6492 private:
6493 virtual bool IsDeletable() const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006494};
6495
6496
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00006497class HDateField: public HUnaryOperation {
6498 public:
6499 HDateField(HValue* date, Smi* index)
6500 : HUnaryOperation(date), index_(index) {
6501 set_representation(Representation::Tagged());
6502 }
6503
6504 Smi* index() const { return index_; }
6505
6506 virtual Representation RequiredInputRepresentation(int index) {
6507 return Representation::Tagged();
6508 }
6509
6510 DECLARE_CONCRETE_INSTRUCTION(DateField)
6511
6512 private:
6513 Smi* index_;
6514};
6515
6516
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00006517class HSeqStringSetChar: public HTemplateInstruction<3> {
6518 public:
6519 HSeqStringSetChar(String::Encoding encoding,
6520 HValue* string,
6521 HValue* index,
6522 HValue* value) : encoding_(encoding) {
6523 SetOperandAt(0, string);
6524 SetOperandAt(1, index);
6525 SetOperandAt(2, value);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00006526 set_representation(Representation::Tagged());
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00006527 }
6528
6529 String::Encoding encoding() { return encoding_; }
6530 HValue* string() { return OperandAt(0); }
6531 HValue* index() { return OperandAt(1); }
6532 HValue* value() { return OperandAt(2); }
6533
6534 virtual Representation RequiredInputRepresentation(int index) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00006535 return (index == 0) ? Representation::Tagged()
6536 : Representation::Integer32();
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00006537 }
6538
6539 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
6540
6541 private:
6542 String::Encoding encoding_;
6543};
6544
6545
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00006546class HCheckMapValue: public HTemplateInstruction<2> {
6547 public:
6548 HCheckMapValue(HValue* value,
6549 HValue* map) {
6550 SetOperandAt(0, value);
6551 SetOperandAt(1, map);
6552 set_representation(Representation::Tagged());
6553 SetFlag(kUseGVN);
6554 SetGVNFlag(kDependsOnMaps);
6555 SetGVNFlag(kDependsOnElementsKind);
6556 }
6557
6558 virtual Representation RequiredInputRepresentation(int index) {
6559 return Representation::Tagged();
6560 }
6561
6562 virtual void PrintDataTo(StringStream* stream);
6563
6564 virtual HType CalculateInferredType() {
6565 return HType::Tagged();
6566 }
6567
6568 HValue* value() { return OperandAt(0); }
6569 HValue* map() { return OperandAt(1); }
6570
6571 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
6572
6573 protected:
6574 virtual bool DataEquals(HValue* other) {
6575 return true;
6576 }
6577};
6578
6579
6580class HForInPrepareMap : public HTemplateInstruction<2> {
6581 public:
6582 HForInPrepareMap(HValue* context,
6583 HValue* object) {
6584 SetOperandAt(0, context);
6585 SetOperandAt(1, object);
6586 set_representation(Representation::Tagged());
6587 SetAllSideEffects();
6588 }
6589
6590 virtual Representation RequiredInputRepresentation(int index) {
6591 return Representation::Tagged();
6592 }
6593
6594 HValue* context() { return OperandAt(0); }
6595 HValue* enumerable() { return OperandAt(1); }
6596
6597 virtual void PrintDataTo(StringStream* stream);
6598
6599 virtual HType CalculateInferredType() {
6600 return HType::Tagged();
6601 }
6602
6603 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
6604};
6605
6606
6607class HForInCacheArray : public HTemplateInstruction<2> {
6608 public:
6609 HForInCacheArray(HValue* enumerable,
6610 HValue* keys,
6611 int idx) : idx_(idx) {
6612 SetOperandAt(0, enumerable);
6613 SetOperandAt(1, keys);
6614 set_representation(Representation::Tagged());
6615 }
6616
6617 virtual Representation RequiredInputRepresentation(int index) {
6618 return Representation::Tagged();
6619 }
6620
6621 HValue* enumerable() { return OperandAt(0); }
6622 HValue* map() { return OperandAt(1); }
6623 int idx() { return idx_; }
6624
6625 HForInCacheArray* index_cache() {
6626 return index_cache_;
6627 }
6628
6629 void set_index_cache(HForInCacheArray* index_cache) {
6630 index_cache_ = index_cache;
6631 }
6632
6633 virtual void PrintDataTo(StringStream* stream);
6634
6635 virtual HType CalculateInferredType() {
6636 return HType::Tagged();
6637 }
6638
6639 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
6640
6641 private:
6642 int idx_;
6643 HForInCacheArray* index_cache_;
6644};
6645
6646
6647class HLoadFieldByIndex : public HTemplateInstruction<2> {
6648 public:
6649 HLoadFieldByIndex(HValue* object,
6650 HValue* index) {
6651 SetOperandAt(0, object);
6652 SetOperandAt(1, index);
6653 set_representation(Representation::Tagged());
6654 }
6655
6656 virtual Representation RequiredInputRepresentation(int index) {
6657 return Representation::Tagged();
6658 }
6659
6660 HValue* object() { return OperandAt(0); }
6661 HValue* index() { return OperandAt(1); }
6662
6663 virtual void PrintDataTo(StringStream* stream);
6664
6665 virtual HType CalculateInferredType() {
6666 return HType::Tagged();
6667 }
6668
6669 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +00006670
6671 private:
6672 virtual bool IsDeletable() const { return true; }
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00006673};
6674
6675
kasperl@chromium.orga5551262010-12-07 12:49:48 +00006676#undef DECLARE_INSTRUCTION
6677#undef DECLARE_CONCRETE_INSTRUCTION
6678
6679} } // namespace v8::internal
6680
6681#endif // V8_HYDROGEN_INSTRUCTIONS_H_