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