blob: ccdecf1d6672bb24eeeac100f832019a2238091c [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2009 the V8 project authors. All rights reserved.
2// 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_FRAME_ELEMENT_H_
29#define V8_FRAME_ELEMENT_H_
30
31#include "register-allocator-inl.h"
32
33namespace v8 {
34namespace internal {
35
36// -------------------------------------------------------------------------
37// Virtual frame elements
38//
39// The internal elements of the virtual frames. There are several kinds of
40// elements:
41// * Invalid: elements that are uninitialized or not actually part
42// of the virtual frame. They should not be read.
43// * Memory: an element that resides in the actual frame. Its address is
44// given by its position in the virtual frame.
45// * Register: an element that resides in a register.
46// * Constant: an element whose value is known at compile time.
47
48class FrameElement BASE_EMBEDDED {
49 public:
50 enum SyncFlag {
51 NOT_SYNCED,
52 SYNCED
53 };
54
55 // The default constructor creates an invalid frame element.
56 FrameElement() {
57 value_ = TypeField::encode(INVALID)
58 | CopiedField::encode(false)
59 | SyncedField::encode(false)
60 | DataField::encode(0);
61 }
62
63 // Factory function to construct an invalid frame element.
64 static FrameElement InvalidElement() {
65 FrameElement result;
66 return result;
67 }
68
69 // Factory function to construct an in-memory frame element.
70 static FrameElement MemoryElement() {
71 FrameElement result(MEMORY, no_reg, SYNCED);
72 return result;
73 }
74
75 // Factory function to construct an in-register frame element.
76 static FrameElement RegisterElement(Register reg,
77 SyncFlag is_synced) {
78 return FrameElement(REGISTER, reg, is_synced);
79 }
80
81 // Factory function to construct a frame element whose value is known at
82 // compile time.
83 static FrameElement ConstantElement(Handle<Object> value,
84 SyncFlag is_synced) {
85 FrameElement result(value, is_synced);
86 return result;
87 }
88
89 // Static indirection table for handles to constants. If a frame
90 // element represents a constant, the data contains an index into
91 // this table of handles to the actual constants.
92 typedef ZoneList<Handle<Object> > ZoneObjectList;
93
94 static ZoneObjectList* ConstantList();
95
96 // Clear the constants indirection table.
97 static void ClearConstantList() {
98 ConstantList()->Clear();
99 }
100
101 bool is_synced() const { return SyncedField::decode(value_); }
102
103 void set_sync() {
104 ASSERT(type() != MEMORY);
105 value_ = value_ | SyncedField::encode(true);
106 }
107
108 void clear_sync() {
109 ASSERT(type() != MEMORY);
110 value_ = value_ & ~SyncedField::mask();
111 }
112
113 bool is_valid() const { return type() != INVALID; }
114 bool is_memory() const { return type() == MEMORY; }
115 bool is_register() const { return type() == REGISTER; }
116 bool is_constant() const { return type() == CONSTANT; }
117 bool is_copy() const { return type() == COPY; }
118
119 bool is_copied() const { return CopiedField::decode(value_); }
120 void set_copied() { value_ = value_ | CopiedField::encode(true); }
121 void clear_copied() { value_ = value_ & ~CopiedField::mask(); }
122
123 Register reg() const {
124 ASSERT(is_register());
125 uint32_t reg = DataField::decode(value_);
126 Register result;
127 result.code_ = reg;
128 return result;
129 }
130
131 Handle<Object> handle() const {
132 ASSERT(is_constant());
133 return ConstantList()->at(DataField::decode(value_));
134 }
135
136 int index() const {
137 ASSERT(is_copy());
138 return DataField::decode(value_);
139 }
140
141 bool Equals(FrameElement other) {
142 uint32_t masked_difference = (value_ ^ other.value_) & ~CopiedField::mask();
143 if (!masked_difference) {
144 // The elements are equal if they agree exactly except on copied field.
145 return true;
146 } else {
147 // If two constants have the same value, and agree otherwise, return true.
148 return !(masked_difference & ~DataField::mask()) &&
149 is_constant() &&
150 handle().is_identical_to(other.handle());
151 }
152 }
153
154 // Test if two FrameElements refer to the same memory or register location.
155 bool SameLocation(FrameElement* other) {
156 if (type() == other->type()) {
157 if (value_ == other->value_) return true;
158 if (is_constant() && handle().is_identical_to(other->handle())) {
159 return true;
160 }
161 }
162 return false;
163 }
164
165 // Given a pair of non-null frame element pointers, return one of them
166 // as an entry frame candidate or null if they are incompatible.
167 FrameElement* Combine(FrameElement* other) {
168 // If either is invalid, the result is.
169 if (!is_valid()) return this;
170 if (!other->is_valid()) return other;
171
172 if (!SameLocation(other)) return NULL;
173 // If either is unsynced, the result is.
174 FrameElement* result = is_synced() ? other : this;
175 return result;
176 }
177
178 private:
179 enum Type {
180 INVALID,
181 MEMORY,
182 REGISTER,
183 CONSTANT,
184 COPY
185 };
186
187 // Used to construct memory and register elements.
188 FrameElement(Type type, Register reg, SyncFlag is_synced) {
189 value_ = TypeField::encode(type)
190 | CopiedField::encode(false)
191 | SyncedField::encode(is_synced != NOT_SYNCED)
192 | DataField::encode(reg.code_ > 0 ? reg.code_ : 0);
193 }
194
195 // Used to construct constant elements.
196 FrameElement(Handle<Object> value, SyncFlag is_synced) {
197 value_ = TypeField::encode(CONSTANT)
198 | CopiedField::encode(false)
199 | SyncedField::encode(is_synced != NOT_SYNCED)
200 | DataField::encode(ConstantList()->length());
201 ConstantList()->Add(value);
202 }
203
204 Type type() const { return TypeField::decode(value_); }
205 void set_type(Type type) {
206 value_ = value_ & ~TypeField::mask();
207 value_ = value_ | TypeField::encode(type);
208 }
209
210 void set_index(int new_index) {
211 ASSERT(is_copy());
212 value_ = value_ & ~DataField::mask();
213 value_ = value_ | DataField::encode(new_index);
214 }
215
216 void set_reg(Register new_reg) {
217 ASSERT(is_register());
218 value_ = value_ & ~DataField::mask();
219 value_ = value_ | DataField::encode(new_reg.code_);
220 }
221
222 // Encode type, copied, synced and data in one 32 bit integer.
223 uint32_t value_;
224
225 class TypeField: public BitField<Type, 0, 3> {};
226 class CopiedField: public BitField<uint32_t, 3, 1> {};
227 class SyncedField: public BitField<uint32_t, 4, 1> {};
228 class DataField: public BitField<uint32_t, 5, 32 - 6> {};
229
230 friend class VirtualFrame;
231};
232
233} } // namespace v8::internal
234
235#endif // V8_FRAME_ELEMENT_H_