mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
845c56005f
Including: Preliminary work on internationalizing error messages Preliminary work on exposing runtime errors as catchable exceptions ECMA-proposed throw and try/catch/finally, with multiple catch clauses and catchguards ECMA-proposed in/instanceof operators IEEE-conformant number to string conversion Fixes and other good stuff.
210 lines
8.9 KiB
C
210 lines
8.9 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#ifndef jsinterp_h___
|
|
#define jsinterp_h___
|
|
/*
|
|
* JS interpreter interface.
|
|
*/
|
|
#include "jsprvtd.h"
|
|
#include "jspubtd.h"
|
|
|
|
/*
|
|
* JS stack frame, allocated on the C stack.
|
|
*/
|
|
struct JSStackFrame {
|
|
JSObject *callobj; /* lazily created Call object */
|
|
JSObject *argsobj; /* lazily created arguments object */
|
|
JSScript *script; /* script being interpreted */
|
|
JSFunction *fun; /* function being called or null */
|
|
JSObject *thisp; /* "this" pointer if in method */
|
|
uintN argc; /* actual argument count */
|
|
jsval *argv; /* base of argument stack slots */
|
|
jsval rval; /* function return value */
|
|
uintN nvars; /* local variable count */
|
|
jsval *vars; /* base of variable stack slots */
|
|
JSStackFrame *down; /* previous frame */
|
|
void *annotation; /* used by Java security */
|
|
JSObject *scopeChain; /* scope chain */
|
|
jsbytecode *pc; /* program counter */
|
|
jsval *sp; /* stack pointer */
|
|
uintN sharpDepth; /* array/object initializer depth */
|
|
JSObject *sharpArray; /* scope for #n= initializer vars */
|
|
JSPackedBool constructing; /* true if called via new operator */
|
|
uint8 overrides; /* bit-set of overridden Call properties */
|
|
JSPackedBool debugging; /* true if for JS_EvaluateInStackFrame */
|
|
JSStackFrame *dormantNext; /* next dormant frame chain */
|
|
};
|
|
|
|
/*
|
|
* Property cache for quickened get/set property opcodes.
|
|
*/
|
|
#define PROPERTY_CACHE_LOG2 10
|
|
#define PROPERTY_CACHE_SIZE PR_BIT(PROPERTY_CACHE_LOG2)
|
|
#define PROPERTY_CACHE_MASK PR_BITMASK(PROPERTY_CACHE_LOG2)
|
|
|
|
#define PROPERTY_CACHE_HASH(obj, id) \
|
|
((((pruword)(obj) >> JSVAL_TAGBITS) ^ (pruword)(id)) & PROPERTY_CACHE_MASK)
|
|
|
|
#ifdef JS_THREADSAFE
|
|
|
|
#if HAVE_ATOMIC_DWORD_ACCESS
|
|
|
|
#define PCE_LOAD(cache, pce, entry) PR_ATOMIC_DWORD_LOAD(pce, entry)
|
|
#define PCE_STORE(cache, pce, entry) PR_ATOMIC_DWORD_STORE(pce, entry)
|
|
|
|
#else /* !HAVE_ATOMIC_DWORD_ACCESS */
|
|
|
|
#define PCE_LOAD(cache, pce, entry) \
|
|
PR_BEGIN_MACRO \
|
|
uint32 _prefills; \
|
|
uint32 _fills = (cache)->fills; \
|
|
do { \
|
|
/* Load until cache->fills is stable (see FILL macro below). */ \
|
|
_prefills = _fills; \
|
|
(entry) = *(pce); \
|
|
} while ((_fills = (cache)->fills) != _prefills); \
|
|
PR_END_MACRO
|
|
|
|
#define PCE_STORE(cache, pce, entry) \
|
|
PR_BEGIN_MACRO \
|
|
do { \
|
|
/* Store until no racing collider stores half or all of pce. */ \
|
|
*(pce) = (entry); \
|
|
} while (PCE_OBJECT(*pce) != PCE_OBJECT(entry) || \
|
|
PCE_PROPERTY(*pce) != PCE_PROPERTY(entry)); \
|
|
PR_END_MACRO
|
|
|
|
#endif /* !HAVE_ATOMIC_DWORD_ACCESS */
|
|
|
|
#else /* !JS_THREADSAFE */
|
|
|
|
#define PCE_LOAD(cache, pce, entry) ((entry) = *(pce))
|
|
#define PCE_STORE(cache, pce, entry) (*(pce) = (entry))
|
|
|
|
#endif /* !JS_THREADSAFE */
|
|
|
|
typedef union JSPropertyCacheEntry {
|
|
struct {
|
|
JSObject *object; /* weak link to object */
|
|
JSProperty *property; /* weak link to property, or not-found id */
|
|
} s;
|
|
#ifdef HAVE_ATOMIC_DWORD_ACCESS
|
|
prdword align;
|
|
#endif
|
|
} JSPropertyCacheEntry;
|
|
|
|
/* These may be called in lvalue or rvalue position. */
|
|
#define PCE_OBJECT(entry) ((entry).s.object)
|
|
#define PCE_PROPERTY(entry) ((entry).s.property)
|
|
|
|
typedef struct JSPropertyCache {
|
|
JSPropertyCacheEntry table[PROPERTY_CACHE_SIZE];
|
|
JSBool empty;
|
|
uint32 fills;
|
|
uint32 recycles;
|
|
uint32 tests;
|
|
uint32 misses;
|
|
uint32 flushes;
|
|
} JSPropertyCache;
|
|
|
|
/* Property-not-found lookup results are cached using this invalid pointer. */
|
|
#define PROP_NOT_FOUND(obj,id) ((JSProperty *) ((prword)(id) | 1))
|
|
#define PROP_NOT_FOUND_ID(prop) ((jsid) ((prword)(prop) & ~1))
|
|
#define PROP_FOUND(prop) ((prop) && ((prword)(prop) & 1) == 0)
|
|
|
|
#define PROPERTY_CACHE_FILL(cx, cache, obj, id, prop) \
|
|
PR_BEGIN_MACRO \
|
|
uintN _hashIndex = (uintN)PROPERTY_CACHE_HASH(obj, id); \
|
|
JSPropertyCache *_cache = (cache); \
|
|
JSPropertyCacheEntry *_pce = &_cache->table[_hashIndex]; \
|
|
JSPropertyCacheEntry _entry; \
|
|
JSProperty *_pce_prop; \
|
|
PCE_LOAD(_cache, _pce, _entry); \
|
|
_pce_prop = PCE_PROPERTY(_entry); \
|
|
if (_pce_prop && _pce_prop != prop) \
|
|
_cache->recycles++; \
|
|
PCE_OBJECT(_entry) = obj; \
|
|
PCE_PROPERTY(_entry) = prop; \
|
|
_cache->empty = JS_FALSE; \
|
|
_cache->fills++; \
|
|
PCE_STORE(_cache, _pce, _entry); \
|
|
PR_END_MACRO
|
|
|
|
#define PROPERTY_CACHE_TEST(cache, obj, id, prop) \
|
|
PR_BEGIN_MACRO \
|
|
uintN _hashIndex = (uintN)PROPERTY_CACHE_HASH(obj, id); \
|
|
JSPropertyCache *_cache = (cache); \
|
|
JSPropertyCacheEntry *_pce = &_cache->table[_hashIndex]; \
|
|
JSPropertyCacheEntry _entry; \
|
|
JSProperty *_pce_prop; \
|
|
PCE_LOAD(_cache, _pce, _entry); \
|
|
_pce_prop = PCE_PROPERTY(_entry); \
|
|
_cache->tests++; \
|
|
if (_pce_prop && \
|
|
(((prword)_pce_prop & 1) \
|
|
? PROP_NOT_FOUND_ID(_pce_prop) \
|
|
: sym_id(((JSScopeProperty *)_pce_prop)->symbols)) == id && \
|
|
PCE_OBJECT(_entry) == obj) { \
|
|
prop = _pce_prop; \
|
|
} else { \
|
|
_cache->misses++; \
|
|
prop = NULL; \
|
|
} \
|
|
PR_END_MACRO
|
|
|
|
extern void
|
|
js_FlushPropertyCache(JSContext *cx);
|
|
|
|
extern void
|
|
js_FlushPropertyCacheByProp(JSContext *cx, JSProperty *prop);
|
|
|
|
extern jsval *
|
|
js_AllocStack(JSContext *cx, uintN nslots, void **markp);
|
|
|
|
extern void
|
|
js_FreeStack(JSContext *cx, void *mark);
|
|
|
|
extern JSBool
|
|
js_GetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
|
|
|
extern JSBool
|
|
js_SetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
|
|
|
extern JSBool
|
|
js_GetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
|
|
|
extern JSBool
|
|
js_SetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
|
|
|
extern JSBool
|
|
js_Invoke(JSContext *cx, uintN argc, JSBool constructing);
|
|
|
|
extern JSBool
|
|
js_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval,
|
|
uintN argc, jsval *argv, jsval *rval);
|
|
|
|
extern JSBool
|
|
js_Execute(JSContext *cx, JSObject *chain, JSScript *script, JSFunction *fun,
|
|
JSStackFrame *down, JSBool debugging, jsval *result);
|
|
|
|
extern JSBool
|
|
js_Interpret(JSContext *cx, jsval *result);
|
|
|
|
#endif /* jsinterp_h___ */
|