1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * 3 * ***** BEGIN LICENSE BLOCK ***** 4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 * 6 * The contents of this file are subject to the Mozilla Public License Version 7 * 1.1 (the "License"); you may not use this file except in compliance with 8 * the License. You may obtain a copy of the License at 9 * http://www.mozilla.org/MPL/ 10 * 11 * Software distributed under the License is distributed on an "AS IS" basis, 12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 * for the specific language governing rights and limitations under the 14 * License. 15 * 16 * The Original Code is Mozilla Communicator client code, released 17 * March 31, 1998. 18 * 19 * The Initial Developer of the Original Code is 20 * Netscape Communications Corporation. 21 * Portions created by the Initial Developer are Copyright (C) 1998 22 * the Initial Developer. All Rights Reserved. 23 * 24 * Contributor(s): 25 * 26 * Alternatively, the contents of this file may be used under the terms of 27 * either of the GNU General Public License Version 2 or later (the "GPL"), 28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 * in which case the provisions of the GPL or the LGPL are applicable instead 30 * of those above. If you wish to allow use of your version of this file only 31 * under the terms of either the GPL or the LGPL, and not to allow others to 32 * use your version of this file under the terms of the MPL, indicate your 33 * decision by deleting the provisions above and replace them with the notice 34 * and other provisions required by the GPL or the LGPL. If you do not delete 35 * the provisions above, a recipient may use your version of this file under 36 * the terms of any one of the MPL, the GPL or the LGPL. 37 * 38 * ***** END LICENSE BLOCK ***** */ 39 40 #ifndef jsinterp_h___ 41 #define jsinterp_h___ 42 /* 43 * JS interpreter interface. 44 */ 45 #include "jsprvtd.h" 46 #include "jspubtd.h" 47 48 JS_BEGIN_EXTERN_C 49 50 /* 51 * JS stack frame, may be allocated on the C stack by native callers. Always 52 * allocated on cx->stackPool for calls from the interpreter to an interpreted 53 * function. 54 * 55 * NB: This struct is manually initialized in jsinterp.c and jsiter.c. If you 56 * add new members, update both files. But first, try to remove members. The 57 * sharp* and xml* members should be moved onto the stack as local variables 58 * with well-known slots, if possible. 59 */ 60 struct JSStackFrame { 61 JSObject *callobj; /* lazily created Call object */ 62 JSObject *argsobj; /* lazily created arguments object */ 63 JSObject *varobj; /* variables object, where vars go */ 64 JSScript *script; /* script being interpreted */ 65 JSFunction *fun; /* function being called or null */ 66 JSObject *thisp; /* "this" pointer if in method */ 67 uintN argc; /* actual argument count */ 68 jsval *argv; /* base of argument stack slots */ 69 jsval rval; /* function return value */ 70 uintN nvars; /* local variable count */ 71 jsval *vars; /* base of variable stack slots */ 72 JSStackFrame *down; /* previous frame */ 73 void *annotation; /* used by Java security */ 74 JSObject *scopeChain; /* scope chain */ 75 jsbytecode *pc; /* program counter */ 76 jsval *sp; /* stack pointer */ 77 jsval *spbase; /* operand stack base */ 78 uintN sharpDepth; /* array/object initializer depth */ 79 JSObject *sharpArray; /* scope for #n= initializer vars */ 80 uint32 flags; /* frame flags -- see below */ 81 JSStackFrame *dormantNext; /* next dormant frame chain */ 82 JSObject *xmlNamespace; /* null or default xml namespace in E4X */ 83 JSObject *blockChain; /* active compile-time block scopes */ 84 }; 85 86 typedef struct JSInlineFrame { 87 JSStackFrame frame; /* base struct */ 88 jsval *rvp; /* ptr to caller's return value slot */ 89 void *mark; /* mark before inline frame */ 90 void *hookData; /* debugger call hook data */ 91 JSVersion callerVersion; /* dynamic version of calling script */ 92 } JSInlineFrame; 93 94 /* JS stack frame flags. */ 95 #define JSFRAME_CONSTRUCTING 0x01 /* frame is for a constructor invocation */ 96 #define JSFRAME_INTERNAL 0x02 /* internal call, not invoked by a script */ 97 #define JSFRAME_SKIP_CALLER 0x04 /* skip one link when evaluating f.caller 98 for this invocation of f */ 99 #define JSFRAME_ASSIGNING 0x08 /* a complex (not simplex JOF_ASSIGNING) op 100 is currently assigning to a property */ 101 #define JSFRAME_DEBUGGER 0x10 /* frame for JS_EvaluateInStackFrame */ 102 #define JSFRAME_EVAL 0x20 /* frame for obj_eval */ 103 #define JSFRAME_SPECIAL 0x30 /* special evaluation frame flags */ 104 #define JSFRAME_COMPILING 0x40 /* frame is being used by compiler */ 105 #define JSFRAME_COMPILE_N_GO 0x80 /* compiler-and-go mode, can optimize name 106 references based on scope chain */ 107 #define JSFRAME_SCRIPT_OBJECT 0x100 /* compiling source for a Script object */ 108 #define JSFRAME_YIELDING 0x200 /* js_Interpret dispatched JSOP_YIELD */ 109 #define JSFRAME_FILTERING 0x400 /* XML filtering predicate expression */ 110 #define JSFRAME_ITERATOR 0x800 /* trying to get an iterator for for-in */ 111 #define JSFRAME_POP_BLOCKS 0x1000 /* scope chain contains blocks to pop */ 112 #define JSFRAME_GENERATOR 0x2000 /* frame belongs to generator-iterator */ 113 114 #define JSFRAME_OVERRIDE_SHIFT 24 /* override bit-set params; see jsfun.c */ 115 #define JSFRAME_OVERRIDE_BITS 8 116 117 /* 118 * Property cache for quickened get/set property opcodes. 119 */ 120 #define PROPERTY_CACHE_LOG2 10 121 #define PROPERTY_CACHE_SIZE JS_BIT(PROPERTY_CACHE_LOG2) 122 #define PROPERTY_CACHE_MASK JS_BITMASK(PROPERTY_CACHE_LOG2) 123 124 #define PROPERTY_CACHE_HASH(obj, id) \ 125 ((((jsuword)(obj) >> JSVAL_TAGBITS) ^ (jsuword)(id)) & PROPERTY_CACHE_MASK) 126 127 #ifdef JS_THREADSAFE 128 129 #if HAVE_ATOMIC_DWORD_ACCESS 130 131 #define PCE_LOAD(cache, pce, entry) JS_ATOMIC_DWORD_LOAD(pce, entry) 132 #define PCE_STORE(cache, pce, entry) JS_ATOMIC_DWORD_STORE(pce, entry) 133 134 #else /* !HAVE_ATOMIC_DWORD_ACCESS */ 135 136 #define JS_PROPERTY_CACHE_METERING 1 137 138 #define PCE_LOAD(cache, pce, entry) \ 139 JS_BEGIN_MACRO \ 140 uint32 prefills_; \ 141 uint32 fills_ = (cache)->fills; \ 142 do { \ 143 /* Load until cache->fills is stable (see FILL macro below). */ \ 144 prefills_ = fills_; \ 145 (entry) = *(pce); \ 146 } while ((fills_ = (cache)->fills) != prefills_); \ 147 JS_END_MACRO 148 149 #define PCE_STORE(cache, pce, entry) \ 150 JS_BEGIN_MACRO \ 151 do { \ 152 /* Store until no racing collider stores half or all of pce. */ \ 153 *(pce) = (entry); \ 154 } while (PCE_OBJECT(*pce) != PCE_OBJECT(entry) || \ 155 PCE_PROPERTY(*pce) != PCE_PROPERTY(entry)); \ 156 JS_END_MACRO 157 158 #endif /* !HAVE_ATOMIC_DWORD_ACCESS */ 159 160 #else /* !JS_THREADSAFE */ 161 162 #define PCE_LOAD(cache, pce, entry) ((entry) = *(pce)) 163 #define PCE_STORE(cache, pce, entry) (*(pce) = (entry)) 164 165 #endif /* !JS_THREADSAFE */ 166 167 typedef union JSPropertyCacheEntry { 168 struct { 169 JSObject *object; /* weak link to object */ 170 JSScopeProperty *property; /* weak link to property */ 171 } s; 172 #ifdef HAVE_ATOMIC_DWORD_ACCESS 173 prdword align; 174 #endif 175 } JSPropertyCacheEntry; 176 177 /* These may be called in lvalue or rvalue position. */ 178 #define PCE_OBJECT(entry) ((entry).s.object) 179 #define PCE_PROPERTY(entry) ((entry).s.property) 180 181 typedef struct JSPropertyCache { 182 JSPropertyCacheEntry table[PROPERTY_CACHE_SIZE]; 183 JSBool empty; 184 JSBool disabled; 185 #ifdef JS_PROPERTY_CACHE_METERING 186 uint32 fills; 187 uint32 recycles; 188 uint32 tests; 189 uint32 misses; 190 uint32 flushes; 191 # define PCMETER(x) x 192 #else 193 # define PCMETER(x) /* nothing */ 194 #endif 195 } JSPropertyCache; 196 197 #define PROPERTY_CACHE_FILL(cache, obj, id, sprop) \ 198 JS_BEGIN_MACRO \ 199 JSPropertyCache *cache_ = (cache); \ 200 if (!cache_->disabled) { \ 201 uintN hashIndex_ = (uintN) PROPERTY_CACHE_HASH(obj, id); \ 202 JSPropertyCacheEntry *pce_ = &cache_->table[hashIndex_]; \ 203 JSPropertyCacheEntry entry_; \ 204 JSScopeProperty *pce_sprop_; \ 205 PCE_LOAD(cache_, pce_, entry_); \ 206 pce_sprop_ = PCE_PROPERTY(entry_); \ 207 PCMETER(if (pce_sprop_ && pce_sprop_ != sprop) \ 208 cache_->recycles++); \ 209 PCE_OBJECT(entry_) = obj; \ 210 PCE_PROPERTY(entry_) = sprop; \ 211 cache_->empty = JS_FALSE; \ 212 PCMETER(cache_->fills++); \ 213 PCE_STORE(cache_, pce_, entry_); \ 214 } \ 215 JS_END_MACRO 216 217 #define PROPERTY_CACHE_TEST(cache, obj, id, sprop) \ 218 JS_BEGIN_MACRO \ 219 uintN hashIndex_ = (uintN) PROPERTY_CACHE_HASH(obj, id); \ 220 JSPropertyCache *cache_ = (cache); \ 221 JSPropertyCacheEntry *pce_ = &cache_->table[hashIndex_]; \ 222 JSPropertyCacheEntry entry_; \ 223 JSScopeProperty *pce_sprop_; \ 224 PCE_LOAD(cache_, pce_, entry_); \ 225 pce_sprop_ = PCE_PROPERTY(entry_); \ 226 PCMETER(cache_->tests++); \ 227 if (pce_sprop_ && \ 228 PCE_OBJECT(entry_) == obj && \ 229 pce_sprop_->id == id) { \ 230 sprop = pce_sprop_; \ 231 } else { \ 232 PCMETER(cache_->misses++); \ 233 sprop = NULL; \ 234 } \ 235 JS_END_MACRO 236 237 extern void 238 js_FlushPropertyCache(JSContext *cx); 239 240 extern void 241 js_DisablePropertyCache(JSContext *cx); 242 243 extern void 244 js_EnablePropertyCache(JSContext *cx); 245 246 extern JS_FRIEND_API(jsval *) 247 js_AllocStack(JSContext *cx, uintN nslots, void **markp); 248 249 extern JS_FRIEND_API(void) 250 js_FreeStack(JSContext *cx, void *mark); 251 252 extern JSBool 253 js_GetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp); 254 255 extern JSBool 256 js_SetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp); 257 258 extern JSBool 259 js_GetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp); 260 261 extern JSBool 262 js_SetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp); 263 264 #ifdef DUMP_CALL_TABLE 265 # define JSOPTION_LOGCALL_TOSOURCE JS_BIT(15) 266 267 extern JSHashTable *js_CallTable; 268 extern size_t js_LogCallToSourceLimit; 269 270 extern void js_DumpCallTable(JSContext *cx); 271 #endif 272 273 /* 274 * Refresh and return fp->scopeChain. It may be stale if block scopes are 275 * active but not yet reflected by objects in the scope chain. If a block 276 * scope contains a with, eval, XML filtering predicate, or similar such 277 * dynamically scoped construct, then compile-time block scope at fp->blocks 278 * must reflect at runtime. 279 */ 280 extern JSObject * 281 js_GetScopeChain(JSContext *cx, JSStackFrame *fp); 282 283 /* 284 * Compute the 'this' parameter for a call with nominal 'this' given by thisp 285 * and arguments including argv[-1] (nominal 'this') and argv[-2] (callee). 286 * Activation objects ("Call" objects not created with "new Call()", i.e., 287 * "Call" objects that have private data) may not be referred to by 'this', 288 * per ECMA-262, so js_ComputeThis censors them. 289 */ 290 extern JSObject * 291 js_ComputeThis(JSContext *cx, JSObject *thisp, jsval *argv); 292 293 /* 294 * NB: js_Invoke requires that cx is currently running JS (i.e., that cx->fp 295 * is non-null), and that the callee, |this| parameter, and actual arguments 296 * are already pushed on the stack under cx->fp->sp. 297 */ 298 extern JS_FRIEND_API(JSBool) 299 js_Invoke(JSContext *cx, uintN argc, uintN flags); 300 301 /* 302 * Consolidated js_Invoke flags simply rename certain JSFRAME_* flags, so that 303 * we can share bits stored in JSStackFrame.flags and passed to: 304 * 305 * js_Invoke 306 * js_InternalInvoke 307 * js_ValueToFunction 308 * js_ValueToFunctionObject 309 * js_ValueToCallableObject 310 * js_ReportIsNotFunction 311 * 312 * See jsfun.h for the latter four and flag renaming macros. 313 */ 314 #define JSINVOKE_CONSTRUCT JSFRAME_CONSTRUCTING 315 #define JSINVOKE_INTERNAL JSFRAME_INTERNAL 316 #define JSINVOKE_SKIP_CALLER JSFRAME_SKIP_CALLER 317 #define JSINVOKE_ITERATOR JSFRAME_ITERATOR 318 319 /* 320 * Mask to isolate construct and iterator flags for use with jsfun.h functions. 321 */ 322 #define JSINVOKE_FUNFLAGS (JSINVOKE_CONSTRUCT | JSINVOKE_ITERATOR) 323 324 /* 325 * "Internal" calls may come from C or C++ code using a JSContext on which no 326 * JS is running (!cx->fp), so they may need to push a dummy JSStackFrame. 327 */ 328 #define js_InternalCall(cx,obj,fval,argc,argv,rval) \ 329 js_InternalInvoke(cx, obj, fval, 0, argc, argv, rval) 330 331 #define js_InternalConstruct(cx,obj,fval,argc,argv,rval) \ 332 js_InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval) 333 334 extern JSBool 335 js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags, 336 uintN argc, jsval *argv, jsval *rval); 337 338 extern JSBool 339 js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval, 340 JSAccessMode mode, uintN argc, jsval *argv, jsval *rval); 341 342 extern JSBool 343 js_Execute(JSContext *cx, JSObject *chain, JSScript *script, 344 JSStackFrame *down, uintN flags, jsval *result); 345 346 extern JSBool 347 js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs, 348 JSObject **objp, JSProperty **propp); 349 350 extern JSBool 351 js_StrictlyEqual(jsval lval, jsval rval); 352 353 extern JSBool 354 js_InvokeConstructor(JSContext *cx, jsval *vp, uintN argc); 355 356 extern JSBool 357 js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result); 358 359 JS_END_EXTERN_C 360 361 #endif /* jsinterp_h___ */ 362