OLD | NEW |
| (Empty) |
1 // 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 | |
33 namespace v8 { namespace internal { | |
34 | |
35 // ------------------------------------------------------------------------- | |
36 // Virtual frame elements | |
37 // | |
38 // The internal elements of the virtual frames. There are several kinds of | |
39 // elements: | |
40 // * Invalid: elements that are uninitialized or not actually part | |
41 // of the virtual frame. They should not be read. | |
42 // * Memory: an element that resides in the actual frame. Its address is | |
43 // given by its position in the virtual frame. | |
44 // * Register: an element that resides in a register. | |
45 // * Constant: an element whose value is known at compile time. | |
46 | |
47 class FrameElement BASE_EMBEDDED { | |
48 public: | |
49 enum SyncFlag { | |
50 NOT_SYNCED, | |
51 SYNCED | |
52 }; | |
53 | |
54 // The default constructor creates an invalid frame element. | |
55 FrameElement() { | |
56 value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE) | |
57 | 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 StaticType static_type = StaticType()) { | |
79 return FrameElement(REGISTER, reg, is_synced, static_type); | |
80 } | |
81 | |
82 // Factory function to construct a frame element whose value is known at | |
83 // compile time. | |
84 static FrameElement ConstantElement(Handle<Object> value, | |
85 SyncFlag is_synced) { | |
86 FrameElement result(value, is_synced); | |
87 return result; | |
88 } | |
89 | |
90 // Static indirection table for handles to constants. If a frame | |
91 // element represents a constant, the data contains an index into | |
92 // this table of handles to the actual constants. | |
93 typedef ZoneList<Handle<Object> > ZoneObjectList; | |
94 | |
95 static ZoneObjectList* ConstantList() { | |
96 static ZoneObjectList list(10); | |
97 return &list; | |
98 } | |
99 | |
100 // Clear the constants indirection table. | |
101 static void ClearConstantList() { | |
102 ConstantList()->Clear(); | |
103 } | |
104 | |
105 bool is_synced() const { return SyncedField::decode(value_); } | |
106 | |
107 void set_sync() { | |
108 ASSERT(type() != MEMORY); | |
109 value_ = value_ | SyncedField::encode(true); | |
110 } | |
111 | |
112 void clear_sync() { | |
113 ASSERT(type() != MEMORY); | |
114 value_ = value_ & ~SyncedField::mask(); | |
115 } | |
116 | |
117 bool is_valid() const { return type() != INVALID; } | |
118 bool is_memory() const { return type() == MEMORY; } | |
119 bool is_register() const { return type() == REGISTER; } | |
120 bool is_constant() const { return type() == CONSTANT; } | |
121 bool is_copy() const { return type() == COPY; } | |
122 | |
123 bool is_copied() const { return CopiedField::decode(value_); } | |
124 void set_copied() { value_ = value_ | CopiedField::encode(true); } | |
125 void clear_copied() { value_ = value_ & ~CopiedField::mask(); } | |
126 | |
127 Register reg() const { | |
128 ASSERT(is_register()); | |
129 uint32_t reg = DataField::decode(value_); | |
130 Register result; | |
131 result.code_ = reg; | |
132 return result; | |
133 } | |
134 | |
135 Handle<Object> handle() const { | |
136 ASSERT(is_constant()); | |
137 return ConstantList()->at(DataField::decode(value_)); | |
138 } | |
139 | |
140 int index() const { | |
141 ASSERT(is_copy()); | |
142 return DataField::decode(value_); | |
143 } | |
144 | |
145 StaticType static_type() { | |
146 return StaticType(StaticTypeField::decode(value_)); | |
147 } | |
148 | |
149 void set_static_type(StaticType static_type) { | |
150 value_ = value_ & ~StaticTypeField::mask(); | |
151 value_ = value_ | StaticTypeField::encode(static_type.static_type_); | |
152 } | |
153 | |
154 bool Equals(FrameElement other) { | |
155 if (value_ == other.value_) return true; | |
156 | |
157 if (type() != other.type() || | |
158 is_copied() != other.is_copied() || | |
159 is_synced() != other.is_synced()) return false; | |
160 | |
161 if (is_register()) { | |
162 if (!reg().is(other.reg())) return false; | |
163 } else if (is_constant()) { | |
164 if (!handle().is_identical_to(other.handle())) return false; | |
165 } else if (is_copy()) { | |
166 if (index() != other.index()) return false; | |
167 } | |
168 | |
169 return true; | |
170 } | |
171 | |
172 // Given a pair of non-null frame element pointers, return one of them | |
173 // as an entry frame candidate or null if they are incompatible. | |
174 FrameElement* Combine(FrameElement* other) { | |
175 // If either is invalid, the result is. | |
176 if (!is_valid()) return this; | |
177 if (!other->is_valid()) return other; | |
178 | |
179 // If they do not have the exact same location we reallocate. | |
180 bool not_same_location = | |
181 (type() != other->type()) || | |
182 (is_register() && !reg().is(other->reg())) || | |
183 (is_constant() && !handle().is_identical_to(other->handle())) || | |
184 (is_copy() && index() != other->index()); | |
185 if (not_same_location) return NULL; | |
186 | |
187 // If either is unsynced, the result is. The result static type is | |
188 // the merge of the static types. It's safe to set it on one of the | |
189 // frame elements, and harmless too (because we are only going to | |
190 // merge the reaching frames and will ensure that the types are | |
191 // coherent, and changing the static type does not emit code). | |
192 FrameElement* result = is_synced() ? other : this; | |
193 result->set_static_type(static_type().merge(other->static_type())); | |
194 return result; | |
195 } | |
196 | |
197 private: | |
198 enum Type { | |
199 INVALID, | |
200 MEMORY, | |
201 REGISTER, | |
202 CONSTANT, | |
203 COPY | |
204 }; | |
205 | |
206 // Used to construct memory and register elements. | |
207 FrameElement(Type type, Register reg, SyncFlag is_synced) { | |
208 value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE) | |
209 | TypeField::encode(type) | |
210 | CopiedField::encode(false) | |
211 | SyncedField::encode(is_synced != NOT_SYNCED) | |
212 | DataField::encode(reg.code_ > 0 ? reg.code_ : 0); | |
213 } | |
214 | |
215 FrameElement(Type type, Register reg, SyncFlag is_synced, StaticType stype) { | |
216 value_ = StaticTypeField::encode(stype.static_type_) | |
217 | TypeField::encode(type) | |
218 | CopiedField::encode(false) | |
219 | SyncedField::encode(is_synced != NOT_SYNCED) | |
220 | DataField::encode(reg.code_ > 0 ? reg.code_ : 0); | |
221 } | |
222 | |
223 // Used to construct constant elements. | |
224 FrameElement(Handle<Object> value, SyncFlag is_synced) { | |
225 value_ = StaticTypeField::encode(StaticType::TypeOf(*value).static_type_) | |
226 | TypeField::encode(CONSTANT) | |
227 | CopiedField::encode(false) | |
228 | SyncedField::encode(is_synced != NOT_SYNCED) | |
229 | DataField::encode(ConstantList()->length()); | |
230 ConstantList()->Add(value); | |
231 } | |
232 | |
233 Type type() const { return TypeField::decode(value_); } | |
234 void set_type(Type type) { | |
235 value_ = value_ & ~TypeField::mask(); | |
236 value_ = value_ | TypeField::encode(type); | |
237 } | |
238 | |
239 void set_index(int new_index) { | |
240 ASSERT(is_copy()); | |
241 value_ = value_ & ~DataField::mask(); | |
242 value_ = value_ | DataField::encode(new_index); | |
243 } | |
244 | |
245 void set_reg(Register new_reg) { | |
246 ASSERT(is_register()); | |
247 value_ = value_ & ~DataField::mask(); | |
248 value_ = value_ | DataField::encode(new_reg.code_); | |
249 } | |
250 | |
251 // Encode static type, type, copied, synced and data in one 32 bit integer. | |
252 uint32_t value_; | |
253 | |
254 class StaticTypeField: public BitField<StaticType::StaticTypeEnum, 0, 3> {}; | |
255 class TypeField: public BitField<Type, 3, 3> {}; | |
256 class CopiedField: public BitField<uint32_t, 6, 1> {}; | |
257 class SyncedField: public BitField<uint32_t, 7, 1> {}; | |
258 class DataField: public BitField<uint32_t, 8, 32 - 9> {}; | |
259 | |
260 friend class VirtualFrame; | |
261 }; | |
262 | |
263 } } // namespace v8::internal | |
264 | |
265 #endif // V8_FRAME_ELEMENT_H_ | |
OLD | NEW |