• 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 "register-allocator-inl.h"
32 
33 namespace v8 {
34 namespace 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 
48 class FrameElement BASE_EMBEDDED {
49  public:
50   enum SyncFlag {
51     NOT_SYNCED,
52     SYNCED
53   };
54 
55   // The default constructor creates an invalid frame element.
FrameElement()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.
InvalidElement()64   static FrameElement InvalidElement() {
65     FrameElement result;
66     return result;
67   }
68 
69   // Factory function to construct an in-memory frame element.
MemoryElement()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.
RegisterElement(Register reg,SyncFlag is_synced)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.
ConstantElement(Handle<Object> value,SyncFlag is_synced)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.
ClearConstantList()97   static void ClearConstantList() {
98     ConstantList()->Clear();
99   }
100 
is_synced()101   bool is_synced() const { return SyncedField::decode(value_); }
102 
set_sync()103   void set_sync() {
104     ASSERT(type() != MEMORY);
105     value_ = value_ | SyncedField::encode(true);
106   }
107 
clear_sync()108   void clear_sync() {
109     ASSERT(type() != MEMORY);
110     value_ = value_ & ~SyncedField::mask();
111   }
112 
is_valid()113   bool is_valid() const { return type() != INVALID; }
is_memory()114   bool is_memory() const { return type() == MEMORY; }
is_register()115   bool is_register() const { return type() == REGISTER; }
is_constant()116   bool is_constant() const { return type() == CONSTANT; }
is_copy()117   bool is_copy() const { return type() == COPY; }
118 
is_copied()119   bool is_copied() const { return CopiedField::decode(value_); }
set_copied()120   void set_copied() { value_ = value_ | CopiedField::encode(true); }
clear_copied()121   void clear_copied() { value_ = value_ & ~CopiedField::mask(); }
122 
reg()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 
handle()131   Handle<Object> handle() const {
132     ASSERT(is_constant());
133     return ConstantList()->at(DataField::decode(value_));
134   }
135 
index()136   int index() const {
137     ASSERT(is_copy());
138     return DataField::decode(value_);
139   }
140 
Equals(FrameElement other)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.
SameLocation(FrameElement * other)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.
Combine(FrameElement * other)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.
FrameElement(Type type,Register reg,SyncFlag is_synced)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.
FrameElement(Handle<Object> value,SyncFlag is_synced)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 
type()204   Type type() const { return TypeField::decode(value_); }
set_type(Type type)205   void set_type(Type type) {
206     value_ = value_ & ~TypeField::mask();
207     value_ = value_ | TypeField::encode(type);
208   }
209 
set_index(int new_index)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 
set_reg(Register new_reg)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_
236