blob: 2ccbf56c50c55597327730a4d76a84ce9c5ca26c [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;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000136 static const int kVirtualRegisterWidth = 18;
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;
143
144 class PolicyField : public BitField<Policy, kPolicyShift, kPolicyWidth> { };
145
146 class LifetimeField
147 : public BitField<Lifetime, kLifetimeShift, kLifetimeWidth> {
148 };
149
150 class VirtualRegisterField
151 : public BitField<unsigned,
152 kVirtualRegisterShift,
153 kVirtualRegisterWidth> {
154 };
155
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000156 static const int kMaxVirtualRegisters = 1 << kVirtualRegisterWidth;
ager@chromium.org04921a82011-06-27 13:21:41 +0000157 static const int kMaxFixedIndex = 63;
158 static const int kMinFixedIndex = -64;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000159
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000160 bool HasAnyPolicy() const {
161 return policy() == ANY;
162 }
163 bool HasFixedPolicy() const {
164 return policy() == FIXED_REGISTER ||
165 policy() == FIXED_DOUBLE_REGISTER ||
166 policy() == FIXED_SLOT;
167 }
168 bool HasRegisterPolicy() const {
169 return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER;
170 }
171 bool HasSameAsInputPolicy() const {
172 return policy() == SAME_AS_FIRST_INPUT;
173 }
174 Policy policy() const { return PolicyField::decode(value_); }
175 void set_policy(Policy policy) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000176 value_ = PolicyField::update(value_, policy);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000177 }
178 int fixed_index() const {
179 return static_cast<int>(value_) >> kFixedIndexShift;
180 }
181
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000182 int virtual_register() const {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000183 return VirtualRegisterField::decode(value_);
184 }
185
186 void set_virtual_register(unsigned id) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000187 value_ = VirtualRegisterField::update(value_, id);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000188 }
189
190 LUnallocated* CopyUnconstrained() {
191 LUnallocated* result = new LUnallocated(ANY);
192 result->set_virtual_register(virtual_register());
193 return result;
194 }
195
196 static LUnallocated* cast(LOperand* op) {
197 ASSERT(op->IsUnallocated());
198 return reinterpret_cast<LUnallocated*>(op);
199 }
200
201 bool IsUsedAtStart() {
202 return LifetimeField::decode(value_) == USED_AT_START;
203 }
204
205 private:
206 void Initialize(Policy policy, int fixed_index, Lifetime lifetime) {
207 value_ |= PolicyField::encode(policy);
208 value_ |= LifetimeField::encode(lifetime);
209 value_ |= fixed_index << kFixedIndexShift;
210 ASSERT(this->fixed_index() == fixed_index);
211 }
212};
213
214
215class LMoveOperands BASE_EMBEDDED {
216 public:
217 LMoveOperands(LOperand* source, LOperand* destination)
218 : source_(source), destination_(destination) {
219 }
220
221 LOperand* source() const { return source_; }
222 void set_source(LOperand* operand) { source_ = operand; }
223
224 LOperand* destination() const { return destination_; }
225 void set_destination(LOperand* operand) { destination_ = operand; }
226
227 // The gap resolver marks moves as "in-progress" by clearing the
228 // destination (but not the source).
229 bool IsPending() const {
230 return destination_ == NULL && source_ != NULL;
231 }
232
233 // True if this move a move into the given destination operand.
234 bool Blocks(LOperand* operand) const {
235 return !IsEliminated() && source()->Equals(operand);
236 }
237
238 // A move is redundant if it's been eliminated, if its source and
239 // destination are the same, or if its destination is unneeded.
240 bool IsRedundant() const {
241 return IsEliminated() || source_->Equals(destination_) || IsIgnored();
242 }
243
244 bool IsIgnored() const {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000245 return destination_ != NULL && destination_->IsIgnored();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000246 }
247
248 // We clear both operands to indicate move that's been eliminated.
249 void Eliminate() { source_ = destination_ = NULL; }
250 bool IsEliminated() const {
251 ASSERT(source_ != NULL || destination_ == NULL);
252 return source_ == NULL;
253 }
254
255 private:
256 LOperand* source_;
257 LOperand* destination_;
258};
259
260
261class LConstantOperand: public LOperand {
262 public:
263 static LConstantOperand* Create(int index) {
264 ASSERT(index >= 0);
265 if (index < kNumCachedOperands) return &cache[index];
266 return new LConstantOperand(index);
267 }
268
269 static LConstantOperand* cast(LOperand* op) {
270 ASSERT(op->IsConstantOperand());
271 return reinterpret_cast<LConstantOperand*>(op);
272 }
273
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000274 static void SetUpCache();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000275 static void TearDownCache();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000276
277 private:
278 static const int kNumCachedOperands = 128;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000279 static LConstantOperand* cache;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000280
281 LConstantOperand() : LOperand() { }
282 explicit LConstantOperand(int index) : LOperand(CONSTANT_OPERAND, index) { }
283};
284
285
286class LArgument: public LOperand {
287 public:
288 explicit LArgument(int index) : LOperand(ARGUMENT, index) { }
289
290 static LArgument* cast(LOperand* op) {
291 ASSERT(op->IsArgument());
292 return reinterpret_cast<LArgument*>(op);
293 }
294};
295
296
297class LStackSlot: public LOperand {
298 public:
299 static LStackSlot* Create(int index) {
300 ASSERT(index >= 0);
301 if (index < kNumCachedOperands) return &cache[index];
302 return new LStackSlot(index);
303 }
304
305 static LStackSlot* cast(LOperand* op) {
306 ASSERT(op->IsStackSlot());
307 return reinterpret_cast<LStackSlot*>(op);
308 }
309
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000310 static void SetUpCache();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000311 static void TearDownCache();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000312
313 private:
314 static const int kNumCachedOperands = 128;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000315 static LStackSlot* cache;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000316
317 LStackSlot() : LOperand() { }
318 explicit LStackSlot(int index) : LOperand(STACK_SLOT, index) { }
319};
320
321
322class LDoubleStackSlot: public LOperand {
323 public:
324 static LDoubleStackSlot* Create(int index) {
325 ASSERT(index >= 0);
326 if (index < kNumCachedOperands) return &cache[index];
327 return new LDoubleStackSlot(index);
328 }
329
330 static LDoubleStackSlot* cast(LOperand* op) {
331 ASSERT(op->IsStackSlot());
332 return reinterpret_cast<LDoubleStackSlot*>(op);
333 }
334
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000335 static void SetUpCache();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000336 static void TearDownCache();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000337
338 private:
339 static const int kNumCachedOperands = 128;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000340 static LDoubleStackSlot* cache;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000341
342 LDoubleStackSlot() : LOperand() { }
343 explicit LDoubleStackSlot(int index) : LOperand(DOUBLE_STACK_SLOT, index) { }
344};
345
346
347class LRegister: public LOperand {
348 public:
349 static LRegister* Create(int index) {
350 ASSERT(index >= 0);
351 if (index < kNumCachedOperands) return &cache[index];
352 return new LRegister(index);
353 }
354
355 static LRegister* cast(LOperand* op) {
356 ASSERT(op->IsRegister());
357 return reinterpret_cast<LRegister*>(op);
358 }
359
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000360 static void SetUpCache();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000361 static void TearDownCache();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000362
363 private:
364 static const int kNumCachedOperands = 16;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000365 static LRegister* cache;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000366
367 LRegister() : LOperand() { }
368 explicit LRegister(int index) : LOperand(REGISTER, index) { }
369};
370
371
372class LDoubleRegister: public LOperand {
373 public:
374 static LDoubleRegister* Create(int index) {
375 ASSERT(index >= 0);
376 if (index < kNumCachedOperands) return &cache[index];
377 return new LDoubleRegister(index);
378 }
379
380 static LDoubleRegister* cast(LOperand* op) {
381 ASSERT(op->IsDoubleRegister());
382 return reinterpret_cast<LDoubleRegister*>(op);
383 }
384
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000385 static void SetUpCache();
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000386 static void TearDownCache();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000387
388 private:
389 static const int kNumCachedOperands = 16;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000390 static LDoubleRegister* cache;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000391
392 LDoubleRegister() : LOperand() { }
393 explicit LDoubleRegister(int index) : LOperand(DOUBLE_REGISTER, index) { }
394};
395
396
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000397class LParallelMove : public ZoneObject {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000398 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000399 LParallelMove() : move_operands_(4) { }
400
401 void AddMove(LOperand* from, LOperand* to) {
402 move_operands_.Add(LMoveOperands(from, to));
403 }
404
405 bool IsRedundant() const;
406
407 const ZoneList<LMoveOperands>* move_operands() const {
408 return &move_operands_;
409 }
410
411 void PrintDataTo(StringStream* stream) const;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000412
413 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000414 ZoneList<LMoveOperands> move_operands_;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000415};
416
417
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000418class LPointerMap: public ZoneObject {
419 public:
420 explicit LPointerMap(int position)
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000421 : pointer_operands_(8),
422 untagged_operands_(0),
423 position_(position),
424 lithium_position_(-1) { }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000425
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000426 const ZoneList<LOperand*>* GetNormalizedOperands() {
427 for (int i = 0; i < untagged_operands_.length(); ++i) {
428 RemovePointer(untagged_operands_[i]);
429 }
430 untagged_operands_.Clear();
431 return &pointer_operands_;
432 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000433 int position() const { return position_; }
434 int lithium_position() const { return lithium_position_; }
435
436 void set_lithium_position(int pos) {
437 ASSERT(lithium_position_ == -1);
438 lithium_position_ = pos;
439 }
440
441 void RecordPointer(LOperand* op);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000442 void RemovePointer(LOperand* op);
443 void RecordUntagged(LOperand* op);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000444 void PrintTo(StringStream* stream);
445
446 private:
447 ZoneList<LOperand*> pointer_operands_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000448 ZoneList<LOperand*> untagged_operands_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000449 int position_;
450 int lithium_position_;
451};
452
453
454class LEnvironment: public ZoneObject {
455 public:
456 LEnvironment(Handle<JSFunction> closure,
ulan@chromium.org967e2702012-02-28 09:49:15 +0000457 FrameType frame_type,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000458 int ast_id,
459 int parameter_count,
460 int argument_count,
461 int value_count,
462 LEnvironment* outer)
463 : closure_(closure),
ulan@chromium.org967e2702012-02-28 09:49:15 +0000464 frame_type_(frame_type),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000465 arguments_stack_height_(argument_count),
466 deoptimization_index_(Safepoint::kNoDeoptimizationIndex),
467 translation_index_(-1),
468 ast_id_(ast_id),
469 parameter_count_(parameter_count),
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000470 pc_offset_(-1),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000471 values_(value_count),
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000472 is_tagged_(value_count, closure->GetHeap()->isolate()->zone()),
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000473 spilled_registers_(NULL),
474 spilled_double_registers_(NULL),
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000475 outer_(outer) { }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000476
477 Handle<JSFunction> closure() const { return closure_; }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000478 FrameType frame_type() const { return frame_type_; }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000479 int arguments_stack_height() const { return arguments_stack_height_; }
480 int deoptimization_index() const { return deoptimization_index_; }
481 int translation_index() const { return translation_index_; }
482 int ast_id() const { return ast_id_; }
483 int parameter_count() const { return parameter_count_; }
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000484 int pc_offset() const { return pc_offset_; }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000485 LOperand** spilled_registers() const { return spilled_registers_; }
486 LOperand** spilled_double_registers() const {
487 return spilled_double_registers_;
488 }
489 const ZoneList<LOperand*>* values() const { return &values_; }
490 LEnvironment* outer() const { return outer_; }
491
492 void AddValue(LOperand* operand, Representation representation) {
493 values_.Add(operand);
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000494 if (representation.IsTagged()) {
495 is_tagged_.Add(values_.length() - 1);
496 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000497 }
498
499 bool HasTaggedValueAt(int index) const {
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000500 return is_tagged_.Contains(index);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000501 }
502
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000503 void Register(int deoptimization_index,
504 int translation_index,
505 int pc_offset) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000506 ASSERT(!HasBeenRegistered());
507 deoptimization_index_ = deoptimization_index;
508 translation_index_ = translation_index;
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000509 pc_offset_ = pc_offset;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000510 }
511 bool HasBeenRegistered() const {
512 return deoptimization_index_ != Safepoint::kNoDeoptimizationIndex;
513 }
514
515 void SetSpilledRegisters(LOperand** registers,
516 LOperand** double_registers) {
517 spilled_registers_ = registers;
518 spilled_double_registers_ = double_registers;
519 }
520
521 void PrintTo(StringStream* stream);
522
523 private:
524 Handle<JSFunction> closure_;
ulan@chromium.org967e2702012-02-28 09:49:15 +0000525 FrameType frame_type_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000526 int arguments_stack_height_;
527 int deoptimization_index_;
528 int translation_index_;
529 int ast_id_;
530 int parameter_count_;
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000531 int pc_offset_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000532 ZoneList<LOperand*> values_;
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000533 BitVector is_tagged_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000534
535 // Allocation index indexed arrays of spill slot operands for registers
536 // that are also in spill slots at an OSR entry. NULL for environments
537 // that do not correspond to an OSR entry.
538 LOperand** spilled_registers_;
539 LOperand** spilled_double_registers_;
540
541 LEnvironment* outer_;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000542};
543
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000544
545// Iterates over the non-null, non-constant operands in an environment.
546class ShallowIterator BASE_EMBEDDED {
547 public:
548 explicit ShallowIterator(LEnvironment* env)
549 : env_(env),
550 limit_(env != NULL ? env->values()->length() : 0),
551 current_(0) {
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000552 SkipUninteresting();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000553 }
554
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000555 bool Done() { return current_ >= limit_; }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000556
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000557 LOperand* Current() {
558 ASSERT(!Done());
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000559 return env_->values()->at(current_);
560 }
561
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000562 void Advance() {
563 ASSERT(!Done());
564 ++current_;
565 SkipUninteresting();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000566 }
567
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000568 LEnvironment* env() { return env_; }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000569
570 private:
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000571 bool ShouldSkip(LOperand* op) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000572 return op == NULL || op->IsConstantOperand() || op->IsArgument();
573 }
574
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000575 // Skip until something interesting, beginning with and including current_.
576 void SkipUninteresting() {
577 while (current_ < limit_ && ShouldSkip(env_->values()->at(current_))) {
578 ++current_;
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000579 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000580 }
581
582 LEnvironment* env_;
583 int limit_;
584 int current_;
585};
586
587
588// Iterator for non-null, non-constant operands incl. outer environments.
589class DeepIterator BASE_EMBEDDED {
590 public:
591 explicit DeepIterator(LEnvironment* env)
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000592 : current_iterator_(env) {
593 SkipUninteresting();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000594 }
595
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000596 bool Done() { return current_iterator_.Done(); }
597
598 LOperand* Current() {
599 ASSERT(!current_iterator_.Done());
600 return current_iterator_.Current();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000601 }
602
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000603 void Advance() {
604 current_iterator_.Advance();
605 SkipUninteresting();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000606 }
607
608 private:
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000609 void SkipUninteresting() {
610 while (current_iterator_.env() != NULL && current_iterator_.Done()) {
611 current_iterator_ = ShallowIterator(current_iterator_.env()->outer());
612 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000613 }
614
615 ShallowIterator current_iterator_;
616};
617
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000618
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000619int ElementsKindToShiftSize(ElementsKind elements_kind);
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000620
621
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000622} } // namespace v8::internal
623
624#endif // V8_LITHIUM_H_