blob: 420a262180e34e74f2e8bba094b83dd0e6e364ea [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +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_LITHIUM_H_
29#define V8_LITHIUM_H_
30
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000032#include "hydrogen.h"
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000033#include "safepoint-table.h"
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000034
35namespace v8 {
36namespace internal {
37
jkummerow@chromium.org1456e702012-03-30 08:38:13 +000038#define LITHIUM_OPERAND_LIST(V) \
39 V(ConstantOperand, CONSTANT_OPERAND) \
40 V(StackSlot, STACK_SLOT) \
41 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \
42 V(Register, REGISTER) \
43 V(DoubleRegister, DOUBLE_REGISTER)
44
45
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000046class LOperand: public ZoneObject {
47 public:
48 enum Kind {
49 INVALID,
50 UNALLOCATED,
51 CONSTANT_OPERAND,
52 STACK_SLOT,
53 DOUBLE_STACK_SLOT,
54 REGISTER,
55 DOUBLE_REGISTER,
56 ARGUMENT
57 };
58
59 LOperand() : value_(KindField::encode(INVALID)) { }
60
61 Kind kind() const { return KindField::decode(value_); }
62 int index() const { return static_cast<int>(value_) >> kKindFieldWidth; }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +000063#define LITHIUM_OPERAND_PREDICATE(name, type) \
64 bool Is##name() const { return kind() == type; }
65 LITHIUM_OPERAND_LIST(LITHIUM_OPERAND_PREDICATE)
66 LITHIUM_OPERAND_PREDICATE(Argument, ARGUMENT)
67 LITHIUM_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
68 LITHIUM_OPERAND_PREDICATE(Ignored, INVALID)
69#undef LITHIUM_OPERAND_PREDICATE
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000070 bool Equals(LOperand* other) const { return value_ == other->value_; }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000071
72 void PrintTo(StringStream* stream);
73 void ConvertTo(Kind kind, int index) {
74 value_ = KindField::encode(kind);
75 value_ |= index << kKindFieldWidth;
76 ASSERT(this->index() == index);
77 }
78
jkummerow@chromium.org1456e702012-03-30 08:38:13 +000079 // Calls SetUpCache()/TearDownCache() for each subclass.
80 static void SetUpCaches();
81 static void TearDownCaches();
82
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000083 protected:
84 static const int kKindFieldWidth = 3;
85 class KindField : public BitField<Kind, 0, kKindFieldWidth> { };
86
87 LOperand(Kind kind, int index) { ConvertTo(kind, index); }
88
89 unsigned value_;
90};
91
92
93class LUnallocated: public LOperand {
94 public:
95 enum Policy {
96 NONE,
97 ANY,
98 FIXED_REGISTER,
99 FIXED_DOUBLE_REGISTER,
100 FIXED_SLOT,
101 MUST_HAVE_REGISTER,
102 WRITABLE_REGISTER,
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000103 SAME_AS_FIRST_INPUT
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000104 };
105
106 // Lifetime of operand inside the instruction.
107 enum Lifetime {
108 // USED_AT_START operand is guaranteed to be live only at
109 // instruction start. Register allocator is free to assign the same register
110 // to some other operand used inside instruction (i.e. temporary or
111 // output).
112 USED_AT_START,
113
114 // USED_AT_END operand is treated as live until the end of
115 // instruction. This means that register allocator will not reuse it's
116 // register for any other operand inside instruction.
117 USED_AT_END
118 };
119
120 explicit LUnallocated(Policy policy) : LOperand(UNALLOCATED, 0) {
121 Initialize(policy, 0, USED_AT_END);
122 }
123
124 LUnallocated(Policy policy, int fixed_index) : LOperand(UNALLOCATED, 0) {
125 Initialize(policy, fixed_index, USED_AT_END);
126 }
127
128 LUnallocated(Policy policy, Lifetime lifetime) : LOperand(UNALLOCATED, 0) {
129 Initialize(policy, 0, lifetime);
130 }
131
132 // The superclass has a KindField. Some policies have a signed fixed
133 // index in the upper bits.
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000134 static const int kPolicyWidth = 3;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000135 static const int kLifetimeWidth = 1;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000136 static const int kVirtualRegisterWidth = 15;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000137
138 static const int kPolicyShift = kKindFieldWidth;
139 static const int kLifetimeShift = kPolicyShift + kPolicyWidth;
140 static const int kVirtualRegisterShift = kLifetimeShift + kLifetimeWidth;
141 static const int kFixedIndexShift =
142 kVirtualRegisterShift + kVirtualRegisterWidth;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000143 static const int kFixedIndexWidth = 32 - kFixedIndexShift;
144 STATIC_ASSERT(kFixedIndexWidth > 5);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000145
146 class PolicyField : public BitField<Policy, kPolicyShift, kPolicyWidth> { };
147
148 class LifetimeField
149 : public BitField<Lifetime, kLifetimeShift, kLifetimeWidth> {
150 };
151
152 class VirtualRegisterField
153 : public BitField<unsigned,
154 kVirtualRegisterShift,
155 kVirtualRegisterWidth> {
156 };
157
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000158 static const int kMaxVirtualRegisters = 1 << kVirtualRegisterWidth;
rossberg@chromium.orgcddc71f2012-12-07 12:40:13 +0000159 static const int kMaxFixedIndex = (1 << (kFixedIndexWidth - 1)) - 1;
160 static const int kMinFixedIndex = -(1 << (kFixedIndexWidth - 1));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000161
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000162 bool HasAnyPolicy() const {
163 return policy() == ANY;
164 }
165 bool HasFixedPolicy() const {
166 return policy() == FIXED_REGISTER ||
167 policy() == FIXED_DOUBLE_REGISTER ||
168 policy() == FIXED_SLOT;
169 }
170 bool HasRegisterPolicy() const {
171 return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER;
172 }
173 bool HasSameAsInputPolicy() const {
174 return policy() == SAME_AS_FIRST_INPUT;
175 }
176 Policy policy() const { return PolicyField::decode(value_); }
177 void set_policy(Policy policy) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000178 value_ = PolicyField::update(value_, policy);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000179 }
180 int fixed_index() const {
181 return static_cast<int>(value_) >> kFixedIndexShift;
182 }
183
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000184 int virtual_register() const {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000185 return VirtualRegisterField::decode(value_);
186 }
187
188 void set_virtual_register(unsigned id) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000189 value_ = VirtualRegisterField::update(value_, id);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000190 }
191
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000192 LUnallocated* CopyUnconstrained(Zone* zone) {
193 LUnallocated* result = new(zone) LUnallocated(ANY);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000194 result->set_virtual_register(virtual_register());
195 return result;
196 }
197
198 static LUnallocated* cast(LOperand* op) {
199 ASSERT(op->IsUnallocated());
200 return reinterpret_cast<LUnallocated*>(op);
201 }
202
203 bool IsUsedAtStart() {
204 return LifetimeField::decode(value_) == USED_AT_START;
205 }
206
207 private:
208 void Initialize(Policy policy, int fixed_index, Lifetime lifetime) {
209 value_ |= PolicyField::encode(policy);
210 value_ |= LifetimeField::encode(lifetime);
211 value_ |= fixed_index << kFixedIndexShift;
212 ASSERT(this->fixed_index() == fixed_index);
213 }
214};
215
216
217class LMoveOperands BASE_EMBEDDED {
218 public:
219 LMoveOperands(LOperand* source, LOperand* destination)
220 : source_(source), destination_(destination) {
221 }
222
223 LOperand* source() const { return source_; }
224 void set_source(LOperand* operand) { source_ = operand; }
225
226 LOperand* destination() const { return destination_; }
227 void set_destination(LOperand* operand) { destination_ = operand; }
228
229 // The gap resolver marks moves as "in-progress" by clearing the
230 // destination (but not the source).
231 bool IsPending() const {
232 return destination_ == NULL && source_ != NULL;
233 }
234
235 // True if this move a move into the given destination operand.
236 bool Blocks(LOperand* operand) const {
237 return !IsEliminated() && source()->Equals(operand);
238 }
239
240 // A move is redundant if it's been eliminated, if its source and
241 // destination are the same, or if its destination is unneeded.
242 bool IsRedundant() const {
243 return IsEliminated() || source_->Equals(destination_) || IsIgnored();
244 }
245
246 bool IsIgnored() const {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000247 return destination_ != NULL && destination_->IsIgnored();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000248 }
249
250 // We clear both operands to indicate move that's been eliminated.
251 void Eliminate() { source_ = destination_ = NULL; }
252 bool IsEliminated() const {
253 ASSERT(source_ != NULL || destination_ == NULL);
254 return source_ == NULL;
255 }
256
257 private:
258 LOperand* source_;
259 LOperand* destination_;
260};
261
262
263class LConstantOperand: public LOperand {
264 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000265 static LConstantOperand* Create(int index, Zone* zone) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000266 ASSERT(index >= 0);
267 if (index < kNumCachedOperands) return &cache[index];
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000268 return new(zone) LConstantOperand(index);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000269 }
270
271 static LConstantOperand* cast(LOperand* op) {
272 ASSERT(op->IsConstantOperand());
273 return reinterpret_cast<LConstantOperand*>(op);
274 }
275
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000276 static void SetUpCache();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000277 static void TearDownCache();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000278
279 private:
280 static const int kNumCachedOperands = 128;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000281 static LConstantOperand* cache;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000282
283 LConstantOperand() : LOperand() { }
284 explicit LConstantOperand(int index) : LOperand(CONSTANT_OPERAND, index) { }
285};
286
287
288class LArgument: public LOperand {
289 public:
290 explicit LArgument(int index) : LOperand(ARGUMENT, index) { }
291
292 static LArgument* cast(LOperand* op) {
293 ASSERT(op->IsArgument());
294 return reinterpret_cast<LArgument*>(op);
295 }
296};
297
298
299class LStackSlot: public LOperand {
300 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000301 static LStackSlot* Create(int index, Zone* zone) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000302 ASSERT(index >= 0);
303 if (index < kNumCachedOperands) return &cache[index];
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000304 return new(zone) LStackSlot(index);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000305 }
306
307 static LStackSlot* cast(LOperand* op) {
308 ASSERT(op->IsStackSlot());
309 return reinterpret_cast<LStackSlot*>(op);
310 }
311
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000312 static void SetUpCache();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000313 static void TearDownCache();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000314
315 private:
316 static const int kNumCachedOperands = 128;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000317 static LStackSlot* cache;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000318
319 LStackSlot() : LOperand() { }
320 explicit LStackSlot(int index) : LOperand(STACK_SLOT, index) { }
321};
322
323
324class LDoubleStackSlot: public LOperand {
325 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000326 static LDoubleStackSlot* Create(int index, Zone* zone) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000327 ASSERT(index >= 0);
328 if (index < kNumCachedOperands) return &cache[index];
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000329 return new(zone) LDoubleStackSlot(index);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000330 }
331
332 static LDoubleStackSlot* cast(LOperand* op) {
333 ASSERT(op->IsStackSlot());
334 return reinterpret_cast<LDoubleStackSlot*>(op);
335 }
336
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000337 static void SetUpCache();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000338 static void TearDownCache();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000339
340 private:
341 static const int kNumCachedOperands = 128;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000342 static LDoubleStackSlot* cache;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000343
344 LDoubleStackSlot() : LOperand() { }
345 explicit LDoubleStackSlot(int index) : LOperand(DOUBLE_STACK_SLOT, index) { }
346};
347
348
349class LRegister: public LOperand {
350 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000351 static LRegister* Create(int index, Zone* zone) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000352 ASSERT(index >= 0);
353 if (index < kNumCachedOperands) return &cache[index];
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000354 return new(zone) LRegister(index);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000355 }
356
357 static LRegister* cast(LOperand* op) {
358 ASSERT(op->IsRegister());
359 return reinterpret_cast<LRegister*>(op);
360 }
361
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000362 static void SetUpCache();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000363 static void TearDownCache();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000364
365 private:
366 static const int kNumCachedOperands = 16;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000367 static LRegister* cache;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000368
369 LRegister() : LOperand() { }
370 explicit LRegister(int index) : LOperand(REGISTER, index) { }
371};
372
373
374class LDoubleRegister: public LOperand {
375 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000376 static LDoubleRegister* Create(int index, Zone* zone) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000377 ASSERT(index >= 0);
378 if (index < kNumCachedOperands) return &cache[index];
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000379 return new(zone) LDoubleRegister(index);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000380 }
381
382 static LDoubleRegister* cast(LOperand* op) {
383 ASSERT(op->IsDoubleRegister());
384 return reinterpret_cast<LDoubleRegister*>(op);
385 }
386
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000387 static void SetUpCache();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000388 static void TearDownCache();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000389
390 private:
391 static const int kNumCachedOperands = 16;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000392 static LDoubleRegister* cache;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000393
394 LDoubleRegister() : LOperand() { }
395 explicit LDoubleRegister(int index) : LOperand(DOUBLE_REGISTER, index) { }
396};
397
398
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000399class LParallelMove : public ZoneObject {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000400 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000401 explicit LParallelMove(Zone* zone) : move_operands_(4, zone) { }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000402
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000403 void AddMove(LOperand* from, LOperand* to, Zone* zone) {
404 move_operands_.Add(LMoveOperands(from, to), zone);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000405 }
406
407 bool IsRedundant() const;
408
409 const ZoneList<LMoveOperands>* move_operands() const {
410 return &move_operands_;
411 }
412
413 void PrintDataTo(StringStream* stream) const;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000414
415 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000416 ZoneList<LMoveOperands> move_operands_;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000417};
418
419
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000420class LPointerMap: public ZoneObject {
421 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000422 explicit LPointerMap(int position, Zone* zone)
423 : pointer_operands_(8, zone),
424 untagged_operands_(0, zone),
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000425 position_(position),
426 lithium_position_(-1) { }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000427
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000428 const ZoneList<LOperand*>* GetNormalizedOperands() {
429 for (int i = 0; i < untagged_operands_.length(); ++i) {
430 RemovePointer(untagged_operands_[i]);
431 }
432 untagged_operands_.Clear();
433 return &pointer_operands_;
434 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000435 int position() const { return position_; }
436 int lithium_position() const { return lithium_position_; }
437
438 void set_lithium_position(int pos) {
439 ASSERT(lithium_position_ == -1);
440 lithium_position_ = pos;
441 }
442
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000443 void RecordPointer(LOperand* op, Zone* zone);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000444 void RemovePointer(LOperand* op);
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000445 void RecordUntagged(LOperand* op, Zone* zone);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000446 void PrintTo(StringStream* stream);
447
448 private:
449 ZoneList<LOperand*> pointer_operands_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000450 ZoneList<LOperand*> untagged_operands_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000451 int position_;
452 int lithium_position_;
453};
454
455
456class LEnvironment: public ZoneObject {
457 public:
458 LEnvironment(Handle<JSFunction> closure,
ulan@chromium.org967e2702012-02-28 09:49:15 +0000459 FrameType frame_type,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000460 BailoutId ast_id,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000461 int parameter_count,
462 int argument_count,
463 int value_count,
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000464 LEnvironment* outer,
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000465 HEnterInlined* entry,
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000466 Zone* zone)
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000467 : closure_(closure),
ulan@chromium.org967e2702012-02-28 09:49:15 +0000468 frame_type_(frame_type),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000469 arguments_stack_height_(argument_count),
470 deoptimization_index_(Safepoint::kNoDeoptimizationIndex),
471 translation_index_(-1),
472 ast_id_(ast_id),
473 parameter_count_(parameter_count),
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000474 pc_offset_(-1),
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000475 values_(value_count, zone),
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000476 is_tagged_(value_count, zone),
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000477 is_uint32_(value_count, zone),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000478 spilled_registers_(NULL),
479 spilled_double_registers_(NULL),
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000480 outer_(outer),
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000481 entry_(entry),
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000482 zone_(zone) { }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000483
484 Handle<JSFunction> closure() const { return closure_; }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000485 FrameType frame_type() const { return frame_type_; }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000486 int arguments_stack_height() const { return arguments_stack_height_; }
487 int deoptimization_index() const { return deoptimization_index_; }
488 int translation_index() const { return translation_index_; }
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000489 BailoutId ast_id() const { return ast_id_; }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000490 int parameter_count() const { return parameter_count_; }
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000491 int pc_offset() const { return pc_offset_; }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000492 LOperand** spilled_registers() const { return spilled_registers_; }
493 LOperand** spilled_double_registers() const {
494 return spilled_double_registers_;
495 }
496 const ZoneList<LOperand*>* values() const { return &values_; }
497 LEnvironment* outer() const { return outer_; }
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000498 HEnterInlined* entry() { return entry_; }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000499
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000500 void AddValue(LOperand* operand,
501 Representation representation,
502 bool is_uint32) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000503 values_.Add(operand, zone());
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000504 if (representation.IsTagged()) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000505 ASSERT(!is_uint32);
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000506 is_tagged_.Add(values_.length() - 1);
507 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000508
509 if (is_uint32) {
510 is_uint32_.Add(values_.length() - 1);
511 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000512 }
513
514 bool HasTaggedValueAt(int index) const {
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000515 return is_tagged_.Contains(index);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000516 }
517
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000518 bool HasUint32ValueAt(int index) const {
519 return is_uint32_.Contains(index);
520 }
521
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000522 void Register(int deoptimization_index,
523 int translation_index,
524 int pc_offset) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000525 ASSERT(!HasBeenRegistered());
526 deoptimization_index_ = deoptimization_index;
527 translation_index_ = translation_index;
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000528 pc_offset_ = pc_offset;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000529 }
530 bool HasBeenRegistered() const {
531 return deoptimization_index_ != Safepoint::kNoDeoptimizationIndex;
532 }
533
534 void SetSpilledRegisters(LOperand** registers,
535 LOperand** double_registers) {
536 spilled_registers_ = registers;
537 spilled_double_registers_ = double_registers;
538 }
539
540 void PrintTo(StringStream* stream);
541
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000542 Zone* zone() const { return zone_; }
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000543
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000544 private:
545 Handle<JSFunction> closure_;
ulan@chromium.org967e2702012-02-28 09:49:15 +0000546 FrameType frame_type_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000547 int arguments_stack_height_;
548 int deoptimization_index_;
549 int translation_index_;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000550 BailoutId ast_id_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000551 int parameter_count_;
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000552 int pc_offset_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000553 ZoneList<LOperand*> values_;
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000554 BitVector is_tagged_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000555 BitVector is_uint32_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000556
557 // Allocation index indexed arrays of spill slot operands for registers
558 // that are also in spill slots at an OSR entry. NULL for environments
559 // that do not correspond to an OSR entry.
560 LOperand** spilled_registers_;
561 LOperand** spilled_double_registers_;
562
563 LEnvironment* outer_;
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000564 HEnterInlined* entry_;
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000565
566 Zone* zone_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000567};
568
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000569
570// Iterates over the non-null, non-constant operands in an environment.
571class ShallowIterator BASE_EMBEDDED {
572 public:
573 explicit ShallowIterator(LEnvironment* env)
574 : env_(env),
575 limit_(env != NULL ? env->values()->length() : 0),
576 current_(0) {
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000577 SkipUninteresting();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000578 }
579
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000580 bool Done() { return current_ >= limit_; }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000581
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000582 LOperand* Current() {
583 ASSERT(!Done());
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +0000584 ASSERT(env_->values()->at(current_) != NULL);
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000585 return env_->values()->at(current_);
586 }
587
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000588 void Advance() {
589 ASSERT(!Done());
590 ++current_;
591 SkipUninteresting();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000592 }
593
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000594 LEnvironment* env() { return env_; }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000595
596 private:
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000597 bool ShouldSkip(LOperand* op) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000598 return op == NULL || op->IsConstantOperand() || op->IsArgument();
599 }
600
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000601 // Skip until something interesting, beginning with and including current_.
602 void SkipUninteresting() {
603 while (current_ < limit_ && ShouldSkip(env_->values()->at(current_))) {
604 ++current_;
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000605 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000606 }
607
608 LEnvironment* env_;
609 int limit_;
610 int current_;
611};
612
613
614// Iterator for non-null, non-constant operands incl. outer environments.
615class DeepIterator BASE_EMBEDDED {
616 public:
617 explicit DeepIterator(LEnvironment* env)
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000618 : current_iterator_(env) {
619 SkipUninteresting();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000620 }
621
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000622 bool Done() { return current_iterator_.Done(); }
623
624 LOperand* Current() {
625 ASSERT(!current_iterator_.Done());
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +0000626 ASSERT(current_iterator_.Current() != NULL);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000627 return current_iterator_.Current();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000628 }
629
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000630 void Advance() {
631 current_iterator_.Advance();
632 SkipUninteresting();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000633 }
634
635 private:
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000636 void SkipUninteresting() {
637 while (current_iterator_.env() != NULL && current_iterator_.Done()) {
638 current_iterator_ = ShallowIterator(current_iterator_.env()->outer());
639 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000640 }
641
642 ShallowIterator current_iterator_;
643};
644
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000645
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000646class LPlatformChunk;
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000647class LGap;
648class LLabel;
649
650// Superclass providing data and behavior common to all the
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000651// arch-specific LPlatformChunk classes.
652class LChunk: public ZoneObject {
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000653 public:
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000654 static LChunk* NewChunk(HGraph* graph);
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000655
656 void AddInstruction(LInstruction* instruction, HBasicBlock* block);
657 LConstantOperand* DefineConstantOperand(HConstant* constant);
658 HConstant* LookupConstant(LConstantOperand* operand) const;
659 Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
660
661 int ParameterAt(int index);
662 int GetParameterStackSlot(int index) const;
663 int spill_slot_count() const { return spill_slot_count_; }
664 CompilationInfo* info() const { return info_; }
665 HGraph* graph() const { return graph_; }
666 const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
667 void AddGapMove(int index, LOperand* from, LOperand* to);
668 LGap* GetGapAt(int index) const;
669 bool IsGapAt(int index) const;
670 int NearestGapPos(int index) const;
671 void MarkEmptyBlocks();
672 const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
673 LLabel* GetLabel(int block_id) const;
674 int LookupDestination(int block_id) const;
675 Label* GetAssemblyLabel(int block_id) const;
676
677 const ZoneList<Handle<JSFunction> >* inlined_closures() const {
678 return &inlined_closures_;
679 }
680
681 void AddInlinedClosure(Handle<JSFunction> closure) {
682 inlined_closures_.Add(closure, zone());
683 }
684
685 Zone* zone() const { return info_->zone(); }
686
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000687 Handle<Code> Codegen(Code::Kind kind);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000688
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000689 void set_allocated_double_registers(BitVector* allocated_registers);
690 BitVector* allocated_double_registers() {
691 return allocated_double_registers_;
692 }
693
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000694 protected:
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000695 LChunk(CompilationInfo* info, HGraph* graph);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000696
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000697 int spill_slot_count_;
698
699 private:
700 CompilationInfo* info_;
701 HGraph* const graph_;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000702 BitVector* allocated_double_registers_;
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000703 ZoneList<LInstruction*> instructions_;
704 ZoneList<LPointerMap*> pointer_maps_;
705 ZoneList<Handle<JSFunction> > inlined_closures_;
706};
707
708
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000709int ElementsKindToShiftSize(ElementsKind elements_kind);
jkummerow@chromium.orgac360712013-02-11 09:00:07 +0000710int StackSlotOffset(int index);
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000711
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000712enum NumberUntagDMode {
713 NUMBER_CANDIDATE_IS_SMI,
714 NUMBER_CANDIDATE_IS_SMI_OR_HOLE,
715 NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE,
716 NUMBER_CANDIDATE_IS_ANY_TAGGED
717};
718
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000719
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000720} } // namespace v8::internal
721
722#endif // V8_LITHIUM_H_