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_CONTEXTS_H_ 29 #define V8_CONTEXTS_H_ 30 31 namespace v8 { 32 namespace internal { 33 34 35 enum ContextLookupFlags { 36 FOLLOW_CONTEXT_CHAIN = 1, 37 FOLLOW_PROTOTYPE_CHAIN = 2, 38 39 DONT_FOLLOW_CHAINS = 0, 40 FOLLOW_CHAINS = FOLLOW_CONTEXT_CHAIN | FOLLOW_PROTOTYPE_CHAIN 41 }; 42 43 44 // Heap-allocated activation contexts. 45 // 46 // Contexts are implemented as FixedArray objects; the Context 47 // class is a convenience interface casted on a FixedArray object. 48 // 49 // Note: Context must have no virtual functions and Context objects 50 // must always be allocated via Heap::AllocateContext() or 51 // Factory::NewContext. 52 53 // Comment for special_function_table: 54 // Table for providing optimized/specialized functions. 55 // The array contains triplets [object, general_function, optimized_function]. 56 // Primarily added to support built-in optimized variants of 57 // Array.prototype.{push,pop}. 58 59 #define GLOBAL_CONTEXT_FIELDS(V) \ 60 V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \ 61 V(SECURITY_TOKEN_INDEX, Object, security_token) \ 62 V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \ 63 V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \ 64 V(STRING_FUNCTION_INDEX, JSFunction, string_function) \ 65 V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \ 66 V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \ 67 V(DATE_FUNCTION_INDEX, JSFunction, date_function) \ 68 V(JSON_OBJECT_INDEX, JSObject, json_object) \ 69 V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \ 70 V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \ 71 V(CREATE_DATE_FUN_INDEX, JSFunction, create_date_fun) \ 72 V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \ 73 V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \ 74 V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \ 75 V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \ 76 V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \ 77 V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \ 78 V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \ 79 V(TO_BOOLEAN_FUN_INDEX, JSFunction, to_boolean_fun) \ 80 V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \ 81 V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \ 82 V(FUNCTION_MAP_INDEX, Map, function_map) \ 83 V(FUNCTION_INSTANCE_MAP_INDEX, Map, function_instance_map) \ 84 V(JS_ARRAY_MAP_INDEX, Map, js_array_map)\ 85 V(SPECIAL_FUNCTION_TABLE_INDEX, FixedArray, special_function_table) \ 86 V(ARGUMENTS_BOILERPLATE_INDEX, JSObject, arguments_boilerplate) \ 87 V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners) \ 88 V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun) \ 89 V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun) \ 90 V(CONFIGURE_GLOBAL_INDEX, JSFunction, configure_global_fun) \ 91 V(FUNCTION_CACHE_INDEX, JSObject, function_cache) \ 92 V(RUNTIME_CONTEXT_INDEX, Context, runtime_context) \ 93 V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \ 94 V(CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, JSFunction, \ 95 call_as_constructor_delegate) \ 96 V(EMPTY_SCRIPT_INDEX, Script, empty_script) \ 97 V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \ 98 V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \ 99 V(OUT_OF_MEMORY_INDEX, Object, out_of_memory) \ 100 V(MAP_CACHE_INDEX, Object, map_cache) \ 101 V(CONTEXT_DATA_INDEX, Object, data) 102 103 // JSFunctions are pairs (context, function code), sometimes also called 104 // closures. A Context object is used to represent function contexts and 105 // dynamically pushed 'with' contexts (or 'scopes' in ECMA-262 speak). 106 // 107 // At runtime, the contexts build a stack in parallel to the execution 108 // stack, with the top-most context being the current context. All contexts 109 // have the following slots: 110 // 111 // [ closure ] This is the current function. It is the same for all 112 // contexts inside a function. It provides access to the 113 // incoming context (i.e., the outer context, which may 114 // or may not become the current function's context), and 115 // it provides access to the functions code and thus it's 116 // scope information, which in turn contains the names of 117 // statically allocated context slots. The names are needed 118 // for dynamic lookups in the presence of 'with' or 'eval'. 119 // 120 // [ fcontext ] A pointer to the innermost enclosing function context. 121 // It is the same for all contexts *allocated* inside a 122 // function, and the function context's fcontext points 123 // to itself. It is only needed for fast access of the 124 // function context (used for declarations, and static 125 // context slot access). 126 // 127 // [ previous ] A pointer to the previous context. It is NULL for 128 // function contexts, and non-NULL for 'with' contexts. 129 // Used to implement the 'with' statement. 130 // 131 // [ extension ] A pointer to an extension JSObject, or NULL. Used to 132 // implement 'with' statements and dynamic declarations 133 // (through 'eval'). The object in a 'with' statement is 134 // stored in the extension slot of a 'with' context. 135 // Dynamically declared variables/functions are also added 136 // to lazily allocated extension object. Context::Lookup 137 // searches the extension object for properties. 138 // 139 // [ global ] A pointer to the global object. Provided for quick 140 // access to the global object from inside the code (since 141 // we always have a context pointer). 142 // 143 // In addition, function contexts may have statically allocated context slots 144 // to store local variables/functions that are accessed from inner functions 145 // (via static context addresses) or through 'eval' (dynamic context lookups). 146 // Finally, the global context contains additional slots for fast access to 147 // global properties. 148 // 149 // We may be able to simplify the implementation: 150 // 151 // - We may be able to get rid of 'fcontext': We can always use the fact that 152 // previous == NULL for function contexts and so we can search for them. They 153 // are only needed when doing dynamic declarations, and the context chains 154 // tend to be very very short (depth of nesting of 'with' statements). At 155 // the moment we also use it in generated code for context slot accesses - 156 // and there we don't want a loop because of code bloat - but we may not 157 // need it there after all (see comment in codegen_*.cc). 158 // 159 // - If we cannot get rid of fcontext, consider making 'previous' never NULL 160 // except for the global context. This could simplify Context::Lookup. 161 162 class Context: public FixedArray { 163 public: 164 // Conversions. cast(Object * context)165 static Context* cast(Object* context) { 166 ASSERT(context->IsContext()); 167 return reinterpret_cast<Context*>(context); 168 } 169 170 // The default context slot layout; indices are FixedArray slot indices. 171 enum { 172 // These slots are in all contexts. 173 CLOSURE_INDEX, 174 FCONTEXT_INDEX, 175 PREVIOUS_INDEX, 176 EXTENSION_INDEX, 177 GLOBAL_INDEX, 178 MIN_CONTEXT_SLOTS, 179 180 // These slots are only in global contexts. 181 GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS, 182 SECURITY_TOKEN_INDEX, 183 ARGUMENTS_BOILERPLATE_INDEX, 184 JS_ARRAY_MAP_INDEX, 185 FUNCTION_MAP_INDEX, 186 FUNCTION_INSTANCE_MAP_INDEX, 187 INITIAL_OBJECT_PROTOTYPE_INDEX, 188 BOOLEAN_FUNCTION_INDEX, 189 NUMBER_FUNCTION_INDEX, 190 STRING_FUNCTION_INDEX, 191 OBJECT_FUNCTION_INDEX, 192 ARRAY_FUNCTION_INDEX, 193 DATE_FUNCTION_INDEX, 194 JSON_OBJECT_INDEX, 195 REGEXP_FUNCTION_INDEX, 196 CREATE_DATE_FUN_INDEX, 197 TO_NUMBER_FUN_INDEX, 198 TO_STRING_FUN_INDEX, 199 TO_DETAIL_STRING_FUN_INDEX, 200 TO_OBJECT_FUN_INDEX, 201 TO_INTEGER_FUN_INDEX, 202 TO_UINT32_FUN_INDEX, 203 TO_INT32_FUN_INDEX, 204 TO_BOOLEAN_FUN_INDEX, 205 INSTANTIATE_FUN_INDEX, 206 CONFIGURE_INSTANCE_FUN_INDEX, 207 SPECIAL_FUNCTION_TABLE_INDEX, 208 MESSAGE_LISTENERS_INDEX, 209 MAKE_MESSAGE_FUN_INDEX, 210 GET_STACK_TRACE_LINE_INDEX, 211 CONFIGURE_GLOBAL_INDEX, 212 FUNCTION_CACHE_INDEX, 213 RUNTIME_CONTEXT_INDEX, 214 CALL_AS_FUNCTION_DELEGATE_INDEX, 215 CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, 216 EMPTY_SCRIPT_INDEX, 217 SCRIPT_FUNCTION_INDEX, 218 CONTEXT_EXTENSION_FUNCTION_INDEX, 219 OUT_OF_MEMORY_INDEX, 220 MAP_CACHE_INDEX, 221 CONTEXT_DATA_INDEX, 222 GLOBAL_CONTEXT_SLOTS 223 }; 224 225 // Direct slot access. closure()226 JSFunction* closure() { return JSFunction::cast(get(CLOSURE_INDEX)); } set_closure(JSFunction * closure)227 void set_closure(JSFunction* closure) { set(CLOSURE_INDEX, closure); } 228 fcontext()229 Context* fcontext() { return Context::cast(get(FCONTEXT_INDEX)); } set_fcontext(Context * context)230 void set_fcontext(Context* context) { set(FCONTEXT_INDEX, context); } 231 previous()232 Context* previous() { 233 Object* result = unchecked_previous(); 234 ASSERT(IsBootstrappingOrContext(result)); 235 return reinterpret_cast<Context*>(result); 236 } set_previous(Context * context)237 void set_previous(Context* context) { set(PREVIOUS_INDEX, context); } 238 has_extension()239 bool has_extension() { return unchecked_extension() != NULL; } extension()240 JSObject* extension() { return JSObject::cast(unchecked_extension()); } set_extension(JSObject * object)241 void set_extension(JSObject* object) { set(EXTENSION_INDEX, object); } 242 global()243 GlobalObject* global() { 244 Object* result = get(GLOBAL_INDEX); 245 ASSERT(IsBootstrappingOrGlobalObject(result)); 246 return reinterpret_cast<GlobalObject*>(result); 247 } set_global(GlobalObject * global)248 void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); } 249 250 // Returns a JSGlobalProxy object or null. 251 JSObject* global_proxy(); 252 void set_global_proxy(JSObject* global); 253 254 // The builtins object. 255 JSBuiltinsObject* builtins(); 256 257 // Compute the global context by traversing the context chain. 258 Context* global_context(); 259 260 // Tells if this is a function context (as opposed to a 'with' context). is_function_context()261 bool is_function_context() { return unchecked_previous() == NULL; } 262 263 // Tells whether the global context is marked with out of memory. has_out_of_memory()264 bool has_out_of_memory() { 265 return global_context()->out_of_memory() == Heap::true_value(); 266 } 267 268 // Mark the global context with out of memory. mark_out_of_memory()269 void mark_out_of_memory() { 270 global_context()->set_out_of_memory(Heap::true_value()); 271 } 272 273 // The exception holder is the object used as a with object in 274 // the implementation of a catch block. is_exception_holder(Object * object)275 bool is_exception_holder(Object* object) { 276 return IsCatchContext() && extension() == object; 277 } 278 279 #define GLOBAL_CONTEXT_FIELD_ACCESSORS(index, type, name) \ 280 void set_##name(type* value) { \ 281 ASSERT(IsGlobalContext()); \ 282 set(index, value); \ 283 } \ 284 type* name() { \ 285 ASSERT(IsGlobalContext()); \ 286 return type::cast(get(index)); \ 287 } 288 GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSORS) 289 #undef GLOBAL_CONTEXT_FIELD_ACCESSORS 290 291 // Lookup the the slot called name, starting with the current context. 292 // There are 4 possible outcomes: 293 // 294 // 1) index_ >= 0 && result->IsContext(): 295 // most common case, the result is a Context, and index is the 296 // context slot index, and the slot exists. 297 // attributes == READ_ONLY for the function name variable, NONE otherwise. 298 // 299 // 2) index_ >= 0 && result->IsJSObject(): 300 // the result is the JSObject arguments object, the index is the parameter 301 // index, i.e., key into the arguments object, and the property exists. 302 // attributes != ABSENT. 303 // 304 // 3) index_ < 0 && result->IsJSObject(): 305 // the result is the JSObject extension context or the global object, 306 // and the name is the property name, and the property exists. 307 // attributes != ABSENT. 308 // 309 // 4) index_ < 0 && result.is_null(): 310 // there was no context found with the corresponding property. 311 // attributes == ABSENT. 312 Handle<Object> Lookup(Handle<String> name, ContextLookupFlags flags, 313 int* index_, PropertyAttributes* attributes); 314 315 // Determine if a local variable with the given name exists in a 316 // context. Do not consider context extension objects. This is 317 // used for compiling code using eval. If the context surrounding 318 // the eval call does not have a local variable with this name and 319 // does not contain a with statement the property is global unless 320 // it is shadowed by a property in an extension object introduced by 321 // eval. 322 bool GlobalIfNotShadowedByEval(Handle<String> name); 323 324 // Code generation support. SlotOffset(int index)325 static int SlotOffset(int index) { 326 return kHeaderSize + index * kPointerSize - kHeapObjectTag; 327 } 328 329 private: 330 // Unchecked access to the slots. unchecked_previous()331 Object* unchecked_previous() { return get(PREVIOUS_INDEX); } unchecked_extension()332 Object* unchecked_extension() { return get(EXTENSION_INDEX); } 333 334 #ifdef DEBUG 335 // Bootstrapping-aware type checks. 336 static bool IsBootstrappingOrContext(Object* object); 337 static bool IsBootstrappingOrGlobalObject(Object* object); 338 #endif 339 }; 340 341 } } // namespace v8::internal 342 343 #endif // V8_CONTEXTS_H_ 344