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