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