1 // Copyright 2006-2008 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_SCOPEINFO_H_ 29 #define V8_SCOPEINFO_H_ 30 31 #include "variables.h" 32 #include "zone-inl.h" 33 34 namespace v8 { 35 namespace internal { 36 37 // Scope information represents information about a functions's 38 // scopes (currently only one, because we don't do any inlining) 39 // and the allocation of the scope's variables. Scope information 40 // is stored in a compressed form in FixedArray objects and is used 41 // at runtime (stack dumps, deoptimization, etc.). 42 // 43 // Historical note: In other VMs built by this team, ScopeInfo was 44 // usually called DebugInfo since the information was used (among 45 // other things) for on-demand debugging (Self, Smalltalk). However, 46 // DebugInfo seems misleading, since this information is primarily used 47 // in debugging-unrelated contexts. 48 49 // Forward defined as 50 // template <class Allocator = FreeStoreAllocationPolicy> class ScopeInfo; 51 template<class Allocator> 52 class ScopeInfo BASE_EMBEDDED { 53 public: 54 // Create a ScopeInfo instance from a scope. 55 explicit ScopeInfo(Scope* scope); 56 57 // Create a ScopeInfo instance from SerializedScopeInfo. 58 explicit ScopeInfo(SerializedScopeInfo* data); 59 60 // Creates a SerializedScopeInfo holding the serialized scope info. 61 Handle<SerializedScopeInfo> Serialize(); 62 63 // -------------------------------------------------------------------------- 64 // Lookup 65 function_name()66 Handle<String> function_name() const { return function_name_; } 67 parameter_name(int i)68 Handle<String> parameter_name(int i) const { return parameters_[i]; } number_of_parameters()69 int number_of_parameters() const { return parameters_.length(); } 70 stack_slot_name(int i)71 Handle<String> stack_slot_name(int i) const { return stack_slots_[i]; } number_of_stack_slots()72 int number_of_stack_slots() const { return stack_slots_.length(); } 73 context_slot_name(int i)74 Handle<String> context_slot_name(int i) const { 75 return context_slots_[i - Context::MIN_CONTEXT_SLOTS]; 76 } number_of_context_slots()77 int number_of_context_slots() const { 78 int l = context_slots_.length(); 79 return l == 0 ? 0 : l + Context::MIN_CONTEXT_SLOTS; 80 } 81 82 Handle<String> LocalName(int i) const; 83 int NumberOfLocals() const; 84 85 // -------------------------------------------------------------------------- 86 // Debugging support 87 88 #ifdef DEBUG 89 void Print(); 90 #endif 91 92 private: 93 Handle<String> function_name_; 94 bool calls_eval_; 95 List<Handle<String>, Allocator > parameters_; 96 List<Handle<String>, Allocator > stack_slots_; 97 List<Handle<String>, Allocator > context_slots_; 98 List<Variable::Mode, Allocator > context_modes_; 99 }; 100 101 102 // This object provides quick access to scope info details for runtime 103 // routines w/o the need to explicitly create a ScopeInfo object. 104 class SerializedScopeInfo : public FixedArray { 105 public : 106 cast(Object * object)107 static SerializedScopeInfo* cast(Object* object) { 108 ASSERT(object->IsFixedArray()); 109 return reinterpret_cast<SerializedScopeInfo*>(object); 110 } 111 112 // Does this scope call eval? 113 bool CallsEval(); 114 115 // Does this scope have an arguments shadow? HasArgumentsShadow()116 bool HasArgumentsShadow() { 117 return StackSlotIndex(GetHeap()->arguments_shadow_symbol()) >= 0; 118 } 119 120 // Return the number of stack slots for code. 121 int NumberOfStackSlots(); 122 123 // Return the number of context slots for code. 124 int NumberOfContextSlots(); 125 126 // Return if this has context slots besides MIN_CONTEXT_SLOTS; 127 bool HasHeapAllocatedLocals(); 128 129 // Lookup support for serialized scope info. Returns the 130 // the stack slot index for a given slot name if the slot is 131 // present; otherwise returns a value < 0. The name must be a symbol 132 // (canonicalized). 133 int StackSlotIndex(String* name); 134 135 // Lookup support for serialized scope info. Returns the 136 // context slot index for a given slot name if the slot is present; otherwise 137 // returns a value < 0. The name must be a symbol (canonicalized). 138 // If the slot is present and mode != NULL, sets *mode to the corresponding 139 // mode for that variable. 140 int ContextSlotIndex(String* name, Variable::Mode* mode); 141 142 // Lookup support for serialized scope info. Returns the 143 // parameter index for a given parameter name if the parameter is present; 144 // otherwise returns a value < 0. The name must be a symbol (canonicalized). 145 int ParameterIndex(String* name); 146 147 // Lookup support for serialized scope info. Returns the 148 // function context slot index if the function name is present (named 149 // function expressions, only), otherwise returns a value < 0. The name 150 // must be a symbol (canonicalized). 151 int FunctionContextSlotIndex(String* name); 152 153 static Handle<SerializedScopeInfo> Create(Scope* scope); 154 155 // Serializes empty scope info. 156 static SerializedScopeInfo* Empty(); 157 158 private: 159 160 inline Object** ContextEntriesAddr(); 161 162 inline Object** ParameterEntriesAddr(); 163 164 inline Object** StackSlotEntriesAddr(); 165 }; 166 167 168 // Cache for mapping (data, property name) into context slot index. 169 // The cache contains both positive and negative results. 170 // Slot index equals -1 means the property is absent. 171 // Cleared at startup and prior to mark sweep collection. 172 class ContextSlotCache { 173 public: 174 // Lookup context slot index for (data, name). 175 // If absent, kNotFound is returned. 176 int Lookup(Object* data, 177 String* name, 178 Variable::Mode* mode); 179 180 // Update an element in the cache. 181 void Update(Object* data, 182 String* name, 183 Variable::Mode mode, 184 int slot_index); 185 186 // Clear the cache. 187 void Clear(); 188 189 static const int kNotFound = -2; 190 private: ContextSlotCache()191 ContextSlotCache() { 192 for (int i = 0; i < kLength; ++i) { 193 keys_[i].data = NULL; 194 keys_[i].name = NULL; 195 values_[i] = kNotFound; 196 } 197 } 198 199 inline static int Hash(Object* data, String* name); 200 201 #ifdef DEBUG 202 void ValidateEntry(Object* data, 203 String* name, 204 Variable::Mode mode, 205 int slot_index); 206 #endif 207 208 static const int kLength = 256; 209 struct Key { 210 Object* data; 211 String* name; 212 }; 213 214 struct Value { ValueValue215 Value(Variable::Mode mode, int index) { 216 ASSERT(ModeField::is_valid(mode)); 217 ASSERT(IndexField::is_valid(index)); 218 value_ = ModeField::encode(mode) | IndexField::encode(index); 219 ASSERT(mode == this->mode()); 220 ASSERT(index == this->index()); 221 } 222 ValueValue223 explicit inline Value(uint32_t value) : value_(value) {} 224 rawValue225 uint32_t raw() { return value_; } 226 modeValue227 Variable::Mode mode() { return ModeField::decode(value_); } 228 indexValue229 int index() { return IndexField::decode(value_); } 230 231 // Bit fields in value_ (type, shift, size). Must be public so the 232 // constants can be embedded in generated code. 233 class ModeField: public BitField<Variable::Mode, 0, 3> {}; 234 class IndexField: public BitField<int, 3, 32-3> {}; 235 private: 236 uint32_t value_; 237 }; 238 239 Key keys_[kLength]; 240 uint32_t values_[kLength]; 241 242 friend class Isolate; 243 DISALLOW_COPY_AND_ASSIGN(ContextSlotCache); 244 }; 245 246 247 } } // namespace v8::internal 248 249 #endif // V8_SCOPEINFO_H_ 250