bug=423874 r=brendan a1.9b5=dsicore

Allocating native functions together with JSObject
This commit is contained in:
igor%mir2.org 2008-03-21 08:19:27 +00:00
Родитель fa81372ac7
Коммит 5ab7e29428
31 изменённых файлов: 827 добавлений и 613 удалений

Просмотреть файл

@ -1636,8 +1636,7 @@ nsScriptSecurityManager::CheckFunctionAccess(JSContext *aCx, void *aFunObj,
{
#ifdef DEBUG
{
JSFunction *fun =
(JSFunction *)caps_GetJSPrivate((JSObject *)aFunObj);
JSFunction *fun = GET_FUNCTION_PRIVATE(aCx, (JSObject *)aFunObj);
JSScript *script = JS_GetFunctionScript(aCx, fun);
NS_ASSERTION(!script, "Null principal for non-native function!");
@ -2152,7 +2151,7 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
nsresult *rv)
{
NS_PRECONDITION(rv, "Null out param");
JSFunction *fun = (JSFunction *) caps_GetJSPrivate(obj);
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
JSScript *script = JS_GetFunctionScript(cx, fun);
*rv = NS_OK;
@ -2221,7 +2220,7 @@ nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
#ifdef DEBUG
if (NS_SUCCEEDED(*rv) && !result)
{
JSFunction *fun = (JSFunction *)caps_GetJSPrivate(obj);
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
JSScript *script = JS_GetFunctionScript(cx, fun);
NS_ASSERTION(!script, "Null principal for non-native function!");

Просмотреть файл

@ -1033,7 +1033,9 @@ jsdScript::CreatePPLineMap()
PRBool scriptOwner = PR_FALSE;
if (fun) {
if (fun->nargs > 12)
PRUint32 nargs = JS_GetFunctionArity(fun);
if (nargs > 12)
return nsnull;
JSString *jsstr = JS_DecompileFunctionBody (cx, fun, 4);
if (!jsstr)
@ -1042,7 +1044,7 @@ jsdScript::CreatePPLineMap()
const char *argnames[] = {"arg1", "arg2", "arg3", "arg4",
"arg5", "arg6", "arg7", "arg8",
"arg9", "arg10", "arg11", "arg12" };
fun = JS_CompileUCFunction (cx, obj, "ppfun", fun->nargs, argnames,
fun = JS_CompileUCFunction (cx, obj, "ppfun", nargs, argnames,
JS_GetStringChars(jsstr),
JS_GetStringLength(jsstr),
"x-jsd:ppbuffer?type=function", 3);

Просмотреть файл

@ -933,15 +933,15 @@ CountHeap(JSContext *cx, uintN argc, jsval *vp)
const char *name;
int32 kind;
} traceKindNames[] = {
{ "all", -1 },
{ "object", JSTRACE_OBJECT },
{ "double", JSTRACE_DOUBLE },
{ "string", JSTRACE_STRING },
{ "function", JSTRACE_FUNCTION },
{ "all", -1 },
{ "object", JSTRACE_OBJECT },
{ "double", JSTRACE_DOUBLE },
{ "string", JSTRACE_STRING },
{ "function", JSTRACE_SCRIPTED_FUNCTION },
#if JS_HAS_XML_SUPPORT
{ "namespace", JSTRACE_NAMESPACE },
{ "qname", JSTRACE_QNAME },
{ "xml", JSTRACE_XML },
{ "namespace", JSTRACE_NAMESPACE },
{ "qname", JSTRACE_QNAME },
{ "xml", JSTRACE_XML },
#endif
};
@ -1029,7 +1029,7 @@ ValueToScript(JSContext *cx, jsval v)
fun = JS_ValueToFunction(cx, v);
if (!fun)
return NULL;
script = FUN_SCRIPT(fun);
script = JS_GetFunctionScript(cx, fun);
}
return script;
}
@ -1371,26 +1371,31 @@ Disassemble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
return JS_FALSE;
if (VALUE_IS_FUNCTION(cx, argv[i])) {
JSFunction *fun = JS_ValueToFunction(cx, argv[i]);
if (fun && (fun->flags & JSFUN_FLAGS_MASK)) {
uint16 flags = fun->flags;
fputs("flags:", stdout);
JSFunction *fun;
uint16 flags;
fun = JS_ValueToFunction(cx, argv[i]);
if (fun) {
flags = JS_GetFunctionFlags(fun);
if (flags & JSFUN_FLAGS_MASK) {
fputs("flags:", stdout);
#define SHOW_FLAG(flag) if (flags & JSFUN_##flag) fputs(" " #flag, stdout);
SHOW_FLAG(LAMBDA);
SHOW_FLAG(SETTER);
SHOW_FLAG(GETTER);
SHOW_FLAG(BOUND_METHOD);
SHOW_FLAG(HEAVYWEIGHT);
SHOW_FLAG(THISP_STRING);
SHOW_FLAG(THISP_NUMBER);
SHOW_FLAG(THISP_BOOLEAN);
SHOW_FLAG(EXPR_CLOSURE);
SHOW_FLAG(INTERPRETED);
SHOW_FLAG(LAMBDA);
SHOW_FLAG(SETTER);
SHOW_FLAG(GETTER);
SHOW_FLAG(BOUND_METHOD);
SHOW_FLAG(HEAVYWEIGHT);
SHOW_FLAG(THISP_STRING);
SHOW_FLAG(THISP_NUMBER);
SHOW_FLAG(THISP_BOOLEAN);
SHOW_FLAG(EXPR_CLOSURE);
SHOW_FLAG(SCRIPTED);
#undef SHOW_FLAG
putchar('\n');
putchar('\n');
}
}
}
@ -2947,7 +2952,7 @@ Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
type = JS_TypeOfValue(cx, argv[i]);
if (type == JSTYPE_FUNCTION) {
fun = JS_ValueToFunction(cx, argv[i]);
str = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
str = JS_GetFunctionId(fun);
} else if (type == JSTYPE_STRING) {
str = JSVAL_TO_STRING(argv[i]);
} else {

Просмотреть файл

@ -369,7 +369,7 @@ JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
break;
case 'f':
fun = va_arg(ap, JSFunction *);
*sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL;
*sp = fun ? OBJECT_TO_JSVAL(FUN_OBJECT(fun)) : JSVAL_NULL;
break;
case 'v':
*sp = va_arg(ap, jsval);
@ -2014,7 +2014,7 @@ JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
name = "double";
break;
case JSTRACE_FUNCTION:
case JSTRACE_SCRIPTED_FUNCTION:
name = "function";
break;
@ -2074,9 +2074,9 @@ JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
JS_snprintf(buf, bufsize, "%g", *(jsdouble *)thing);
break;
case JSTRACE_FUNCTION:
case JSTRACE_SCRIPTED_FUNCTION:
{
JSFunction *fun = (JSFunction *)thing;
JSScriptedFunction *fun = (JSScriptedFunction *)thing;
if (fun->atom && ATOM_IS_STRING(fun->atom))
js_PutEscapedString(buf, bufsize, ATOM_TO_STRING(fun->atom), 0);
@ -2668,7 +2668,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
JSTempValueRooter tvr;
jsval cval, rval;
JSBool named;
JSFunction *fun;
JSNativeFunction *fun;
CHECK_REQUEST(cx);
atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
@ -2698,7 +2698,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
}
/* Create a prototype object for this class. */
proto = js_NewObject(cx, clasp, parent_proto, obj);
proto = js_NewObject(cx, clasp, parent_proto, obj, 0);
if (!proto)
return NULL;
@ -2741,7 +2741,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
* we know to create an object of this class when we call the
* constructor.
*/
fun->u.n.clasp = clasp;
fun->clasp = clasp;
/*
* Optionally construct the prototype object, before the class has
@ -2749,7 +2749,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
* different object, as is done for operator new -- and as at least
* XML support requires.
*/
ctor = fun->object;
ctor = &fun->object;
if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
cval = OBJECT_TO_JSVAL(ctor);
if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval))
@ -2966,7 +2966,7 @@ JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
CHECK_REQUEST(cx);
if (!clasp)
clasp = &js_ObjectClass; /* default class is Object */
return js_NewObject(cx, clasp, proto, parent);
return js_NewObject(cx, clasp, proto, parent, 0);
}
JS_PUBLIC_API(JSObject *)
@ -2976,7 +2976,7 @@ JS_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
CHECK_REQUEST(cx);
if (!clasp)
clasp = &js_ObjectClass; /* default class is Object */
return js_NewObjectWithGivenProto(cx, clasp, proto, parent);
return js_NewObjectWithGivenProto(cx, clasp, proto, parent, 0);
}
JS_PUBLIC_API(JSBool)
@ -3120,7 +3120,7 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
CHECK_REQUEST(cx);
if (!clasp)
clasp = &js_ObjectClass; /* default class is Object */
nobj = js_NewObject(cx, clasp, proto, obj);
nobj = js_NewObject(cx, clasp, proto, obj, 0);
if (!nobj)
return NULL;
if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
@ -3999,7 +3999,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
JSIdArray *ida;
CHECK_REQUEST(cx);
iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj);
iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj, 0);
if (!iterobj)
return NULL;
@ -4197,6 +4197,7 @@ JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
JSObject *parent, const char *name)
{
JSAtom *atom;
JSNativeFunction *fun;
CHECK_REQUEST(cx);
@ -4207,7 +4208,8 @@ JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
if (!atom)
return NULL;
}
return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
fun = js_NewNativeFunction(cx, native, nargs, flags, parent, atom);
return fun ? NATIVE_TO_FUN(fun) : NULL;
}
JS_PUBLIC_API(JSObject *)
@ -4224,49 +4226,43 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
JS_PUBLIC_API(JSObject *)
JS_GetFunctionObject(JSFunction *fun)
{
return fun->object;
return FUN_OBJECT(fun);
}
JS_PUBLIC_API(const char *)
JS_GetFunctionName(JSFunction *fun)
{
return fun->atom
? JS_GetStringBytes(ATOM_TO_STRING(fun->atom))
: js_anonymous_str;
JSAtom *atom;
atom = FUN_ATOM(fun);
return atom ? JS_GetStringBytes(ATOM_TO_STRING(atom)) : js_anonymous_str;
}
JS_PUBLIC_API(JSString *)
JS_GetFunctionId(JSFunction *fun)
{
return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
JSAtom *atom;
atom = FUN_ATOM(fun);
return atom ? ATOM_TO_STRING(atom) : NULL;
}
JS_PUBLIC_API(uintN)
JS_GetFunctionFlags(JSFunction *fun)
{
#ifdef MOZILLA_1_8_BRANCH
uintN flags = fun->flags;
return JSFUN_DISJOINT_FLAGS(flags) |
(JSFUN_GETTER_TEST(flags) ? JSFUN_GETTER : 0) |
(JSFUN_SETTER_TEST(flags) ? JSFUN_SETTER : 0) |
(JSFUN_BOUND_METHOD_TEST(flags) ? JSFUN_BOUND_METHOD : 0) |
(JSFUN_HEAVYWEIGHT_TEST(flags) ? JSFUN_HEAVYWEIGHT : 0);
#else
return fun->flags;
#endif
return FUN_FLAGS(fun);
}
JS_PUBLIC_API(uint16)
JS_GetFunctionArity(JSFunction *fun)
{
return fun->nargs;
return FUN_NARGS(fun);
}
JS_PUBLIC_API(JSBool)
JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
{
return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass;
return HAS_FUNCTION_CLASS(obj);
}
JS_STATIC_DLL_CALLBACK(JSBool)
@ -4386,6 +4382,7 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
uintN flags;
JSObject *ctor;
JSFunction *fun;
JSNativeFunction *native;
CHECK_REQUEST(cx);
ctor = NULL;
@ -4412,14 +4409,16 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
fs->nargs + 1, flags);
if (!fun)
return JS_FALSE;
fun->u.n.extra = (uint16)fs->extra;
fun->u.n.minargs = (uint16)(fs->extra >> 16);
native = FUN_TO_NATIVE(fun);
native->extra = (uint16)fs->extra;
native->minargs = (uint16)(fs->extra >> 16);
/*
* As jsapi.h notes, fs must point to storage that lives as long
* as fun->object lives.
*/
if (!JS_SetReservedSlot(cx, fun->object, 0, PRIVATE_TO_JSVAL(fs)))
if (!JS_SetReservedSlot(cx, &native->object, 0,
PRIVATE_TO_JSVAL(fs)))
return JS_FALSE;
}
@ -4428,8 +4427,9 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags);
if (!fun)
return JS_FALSE;
fun->u.n.extra = (uint16)fs->extra;
fun->u.n.minargs = (uint16)(fs->extra >> 16);
native = FUN_TO_NATIVE(fun);
native->extra = (uint16)fs->extra;
native->minargs = (uint16)(fs->extra >> 16);
}
return JS_TRUE;
}
@ -4439,12 +4439,14 @@ JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
uintN nargs, uintN attrs)
{
JSAtom *atom;
JSNativeFunction *fun;
CHECK_REQUEST(cx);
atom = js_Atomize(cx, name, strlen(name), 0);
if (!atom)
return NULL;
return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
fun = js_DefineFunction(cx, obj, atom, call, nargs, attrs);
return fun ? NATIVE_TO_FUN(fun) : NULL;
}
JS_PUBLIC_API(JSFunction *)
@ -4453,11 +4455,13 @@ JS_DefineUCFunction(JSContext *cx, JSObject *obj,
uintN nargs, uintN attrs)
{
JSAtom *atom;
JSNativeFunction *fun;
atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
if (!atom)
return NULL;
return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
fun = js_DefineFunction(cx, obj, atom, call, nargs, attrs);
return fun ? NATIVE_TO_FUN(fun) : NULL;
}
JS_PUBLIC_API(JSScript *)
@ -4635,10 +4639,10 @@ JS_NewScriptObject(JSContext *cx, JSScript *script)
JSObject *obj;
if (!script)
return js_NewObject(cx, &js_ScriptClass, NULL, NULL);
return js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
if (obj) {
JS_SetPrivate(cx, obj, script);
script->object = obj;
@ -4723,7 +4727,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
const jschar *chars, size_t length,
const char *filename, uintN lineno)
{
JSFunction *fun;
JSScriptedFunction *fun;
JSTempValueRooter tvr;
JSAtom *funAtom, *argAtom;
uintN i;
@ -4738,7 +4742,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
goto out2;
}
}
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom);
fun = js_NewScriptedFunction(cx, NULL, 0, obj, funAtom);
if (!fun)
goto out2;
@ -4782,12 +4786,12 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
#endif
out:
cx->weakRoots.newborn[JSTRACE_FUNCTION] = fun;
cx->weakRoots.newborn[JSTRACE_SCRIPTED_FUNCTION] = fun;
JS_POP_TEMP_ROOT(cx, &tvr);
out2:
LAST_FRAME_CHECKS(cx, fun);
return fun;
return fun ? SCRIPTED_TO_FUN(fun) : NULL;
}
JS_PUBLIC_API(JSString *)
@ -4798,7 +4802,7 @@ JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
JSString *str;
CHECK_REQUEST(cx);
jp = JS_NEW_PRINTER(cx, name, NULL,
jp = JS_NEW_PRINTER(cx, name,
indent & ~JS_DONT_PRETTY_PRINT,
!(indent & JS_DONT_PRETTY_PRINT));
if (!jp)
@ -4818,15 +4822,18 @@ JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
JSString *str;
CHECK_REQUEST(cx);
jp = JS_NEW_PRINTER(cx, "JS_DecompileFunction", fun,
jp = JS_NEW_PRINTER(cx, "JS_DecompileFunction",
indent & ~JS_DONT_PRETTY_PRINT,
!(indent & JS_DONT_PRETTY_PRINT));
if (!jp)
return NULL;
if (js_DecompileFunction(jp))
if (FUN_IS_SCRIPTED(fun)
? js_DecompileFunction(jp, FUN_TO_SCRIPTED(fun))
: js_DecompileNativeFunction(jp, FUN_TO_NATIVE(fun))) {
str = js_GetPrinterOutput(jp);
else
} else {
str = NULL;
}
js_DestroyPrinter(jp);
return str;
}
@ -4838,15 +4845,19 @@ JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
JSString *str;
CHECK_REQUEST(cx);
jp = JS_NEW_PRINTER(cx, "JS_DecompileFunctionBody", fun,
jp = JS_NEW_PRINTER(cx, "JS_DecompileFunctionBody",
indent & ~JS_DONT_PRETTY_PRINT,
!(indent & JS_DONT_PRETTY_PRINT));
if (!jp)
return NULL;
if (js_DecompileFunctionBody(jp))
if (FUN_IS_SCRIPTED(fun)
? js_DecompileFunctionBody(jp, FUN_TO_SCRIPTED(fun))
: js_DecompileNativeFunctionBody(jp, FUN_TO_NATIVE(fun))) {
str = js_GetPrinterOutput(jp);
else
} else {
str = NULL;
}
js_DestroyPrinter(jp);
return str;
}
@ -4972,10 +4983,11 @@ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
jsval *argv, jsval *rval)
{
JSBool ok;
jsval funval;
CHECK_REQUEST(cx);
ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(fun->object), argc, argv,
rval);
funval = OBJECT_TO_JSVAL(FUN_OBJECT(fun));
ok = js_InternalCall(cx, obj, funval, argc, argv, rval);
LAST_FRAME_CHECKS(cx, ok);
return ok;
}

Просмотреть файл

@ -2879,7 +2879,7 @@ Array(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
/* If called without new, replace obj with a new Array object. */
if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -2929,7 +2929,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector)
JSTempValueRooter tvr;
JSObject *obj;
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
if (!obj)
return NULL;
@ -2946,7 +2946,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector)
JSObject *
js_NewSlowArrayObject(JSContext *cx)
{
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL);
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL, 0);
if (obj)
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
return obj;

Просмотреть файл

@ -2150,7 +2150,7 @@ js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
JSObject *obj;
jsdouble *date;
obj = js_NewObject(cx, &js_DateClass, NULL, NULL);
obj = js_NewObject(cx, &js_DateClass, NULL, NULL, 0);
if (!obj)
return NULL;

Просмотреть файл

@ -564,7 +564,9 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
clasp = OBJ_GET_CLASS(cx, closure);
if (clasp == &js_FunctionClass) {
fun = GET_FUNCTION_PRIVATE(cx, closure);
script = FUN_SCRIPT(fun);
script = FUN_IS_SCRIPTED(fun)
? FUN_TO_SCRIPTED(fun)->script
: NULL;
} else if (clasp == &js_ScriptClass) {
fun = NULL;
script = (JSScript *) JS_GetPrivate(cx, closure);
@ -576,10 +578,15 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
nslots = 2;
injectFrame = JS_TRUE;
if (fun) {
nslots += FUN_MINARGS(fun);
if (!FUN_INTERPRETED(fun)) {
nslots += fun->u.n.extra;
injectFrame = !(fun->flags & JSFUN_FAST_NATIVE);
if (FUN_IS_SCRIPTED(fun)) {
nslots += FUN_TO_SCRIPTED(fun)->nargs;
} else {
JSNativeFunction *nfun;
nfun = FUN_TO_NATIVE(fun);
nslots += NATIVE_FUN_MINARGS(nfun);
nslots += nfun->extra;
injectFrame = !(nfun->flags & JSFUN_FAST_NATIVE);
}
}
@ -657,7 +664,7 @@ js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
funobj = JSVAL_TO_OBJECT(argv[-2]);
JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass);
wrapper = GET_FUNCTION_PRIVATE(cx, funobj);
userid = ATOM_KEY(wrapper->atom);
userid = ATOM_KEY(FUN_ATOM(wrapper));
*rval = argv[0];
return js_watch_set(cx, obj, userid, rval);
}
@ -666,7 +673,7 @@ JSPropertyOp
js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
{
JSAtom *atom;
JSFunction *wrapper;
JSNativeFunction *wrapper;
if (!(attrs & JSPROP_SETTER))
return &js_watch_set; /* & to silence schoolmarmish MSVC */
@ -680,12 +687,12 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
} else {
atom = NULL;
}
wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0,
OBJ_GET_PARENT(cx, (JSObject *)setter),
atom);
wrapper = js_NewNativeFunction(cx, js_watch_set_wrapper, 1, 0,
OBJ_GET_PARENT(cx, (JSObject *)setter),
atom);
if (!wrapper)
return NULL;
return (JSPropertyOp) wrapper->object;
return (JSPropertyOp) &wrapper->object;
}
JS_PUBLIC_API(JSBool)
@ -918,19 +925,33 @@ JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
JS_PUBLIC_API(JSScript *)
JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
{
return FUN_SCRIPT(fun);
return FUN_IS_SCRIPTED(fun) ? FUN_TO_SCRIPTED(fun)->script : NULL;
}
JS_PUBLIC_API(JSNative)
JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
{
return FUN_NATIVE(fun);
JSNativeFunction *nfun;
if (FUN_IS_SCRIPTED(fun))
return NULL;
nfun = FUN_TO_NATIVE(fun);
return (nfun->flags & JSFUN_FAST_NATIVE) ? NULL : nfun->native;
}
JS_PUBLIC_API(JSFastNative)
JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun)
{
return FUN_FAST_NATIVE(fun);
JSNativeFunction *nfun;
if (FUN_IS_SCRIPTED(fun))
return NULL;
nfun = FUN_TO_NATIVE(fun);
return (nfun->flags & JSFUN_FAST_NATIVE)
? (JSFastNative) nfun->native
: NULL;
}
JS_PUBLIC_API(JSPrincipals *)
@ -983,7 +1004,7 @@ JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
JSRuntime *rt = cx->runtime;
if (rt->findObjectPrincipals) {
if (fp->fun->object != fp->callee)
if (FUN_OBJECT(fp->fun) != fp->callee)
return rt->findObjectPrincipals(cx, fp->callee);
/* FALL THROUGH */
}
@ -1552,13 +1573,25 @@ JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
{
size_t nbytes;
nbytes = sizeof *fun;
if (fun->object)
nbytes += JS_GetObjectTotalSize(cx, fun->object);
if (FUN_INTERPRETED(fun))
nbytes += JS_GetScriptTotalSize(cx, fun->u.i.script);
if (fun->atom)
nbytes += GetAtomTotalSize(cx, fun->atom);
if (FUN_IS_SCRIPTED(fun)) {
JSScriptedFunction *sfun;
sfun = FUN_TO_SCRIPTED(fun);
nbytes = sizeof *sfun;
nbytes += JS_GetScriptTotalSize(cx, sfun->script);
if (sfun->object)
nbytes += JS_GetObjectTotalSize(cx, sfun->object);
if (sfun->atom)
nbytes += GetAtomTotalSize(cx, sfun->atom);
} else {
JSNativeFunction *nfun;
nfun = FUN_TO_NATIVE(fun);
nbytes = sizeof(JSNativeFunction) - sizeof(JSObject);
nbytes += JS_GetObjectTotalSize(cx, &nfun->object);
if (nfun->atom)
nbytes += GetAtomTotalSize(cx, nfun->atom);
}
return nbytes;
}
@ -1667,7 +1700,7 @@ JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
{
JSObject *obj;
obj = js_NewObject(cx, clasp, proto, parent);
obj = js_NewObject(cx, clasp, proto, parent, 0);
if (obj && system)
STOBJ_SET_SYSTEM(obj);
return obj;

Просмотреть файл

@ -54,9 +54,13 @@ static char dempty[] = "<null>";
char *
jsdtrace_funcclass_name(JSFunction *fun)
{
return (!FUN_INTERPRETED(fun) && fun->u.n.clasp)
? (char *)fun->u.n.clasp->name
: dempty;
JSNativeFunction *nfun;
if (FUN_IS_SCRIPTED(fun))
return dempty;
nfun = FUN_TO_NATIVE(fun);
return nfun->clasp ? (char *) nfun->clasp->name : dempty;
}
char *

Просмотреть файл

@ -2037,7 +2037,7 @@ CheckSideEffects(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
JSBool *answer)
{
JSBool ok;
JSFunction *fun;
JSScriptedFunction *fun;
JSParseNode *pn2;
ok = JS_TRUE;
@ -2053,7 +2053,7 @@ CheckSideEffects(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
* name in that scope object. See comments at case JSOP_NAMEDFUNOBJ:
* in jsinterp.c.
*/
fun = GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object);
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object));
if (fun->atom)
*answer = JS_TRUE;
break;
@ -3924,7 +3924,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
switch (pn->pn_type) {
case TOK_FUNCTION:
{
JSFunction *fun;
JSScriptedFunction *fun;
void *cg2mark;
JSCodeGenerator *cg2;
uintN slot;
@ -3937,8 +3937,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
}
#endif
fun = GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object);
if (fun->u.i.script) {
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object));
if (fun->script) {
/*
* This second pass is needed to emit JSOP_NOP with a source note
* for the already-emitted function. See comments in the TOK_LC

Просмотреть файл

@ -175,7 +175,7 @@ struct JSTreeContext { /* tree context for semantic checks */
XXX combine with blockChain? */
JSAtomList decls; /* function, const, and var declarations */
JSParseContext *parseContext;
JSFunction *fun; /* function to store argument and variable
JSScriptedFunction *fun; /* function to store argument and variable
names when flags & TCF_IN_FUNCTION */
};

Просмотреть файл

@ -321,8 +321,11 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
elem->funName = NULL;
elem->argc = 0;
} else {
elem->funName = fp->fun->atom
? ATOM_TO_STRING(fp->fun->atom)
JSAtom *atom;
atom = FUN_ATOM(fp->fun);
elem->funName = atom
? ATOM_TO_STRING(atom)
: cx->runtime->emptyString;
elem->argc = fp->argc;
memcpy(values, fp->argv, fp->argc * sizeof(jsval));
@ -750,7 +753,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
.classPrototypeAtom),
rval))
return JS_FALSE;
obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL);
obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL, 0);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -1043,7 +1046,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
/* Initialize the prototypes first. */
for (i = 0; exceptions[i].name != 0; i++) {
JSAtom *atom;
JSFunction *fun;
JSNativeFunction *fun;
JSObject *funobj;
JSString *nameString;
int protoIndex = exceptions[i].protoIndex;
@ -1053,7 +1056,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
(protoIndex != JSEXN_NONE)
? protos[protoIndex]
: obj_proto,
obj);
obj, 0);
if (!protos[i])
break;
@ -1067,10 +1070,10 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
break;
/* Make this constructor make objects of class Exception. */
fun->u.n.clasp = &js_ErrorClass;
fun->clasp = &js_ErrorClass;
/* Extract the constructor object. */
funobj = fun->object;
funobj = &fun->object;
/* Make the prototype and constructor links. */
if (!js_SetClassPrototype(cx, funobj, protos[i],
@ -1223,7 +1226,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
goto out;
tv[0] = OBJECT_TO_JSVAL(errProto);
errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL);
errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL, 0);
if (!errObject) {
ok = JS_FALSE;
goto out;

Просмотреть файл

@ -242,7 +242,8 @@ js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
* We must be in a function activation; the function must be lightweight
* or else fp must have a variable object.
*/
JS_ASSERT(fp->fun && (!(fp->fun->flags & JSFUN_HEAVYWEIGHT) || fp->varobj));
JS_ASSERT(fp->fun);
JS_ASSERT_IF(FUN_FLAGS(fp->fun) & JSFUN_HEAVYWEIGHT, fp->varobj);
/* Skip eval and debugger frames. */
while (fp->flags & JSFRAME_SPECIAL)
@ -254,7 +255,7 @@ js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
return argsobj;
/* Link the new object to fp so it can get actual argument values. */
argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL);
argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL, 0);
if (!argsobj || !JS_SetPrivate(cx, argsobj, fp)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -418,7 +419,7 @@ args_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
break;
default:
if (FUN_INTERPRETED(fp->fun) &&
if (FUN_IS_SCRIPTED(fp->fun) &&
(uintN)slot < fp->argc &&
!ArgWasDeleted(cx, fp, slot)) {
fp->argv[slot] = *vp;
@ -602,7 +603,7 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent)
}
/* Create the call object and link it to its stack frame. */
callobj = js_NewObject(cx, &js_CallClass, NULL, parent);
callobj = js_NewObject(cx, &js_CallClass, NULL, parent, 0);
if (!callobj || !JS_SetPrivate(cx, callobj, fp)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -669,7 +670,7 @@ call_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
if (!fp)
return JS_TRUE;
JS_ASSERT(fp->fun);
JS_ASSERT(fp->fun && FUN_IS_SCRIPTED(fp->fun));
slot = JSVAL_TO_INT(id);
switch (slot) {
@ -683,7 +684,7 @@ call_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
break;
default:
if ((uintN)slot < JS_MAX(fp->argc, fp->fun->nargs))
if ((uintN)slot < JS_MAX(fp->argc, FUN_TO_SCRIPTED(fp->fun)->nargs))
*vp = fp->argv[slot];
break;
}
@ -701,7 +702,7 @@ call_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
if (!fp)
return JS_TRUE;
JS_ASSERT(fp->fun);
JS_ASSERT(fp->fun && FUN_IS_SCRIPTED(fp->fun));
slot = JSVAL_TO_INT(id);
switch (slot) {
@ -710,7 +711,7 @@ call_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
break;
default:
if ((uintN)slot < JS_MAX(fp->argc, fp->fun->nargs))
if ((uintN)slot < JS_MAX(fp->argc, FUN_TO_SCRIPTED(fp->fun)->nargs))
fp->argv[slot] = *vp;
break;
}
@ -749,7 +750,7 @@ static JSBool
call_enumerate(JSContext *cx, JSObject *obj)
{
JSStackFrame *fp;
JSFunction *fun;
JSScriptedFunction *fun;
uintN n, i, slot;
void *mark;
jsuword *names;
@ -769,7 +770,7 @@ call_enumerate(JSContext *cx, JSObject *obj)
* and functions in fp->vars for declared variables and nested-at-top-level
* local functions.
*/
fun = fp->fun;
fun = FUN_TO_SCRIPTED(fp->fun);
n = JS_GET_LOCAL_NAME_COUNT(fun);
if (n == 0)
return JS_TRUE;
@ -821,6 +822,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
{
JSStackFrame *fp;
jsid id;
JSScriptedFunction *fun;
JSLocalKind localKind;
JSPropertyOp getter, setter;
uintN slot, attrs;
@ -829,7 +831,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
if (!fp)
return JS_TRUE;
JS_ASSERT(fp->fun);
JS_ASSERT(fp->fun && FUN_IS_SCRIPTED(fp->fun));
JS_ASSERT(GET_FUNCTION_PRIVATE(cx, fp->callee) == fp->fun);
if (!JSVAL_IS_STRING(idval))
@ -838,16 +840,17 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
if (!js_ValueToStringId(cx, idval, &id))
return JS_FALSE;
localKind = js_LookupLocal(cx, fp->fun, JSID_TO_ATOM(id), &slot);
fun = FUN_TO_SCRIPTED(fp->fun);
localKind = js_LookupLocal(cx, fun, JSID_TO_ATOM(id), &slot);
if (localKind != JSLOCAL_NONE) {
if (localKind == JSLOCAL_ARG) {
JS_ASSERT(slot < fp->fun->nargs);
JS_ASSERT(slot < fun->nargs);
vp = fp->argv;
getter = setter = NULL;
attrs = JSPROP_PERMANENT;
} else {
JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
JS_ASSERT(fp->fun->u.i.nvars == fp->nvars);
JS_ASSERT(FUN_TO_SCRIPTED(fp->fun)->nvars == fp->nvars);
JS_ASSERT(slot < fp->nvars);
vp = fp->vars;
getter = js_GetCallVariable;
@ -1012,14 +1015,16 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
case ARGS_LENGTH:
case FUN_ARITY:
*vp = INT_TO_JSVAL((jsint)fun->nargs);
*vp = INT_TO_JSVAL((jsint) FUN_NARGS(fun));
break;
case FUN_NAME:
*vp = fun->atom
? ATOM_KEY(fun->atom)
: STRING_TO_JSVAL(cx->runtime->emptyString);
case FUN_NAME: {
JSAtom *atom;
atom = FUN_ATOM(fun);
*vp = atom ? ATOM_KEY(atom) : STRING_TO_JSVAL(cx->runtime->emptyString);
break;
}
case FUN_CALLER:
if (fp && fp->down && fp->down->fun)
@ -1035,7 +1040,7 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
default:
/* XXX fun[0] and fun.arguments[0] are equivalent. */
if (fp && fp->fun && (uintN)slot < fp->fun->nargs)
if (fp && fp->fun && (uintN)slot < FUN_NARGS(fp->fun))
*vp = fp->argv[slot];
break;
}
@ -1070,7 +1075,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
return JS_TRUE;
fun = GET_FUNCTION_PRIVATE(cx, obj);
JS_ASSERT(fun->object);
JS_ASSERT(FUN_OBJECT(fun));
/*
* No need to reflect fun.prototype in 'fun.prototype = ... '.
@ -1099,7 +1104,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
* Beware of the wacky case of a user function named Object -- trying
* to find a prototype for that will recur back here _ad perniciem_.
*/
if (fun->atom == CLASS_ATOM(cx, Object))
if (FUN_ATOM(fun) == CLASS_ATOM(cx, Object))
return JS_TRUE;
/*
@ -1107,7 +1112,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
* object itself.
*/
proto = js_NewObject(cx, &js_ObjectClass, NULL,
OBJ_GET_PARENT(cx, obj));
OBJ_GET_PARENT(cx, obj), 0);
if (!proto)
return JS_FALSE;
@ -1166,7 +1171,7 @@ static JSBool
fun_xdrObject(JSXDRState *xdr, JSObject **objp)
{
JSContext *cx;
JSFunction *fun;
JSScriptedFunction *fun;
uint32 nullAtom; /* flag to indicate if fun->atom is NULL */
uintN nargs, nvars, n;
uint32 localsword; /* word to xdr argument and variable counts */
@ -1176,20 +1181,23 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
cx = xdr->cx;
if (xdr->mode == JSXDR_ENCODE) {
fun = GET_FUNCTION_PRIVATE(cx, *objp);
if (!FUN_INTERPRETED(fun)) {
JSFunction *f;
f = GET_FUNCTION_PRIVATE(cx, *objp);
if (!FUN_IS_SCRIPTED(f)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_NOT_SCRIPTED_FUNCTION,
JS_GetFunctionName(fun));
JS_GetFunctionName(f));
return JS_FALSE;
}
fun = FUN_TO_SCRIPTED(f);
nullAtom = !fun->atom;
nargs = fun->nargs;
nvars = fun->u.i.nvars;
nvars = fun->nvars;
localsword = (nargs << 16) | nvars;
flagsword = fun->flags;
} else {
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
fun = js_NewScriptedFunction(cx, NULL, 0, NULL, NULL);
if (!fun)
return JS_FALSE;
STOBJ_SET_PARENT(fun->object, NULL);
@ -1215,7 +1223,7 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
if (xdr->mode == JSXDR_DECODE) {
nargs = localsword >> 16;
nvars = localsword & JS_BITMASK(16);
JS_ASSERT(flagsword | JSFUN_INTERPRETED);
JS_ASSERT(flagsword | JSFUN_SCRIPTED);
fun->flags = (uint16) flagsword;
}
@ -1316,15 +1324,15 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
js_FreezeLocalNames(cx, fun);
}
if (!js_XDRScript(xdr, &fun->u.i.script, NULL))
if (!js_XDRScript(xdr, &fun->script, NULL))
goto bad;
if (xdr->mode == JSXDR_DECODE) {
*objp = fun->object;
#ifdef CHECK_SCRIPT_OWNER
fun->u.i.script->owner = NULL;
fun->script->owner = NULL;
#endif
js_CallNewScriptHook(cx, fun->u.i.script, fun);
js_CallNewScriptHook(cx, fun->script, fun);
}
out:
@ -1376,17 +1384,30 @@ static void
fun_trace(JSTracer *trc, JSObject *obj)
{
JSFunction *fun;
JSNativeFunction *native;
/* A newborn function object may have a not yet initialized private slot. */
fun = (JSFunction *) JS_GetPrivate(trc->context, obj);
if (fun)
JS_CALL_TRACER(trc, fun, JSTRACE_FUNCTION, "private");
if (!fun)
return;
if (FUN_IS_SCRIPTED(fun)) {
JS_CALL_TRACER(trc, FUN_TO_SCRIPTED(fun),
JSTRACE_SCRIPTED_FUNCTION, "private");
return;
}
native = (JSNativeFunction *) obj;
JS_ASSERT(FUN_TO_NATIVE(fun) == native);
if (native->atom)
JS_CALL_STRING_TRACER(trc, ATOM_TO_STRING(native->atom), "atom");
}
static uint32
fun_reserveSlots(JSContext *cx, JSObject *obj)
{
JSFunction *fun;
JSScript *script;
/*
* We use JS_GetPrivate and not GET_FUNCTION_PRIVATE because during
@ -1394,9 +1415,12 @@ fun_reserveSlots(JSContext *cx, JSObject *obj)
* private slot of the function object is set.
*/
fun = (JSFunction *) JS_GetPrivate(cx, obj);
return (fun && FUN_INTERPRETED(fun) &&
fun->u.i.script && fun->u.i.script->regexpsOffset != 0)
? JS_SCRIPT_REGEXPS(fun->u.i.script)->length
if (!fun || !FUN_IS_SCRIPTED(fun))
return 0;
script = FUN_TO_SCRIPTED(fun)->script;
return (script && script->regexpsOffset != 0)
? JS_SCRIPT_REGEXPS(script)->length
: 0;
}
@ -1699,7 +1723,7 @@ static JSBool
Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JSStackFrame *fp, *caller;
JSFunction *fun;
JSScriptedFunction *fun;
JSObject *parent;
uintN i, n, lineno;
JSAtom *atom;
@ -1715,7 +1739,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
fp = cx->fp;
if (!(fp->flags & JSFRAME_CONSTRUCTING)) {
obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL);
obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -1725,8 +1749,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
* The constructor is called before the private slot is initialized so we
* must use JS_GetPrivate, not GET_FUNCTION_PRIVATE here.
*/
fun = (JSFunction *) JS_GetPrivate(cx, obj);
if (fun)
if (JS_GetPrivate(cx, obj))
return JS_TRUE;
/*
@ -1741,8 +1764,8 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
*/
parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]));
fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
parent, cx->runtime->atomState.anonymousAtom);
fun = js_NewScriptedFunction(cx, obj, JSFUN_LAMBDA, parent,
cx->runtime->atomState.anonymousAtom);
if (!fun)
return JS_FALSE;
@ -1754,7 +1777,9 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
* are built for Function.prototype.call or .apply activations that invoke
* Function indirectly from a script.
*/
JS_ASSERT(!fp->script && fp->fun && fp->fun->u.n.native == Function);
JS_ASSERT(fp->fun &&
!FUN_IS_SCRIPTED(fp->fun) &&
FUN_TO_NATIVE(fp->fun)->native == Function);
caller = JS_GetScriptedCaller(cx, fp);
if (caller) {
principals = JS_EvalFramePrincipals(cx, fp, caller);
@ -1932,7 +1957,7 @@ js_InitFunctionClass(JSContext *cx, JSObject *obj)
{
JSObject *proto;
JSAtom *atom;
JSFunction *fun;
JSScriptedFunction *fun;
proto = JS_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,
function_props, function_methods, NULL, NULL);
@ -1942,15 +1967,15 @@ js_InitFunctionClass(JSContext *cx, JSObject *obj)
0);
if (!atom)
goto bad;
fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL);
fun = js_NewScriptedFunction(cx, proto, 0, obj, NULL);
if (!fun)
goto bad;
fun->u.i.script = js_NewScript(cx, 1, 0, 0, 0, 0, 0);
if (!fun->u.i.script)
fun->script = js_NewScript(cx, 1, 0, 0, 0, 0, 0);
if (!fun->script)
goto bad;
fun->u.i.script->code[0] = JSOP_STOP;
fun->script->code[0] = JSOP_STOP;
#ifdef CHECK_SCRIPT_OWNER
fun->u.i.script->owner = NULL;
fun->script->owner = NULL;
#endif
return proto;
@ -1977,18 +2002,20 @@ js_InitCallClass(JSContext *cx, JSObject *obj)
return proto;
}
JSFunction *
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
uintN flags, JSObject *parent, JSAtom *atom)
JSScriptedFunction *
js_NewScriptedFunction(JSContext *cx, JSObject *funobj, uintN flags,
JSObject *parent, JSAtom *atom)
{
JSFunction *fun;
JSScriptedFunction *sfun;
JSTempValueRooter tvr;
JS_ASSERT((flags & ~JSFUN_LAMBDA) == 0);
/* If funobj is null, allocate an object for it. */
if (funobj) {
OBJ_SET_PARENT(cx, funobj, parent);
} else {
funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);
funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent, 0);
if (!funobj)
return NULL;
}
@ -2000,115 +2027,134 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
* Allocate fun after allocating funobj so allocations in js_NewObject
* and hooks called from it do not wipe out fun from newborn[GCX_FUNCTION].
*/
fun = (JSFunction *) js_NewGCThing(cx, GCX_FUNCTION, sizeof(JSFunction));
if (!fun)
sfun = (JSScriptedFunction *)
js_NewGCThing(cx, GCX_FUNCTION, sizeof(JSScriptedFunction));
if (!sfun)
goto out;
/* Initialize all function members. */
fun->object = NULL;
fun->nargs = nargs;
fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED);
if (flags & JSFUN_INTERPRETED) {
JS_ASSERT(!native);
JS_ASSERT(nargs == 0);
fun->u.i.nvars = 0;
fun->u.i.spare = 0;
fun->u.i.script = NULL;
sfun->object = NULL;
sfun->flags = (flags & JSFUN_FLAGS_MASK) | JSFUN_SCRIPTED;
sfun->nargs = 0;
sfun->nvars = 0;
sfun->spare = 0;
sfun->script = NULL;
#ifdef DEBUG
fun->u.i.names.taggedAtom = 0;
sfun->names.taggedAtom = 0;
#endif
} else {
fun->u.n.native = native;
fun->u.n.extra = 0;
fun->u.n.minargs = 0;
fun->u.n.clasp = NULL;
}
fun->atom = atom;
sfun->atom = atom;
/* Link fun to funobj and vice versa. */
if (!js_LinkFunctionObject(cx, fun, funobj)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
fun = NULL;
}
sfun->object = funobj;
JS_SetPrivate(cx, funobj, SCRIPTED_TO_FUN(sfun));
out:
JS_POP_TEMP_ROOT(cx, &tvr);
return fun;
return sfun;
}
JSNativeFunction *
js_NewNativeFunction(JSContext *cx, JSNative native, uintN nargs,
uintN flags, JSObject *parent, JSAtom *atom)
{
JSNativeFunction *nfun;
JS_ASSERT(!(flags & (JSFUN_LAMBDA | JSFUN_SCRIPTED)));
nfun = (JSNativeFunction *) js_NewObject(cx, &js_FunctionClass, NULL,
parent,
sizeof(JSNativeFunction) -
sizeof(JSObject));
if (!nfun)
return NULL;
/* Initialize all function members. */
nfun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_SCRIPTED);
nfun->nargs = nargs;
nfun->native = native;
nfun->extra = 0;
nfun->minargs = 0;
nfun->clasp = NULL;
nfun->atom = atom;
JS_SetPrivate(cx, &nfun->object, NATIVE_TO_FUN(nfun));
return nfun;
}
static void
TraceLocalNames(JSTracer *trc, JSFunction *fun);
TraceLocalNames(JSTracer *trc, JSScriptedFunction *fun);
void
js_TraceFunction(JSTracer *trc, JSFunction *fun)
js_TraceFunction(JSTracer *trc, JSScriptedFunction *fun)
{
if (fun->object)
JS_CALL_OBJECT_TRACER(trc, fun->object, "object");
if (fun->atom)
JS_CALL_STRING_TRACER(trc, ATOM_TO_STRING(fun->atom), "atom");
if (FUN_INTERPRETED(fun)) {
if (fun->u.i.script)
js_TraceScript(trc, fun->u.i.script);
TraceLocalNames(trc, fun);
}
if (fun->script)
js_TraceScript(trc, fun->script);
TraceLocalNames(trc, fun);
}
static void
DestroyLocalNames(JSContext *cx, JSFunction *fun);
DestroyLocalNames(JSContext *cx, JSScriptedFunction *fun);
void
js_FinalizeFunction(JSContext *cx, JSFunction *fun)
js_FinalizeFunction(JSContext *cx, JSScriptedFunction *fun)
{
/*
* Null-check of i.script is required since the parser sets interpreted
* very early.
* Null-check of i.script is required since the parser creates
* JSScriptedFunction very early.
*/
if (FUN_INTERPRETED(fun)) {
if (fun->u.i.script)
js_DestroyScript(cx, fun->u.i.script);
DestroyLocalNames(cx, fun);
}
if (fun->script)
js_DestroyScript(cx, fun->script);
DestroyLocalNames(cx, fun);
}
JSObject *
js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
{
JSObject *newfunobj;
JSFunction *fun;
JSObject *newfunobj;
JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass);
newfunobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);
if (!newfunobj)
return NULL;
fun = GET_FUNCTION_PRIVATE(cx, funobj);
if (!js_LinkFunctionObject(cx, fun, newfunobj)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
if (FUN_IS_SCRIPTED(fun)) {
JSScriptedFunction *sfun;
sfun = FUN_TO_SCRIPTED(fun);
JS_ASSERT(sfun->object);
newfunobj = js_NewObject(cx, &js_FunctionClass, NULL, parent, 0);
if (!newfunobj)
return NULL;
JS_SetPrivate(cx, newfunobj, SCRIPTED_TO_FUN(sfun));
} else {
JS_ASSERT((JSNativeFunction *) funobj == FUN_TO_NATIVE(fun));
newfunobj = js_NewObject(cx, &js_FunctionClass, NULL, parent,
sizeof(JSNativeFunction) - sizeof(JSObject));
if (!newfunobj)
return NULL;
memcpy((uint8 *) newfunobj + sizeof(JSObject),
(uint8 *) funobj + sizeof(JSObject),
sizeof(JSNativeFunction) - sizeof(JSObject));
JS_SetPrivate(cx, newfunobj,
NATIVE_TO_FUN((JSNativeFunction *) newfunobj));
}
return newfunobj;
}
JSBool
js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *funobj)
{
if (!fun->object)
fun->object = funobj;
return JS_SetPrivate(cx, funobj, fun);
}
JSFunction *
JSNativeFunction *
js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
uintN nargs, uintN attrs)
{
JSFunction *fun;
JSNativeFunction *fun;
JSPropertyOp gsop;
fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);
fun = js_NewNativeFunction(cx, native, nargs, attrs, obj, atom);
if (!fun)
return NULL;
gsop = (attrs & JSFUN_STUB_GSOPS) ? JS_PropertyStub : NULL;
if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
OBJECT_TO_JSVAL(fun->object),
OBJECT_TO_JSVAL(&fun->object),
gsop, gsop,
attrs & ~JSFUN_FLAGS_MASK, NULL)) {
return NULL;
@ -2148,6 +2194,7 @@ js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
{
JSFunction *fun;
JSObject *funobj;
JSAtom *atom;
JSStackFrame *caller;
JSPrincipals *principals;
@ -2157,7 +2204,19 @@ js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
fun = js_ValueToFunction(cx, vp, flags);
if (!fun)
return NULL;
funobj = fun->object;
if (FUN_IS_SCRIPTED(fun)) {
JSScriptedFunction *sfun;
sfun = FUN_TO_SCRIPTED(fun);
funobj = sfun->object;
atom = sfun->atom;
} else {
JSNativeFunction *nfun;
nfun = FUN_TO_NATIVE(fun);
funobj = &nfun->object;
atom = nfun->atom;
}
*vp = OBJECT_TO_JSVAL(funobj);
caller = JS_GetScriptedCaller(cx, cx->fp);
@ -2169,8 +2228,8 @@ js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
}
if (!js_CheckPrincipalsAccess(cx, funobj, principals,
fun->atom
? fun->atom
atom
? atom
: cx->runtime->atomState.anonymousAtom)) {
return NULL;
}
@ -2321,7 +2380,8 @@ HashLocalName(JSContext *cx, JSLocalNameMap *map, JSAtom *name,
}
JSBool
js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
js_AddLocal(JSContext *cx, JSScriptedFunction *fun, JSAtom *atom,
JSLocalKind kind)
{
jsuword taggedAtom;
uint16 *indexp;
@ -2329,14 +2389,13 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
jsuword *array;
JSLocalNameMap *map;
JS_ASSERT(FUN_INTERPRETED(fun));
JS_ASSERT(!fun->u.i.script);
JS_ASSERT(!fun->script);
JS_ASSERT(((jsuword) atom & 1) == 0);
taggedAtom = (jsuword) atom;
if (kind == JSLOCAL_ARG) {
indexp = &fun->nargs;
} else {
indexp = &fun->u.i.nvars;
indexp = &fun->nvars;
if (kind == JSLOCAL_CONST)
taggedAtom |= 1;
else
@ -2344,17 +2403,17 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
}
n = JS_GET_LOCAL_NAME_COUNT(fun);
if (n == 0) {
JS_ASSERT(fun->u.i.names.taggedAtom == 0);
fun->u.i.names.taggedAtom = taggedAtom;
JS_ASSERT(fun->names.taggedAtom == 0);
fun->names.taggedAtom = taggedAtom;
} else if (n < MAX_ARRAY_LOCALS) {
if (n > 1) {
array = fun->u.i.names.array;
array = fun->names.array;
} else {
array = (jsuword *) JS_malloc(cx, MAX_ARRAY_LOCALS * sizeof *array);
if (!array)
return JS_FALSE;
array[0] = fun->u.i.names.taggedAtom;
fun->u.i.names.array = array;
array[0] = fun->names.taggedAtom;
fun->names.array = array;
}
if (kind == JSLOCAL_ARG) {
/*
@ -2362,19 +2421,19 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
* so for the following arguments nvars != 0.
*/
#if JS_HAS_DESTRUCTURING
if (fun->u.i.nvars != 0) {
if (fun->nvars != 0) {
memmove(array + fun->nargs + 1, array + fun->nargs,
fun->u.i.nvars * sizeof *array);
fun->nvars * sizeof *array);
}
#else
JS_ASSERT(fun->u.i.nvars == 0);
JS_ASSERT(fun->nvars == 0);
#endif
array[fun->nargs] = taggedAtom;
} else {
array[n] = taggedAtom;
}
} else if (n == MAX_ARRAY_LOCALS) {
array = fun->u.i.names.array;
array = fun->names.array;
map = (JSLocalNameMap *) JS_malloc(cx, sizeof *map);
if (!map)
return JS_FALSE;
@ -2408,7 +2467,7 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
* At this point the entry is added and we cannot fail. It is time
* to replace fun->u.i.names with the built map.
*/
fun->u.i.names.map = map;
fun->names.map = map;
JS_free(cx, array);
} else {
if (*indexp == JS_BITMASK(16)) {
@ -2418,7 +2477,7 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
: JSMSG_TOO_MANY_FUN_VARS);
return JS_FALSE;
}
if (!HashLocalName(cx, fun->u.i.names.map, atom, kind, *indexp))
if (!HashLocalName(cx, fun->names.map, atom, kind, *indexp))
return JS_FALSE;
}
@ -2428,18 +2487,18 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
}
JSLocalKind
js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp)
js_LookupLocal(JSContext *cx, JSScriptedFunction *fun, JSAtom *atom,
uintN *indexp)
{
uintN n, i;
jsuword *array;
JSLocalNameHashEntry *entry;
JS_ASSERT(FUN_INTERPRETED(fun));
n = JS_GET_LOCAL_NAME_COUNT(fun);
if (n == 0)
return JSLOCAL_NONE;
if (n <= MAX_ARRAY_LOCALS) {
array = (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
array = (n == 1) ? &fun->names.taggedAtom : fun->names.array;
/* Search from the tail to pick up the last duplicated name. */
i = n;
@ -2460,7 +2519,7 @@ js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp)
} while (i != 0);
} else {
entry = (JSLocalNameHashEntry *)
JS_DHashTableOperate(&fun->u.i.names.map->names, atom,
JS_DHashTableOperate(&fun->names.map->names, atom,
JS_DHASH_LOOKUP);
if (JS_DHASH_ENTRY_IS_BUSY(&entry->hdr)) {
JS_ASSERT(entry->localKind != JSLOCAL_NONE);
@ -2473,11 +2532,11 @@ js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp)
}
typedef struct JSLocalNameEnumeratorArgs {
JSFunction *fun;
jsuword *names;
JSScriptedFunction *fun;
jsuword *names;
#ifdef DEBUG
uintN nCopiedArgs;
uintN nCopiedVars;
uintN nCopiedArgs;
uintN nCopiedVars;
#endif
} JSLocalNameEnumeratorArgs;
@ -2501,8 +2560,8 @@ get_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
} else {
JS_ASSERT(entry->localKind == JSLOCAL_VAR ||
entry->localKind == JSLOCAL_CONST);
JS_ASSERT(entry->index < args->fun->u.i.nvars);
JS_ASSERT(args->nCopiedVars++ < args->fun->u.i.nvars);
JS_ASSERT(entry->index < args->fun->nvars);
JS_ASSERT(args->nCopiedVars++ < args->fun->nvars);
i = args->fun->nargs + entry->index;
constFlag = (entry->localKind == JSLOCAL_CONST);
}
@ -2511,7 +2570,7 @@ get_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
}
jsuword *
js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
js_GetLocalNameArray(JSContext *cx, JSScriptedFunction *fun, JSArenaPool *pool)
{
uintN n;
jsuword *names;
@ -2519,12 +2578,11 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
JSLocalNameEnumeratorArgs args;
JSNameIndexPair *dup;
JS_ASSERT(FUN_INTERPRETED(fun));
n = JS_GET_LOCAL_NAME_COUNT(fun);
JS_ASSERT(n != 0);
if (n <= MAX_ARRAY_LOCALS)
return (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
return (n == 1) ? &fun->names.taggedAtom : fun->names.array;
/*
* No need to check for overflow of the allocation size as we are making a
@ -2540,7 +2598,7 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
/* Some parameter names can be NULL due to destructuring patterns. */
memset(names, 0, fun->nargs * sizeof *names);
#endif
map = fun->u.i.names.map;
map = fun->names.map;
args.fun = fun;
args.names = names;
#ifdef DEBUG
@ -2556,7 +2614,7 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
#if !JS_HAS_DESTRUCTURING
JS_ASSERT(args.nCopiedArgs == fun->nargs);
#endif
JS_ASSERT(args.nCopiedVars == fun->u.i.nvars);
JS_ASSERT(args.nCopiedVars == fun->nvars);
return names;
}
@ -2579,18 +2637,17 @@ trace_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
}
static void
TraceLocalNames(JSTracer *trc, JSFunction *fun)
TraceLocalNames(JSTracer *trc, JSScriptedFunction *fun)
{
uintN n, i;
JSAtom *atom;
jsuword *array;
JS_ASSERT(FUN_INTERPRETED(fun));
n = JS_GET_LOCAL_NAME_COUNT(fun);
if (n == 0)
return;
if (n <= MAX_ARRAY_LOCALS) {
array = (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
array = (n == 1) ? &fun->names.taggedAtom : fun->names.array;
i = n;
do {
--i;
@ -2603,7 +2660,7 @@ TraceLocalNames(JSTracer *trc, JSFunction *fun)
}
} while (i != 0);
} else {
JS_DHashTableEnumerate(&fun->u.i.names.map->names,
JS_DHashTableEnumerate(&fun->names.map->names,
trace_local_names_enumerator, trc);
/*
@ -2614,33 +2671,31 @@ TraceLocalNames(JSTracer *trc, JSFunction *fun)
}
void
DestroyLocalNames(JSContext *cx, JSFunction *fun)
DestroyLocalNames(JSContext *cx, JSScriptedFunction *fun)
{
uintN n;
n = fun->nargs + fun->u.i.nvars;
n = fun->nargs + fun->nvars;
if (n <= 1)
return;
if (n <= MAX_ARRAY_LOCALS)
JS_free(cx, fun->u.i.names.array);
JS_free(cx, fun->names.array);
else
FreeLocalNameHash(cx, fun->u.i.names.map);
FreeLocalNameHash(cx, fun->names.map);
}
void
js_FreezeLocalNames(JSContext *cx, JSFunction *fun)
js_FreezeLocalNames(JSContext *cx, JSScriptedFunction *fun)
{
uintN n;
jsuword *array;
JS_ASSERT(FUN_INTERPRETED(fun));
JS_ASSERT(!fun->u.i.script);
n = fun->nargs + fun->u.i.nvars;
JS_ASSERT(!fun->script);
n = fun->nargs + fun->nvars;
if (2 <= n && n < MAX_ARRAY_LOCALS) {
/* Shrink over-allocated array ignoring realloc failures. */
array = (jsuword *) JS_realloc(cx, fun->u.i.names.array,
n * sizeof *array);
array = (jsuword *) JS_realloc(cx, fun->names.array, n * sizeof *array);
if (array)
fun->u.i.names.array = array;
fun->names.array = array;
}
}

Просмотреть файл

@ -44,6 +44,7 @@
*/
#include "jsprvtd.h"
#include "jspubtd.h"
#include "jsobj.h"
JS_BEGIN_EXTERN_C
@ -62,44 +63,73 @@ typedef union JSLocalNames {
JSLocalNameMap *map;
} JSLocalNames;
struct JSFunction {
JSObject *object; /* back-pointer to GC'ed object header */
struct JSNativeFunction {
JSObject object;
uint16 flags; /* bound method and other flags, see jsapi.h */
uint16 nargs; /* maximum number of specified arguments,
reflected as f.length/f.arity */
uint16 flags; /* bound method and other flags, see jsapi.h */
union {
struct {
uint16 extra; /* number of arg slots for local GC roots */
uint16 minargs;/* minimum number of specified arguments, used
uint16 extra; /* number of arg slots for local GC roots */
uint16 minargs; /* minimum number of specified arguments, used
only when calling fast native */
JSNative native; /* native method pointer or null */
JSClass *clasp; /* if non-null, constructor for this class */
} n;
struct {
uint16 nvars; /* number of local variables */
uint16 spare; /* reserved for future use */
JSScript *script;/* interpreted bytecode descriptor or null */
JSLocalNames names; /* argument and variable names */
} i;
} u;
JSNative native; /* native method pointer or null */
JSClass *clasp; /* if non-null, constructor for this class */
JSAtom *atom; /* name for diagnostics and decompiling */
};
struct JSScriptedFunction {
JSObject *object; /* back-pointer to GC'ed object header */
uint16 flags; /* bound method and other flags, see jsapi.h */
uint16 nargs; /* number of arguments */
uint16 nvars; /* number of local variables */
uint16 spare; /* reserved for future use */
JSScript *script; /* interpreted bytecode descriptor or null */
JSLocalNames names; /* argument and variable names */
JSAtom *atom; /* name for diagnostics and decompiling */
};
#define JSFUN_EXPR_CLOSURE 0x4000 /* expression closure: function(x)x*x */
#define JSFUN_INTERPRETED 0x8000 /* use u.i if set, u.n if unset */
#define JSFUN_SCRIPTED 0x8000 /* use FUN_TO_SCRIPTED if set,
FUN_TO_NATIVE if unset */
#define JSFUN_SCRIPT_OR_FAST_NATIVE (JSFUN_INTERPRETED | JSFUN_FAST_NATIVE)
#define FUN_INTERPRETED(fun) ((fun)->flags & JSFUN_INTERPRETED)
#define FUN_SLOW_NATIVE(fun) (!((fun)->flags & JSFUN_SCRIPT_OR_FAST_NATIVE))
#define FUN_SCRIPT(fun) (FUN_INTERPRETED(fun) ? (fun)->u.i.script : NULL)
#define FUN_NATIVE(fun) (FUN_SLOW_NATIVE(fun) ? (fun)->u.n.native : NULL)
#define FUN_FAST_NATIVE(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
? (JSFastNative) (fun)->u.n.native \
: NULL)
#define FUN_MINARGS(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
? (fun)->u.n.minargs \
: (fun)->nargs)
/*
* JSFunction * points into the flags field of either JSNativeFunction
* or JSScriptedFunction.
*/
#define FUN_FLAGS(fun) (*(uint16 *) (fun))
#define FUN_IS_SCRIPTED(fun) (FUN_FLAGS(fun) & JSFUN_SCRIPTED)
#define FUN_TO_SCRIPTED(fun) \
(JS_ASSERT(FUN_IS_SCRIPTED(fun)), \
(JSScriptedFunction *)((uint8 *)fun - offsetof(JSScriptedFunction, flags)))
#define FUN_TO_NATIVE(fun) \
(JS_ASSERT(!FUN_IS_SCRIPTED(fun)), \
(JSNativeFunction *)((uint8 *)fun - offsetof(JSNativeFunction, flags)))
#define NATIVE_TO_FUN(nfun) \
(JS_ASSERT(((nfun)->flags & JSFUN_SCRIPTED) == 0), \
(JSFunction *) (void *) &(nfun)->flags)
#define SCRIPTED_TO_FUN(sfun) \
(JS_ASSERT((sfun)->flags & JSFUN_SCRIPTED), \
(JSFunction *) (void *) &(sfun)->flags)
#define FUN_NARGS(fun) (FUN_IS_SCRIPTED(fun) \
? FUN_TO_SCRIPTED(fun)->nargs \
: FUN_TO_NATIVE(fun)->nargs)
#define FUN_OBJECT(fun) (FUN_IS_SCRIPTED(fun) \
? FUN_TO_SCRIPTED(fun)->object \
: &FUN_TO_NATIVE(fun)->object)
#define FUN_ATOM(fun) (FUN_IS_SCRIPTED(fun) \
? FUN_TO_SCRIPTED(fun)->atom \
: FUN_TO_NATIVE(fun)->atom)
#define NATIVE_FUN_MINARGS(nfun) \
(((nfun)->flags & JSFUN_FAST_NATIVE) ? (nfun)->minargs : (nfun)->nargs)
extern JSClass js_ArgumentsClass;
extern JS_FRIEND_DATA(JSClass) js_CallClass;
@ -107,19 +137,20 @@ extern JS_FRIEND_DATA(JSClass) js_CallClass;
/* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */
extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
#define HAS_FUNCTION_CLASS(obj) (STOBJ_GET_CLASS(obj) == &js_FunctionClass)
/*
* NB: jsapi.h and jsobj.h must be included before any call to this macro.
*/
#define VALUE_IS_FUNCTION(cx, v) \
(!JSVAL_IS_PRIMITIVE(v) && \
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass)
(!JSVAL_IS_PRIMITIVE(v) && HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)))
/*
* Macro to access the private slot of the function object after the slot is
* initialized.
*/
#define GET_FUNCTION_PRIVATE(cx, funobj) \
(JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass), \
(JS_ASSERT(HAS_FUNCTION_CLASS(funobj)), \
(JSFunction *) OBJ_GET_PRIVATE(cx, funobj))
extern JSObject *
@ -135,19 +166,24 @@ extern JSFunction *
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
uintN flags, JSObject *parent, JSAtom *atom);
extern void
js_TraceFunction(JSTracer *trc, JSFunction *fun);
extern JSNativeFunction *
js_NewNativeFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
JSObject *parent, JSAtom *atom);
extern JSScriptedFunction *
js_NewScriptedFunction(JSContext *cx, JSObject *funobj, uintN flags,
JSObject *parent, JSAtom *atom);
extern void
js_FinalizeFunction(JSContext *cx, JSFunction *fun);
js_TraceFunction(JSTracer *trc, JSScriptedFunction *fun);
extern void
js_FinalizeFunction(JSContext *cx, JSScriptedFunction *fun);
extern JSObject *
js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
extern JSBool
js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *object);
extern JSFunction *
extern JSNativeFunction *
js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
uintN nargs, uintN flags);
@ -206,10 +242,11 @@ typedef enum JSLocalKind {
JSLOCAL_CONST
} JSLocalKind;
#define JS_GET_LOCAL_NAME_COUNT(fun) ((fun)->nargs + (fun)->u.i.nvars)
#define JS_GET_LOCAL_NAME_COUNT(fun) ((fun)->nargs + (fun)->nvars)
extern JSBool
js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind);
js_AddLocal(JSContext *cx, JSScriptedFunction *fun, JSAtom *atom,
JSLocalKind kind);
/*
* Look up an argument or variable name returning its kind when found or
@ -218,7 +255,8 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind);
* variable.
*/
extern JSLocalKind
js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp);
js_LookupLocal(JSContext *cx, JSScriptedFunction *fun, JSAtom *atom,
uintN *indexp);
/*
* Functions to work with local names as an array of words.
@ -235,7 +273,7 @@ js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp);
* corresponds to the const declaration.
*/
extern jsuword *
js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool);
js_GetLocalNameArray(JSContext *cx, JSScriptedFunction *fun, JSArenaPool *pool);
#define JS_LOCAL_NAME_TO_ATOM(nameWord) \
((JSAtom *) ((nameWord) & ~(jsuword) 1))
@ -244,7 +282,7 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool);
((((nameWord) & (jsuword) 1)) != 0)
extern void
js_FreezeLocalNames(JSContext *cx, JSFunction *fun);
js_FreezeLocalNames(JSContext *cx, JSScriptedFunction *fun);
JS_END_EXTERN_C

Просмотреть файл

@ -2250,8 +2250,8 @@ JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind)
JS_CALL_STRING_TRACER(trc, JSSTRDEP_BASE(str), "base");
break;
case JSTRACE_FUNCTION:
js_TraceFunction(trc, (JSFunction *)thing);
case JSTRACE_SCRIPTED_FUNCTION:
js_TraceFunction(trc, (JSScriptedFunction *) thing);
break;
#if JS_HAS_XML_SUPPORT
@ -2660,7 +2660,7 @@ gc_lock_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
void
js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
{
uintN nslots, minargs, skip;
uintN nslots, skip;
if (fp->callobj)
JS_CALL_OBJECT_TRACER(trc, fp->callobj, "call");
@ -2682,8 +2682,8 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
}
/* Allow for primitive this parameter due to JSFUN_THISP_* flags. */
JS_ASSERT(JSVAL_IS_OBJECT((jsval)fp->thisp) ||
(fp->fun && JSFUN_THISP_FLAGS(fp->fun->flags)));
JS_ASSERT_IF(!JSVAL_IS_OBJECT((jsval)fp->thisp),
fp->fun && JSFUN_THISP_FLAGS(FUN_FLAGS(fp->fun)));
JS_CALL_VALUE_TRACER(trc, (jsval)fp->thisp, "this");
if (fp->callee)
@ -2693,14 +2693,22 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
nslots = fp->argc;
skip = 0;
if (fp->fun) {
minargs = FUN_MINARGS(fp->fun);
if (minargs > nslots)
nslots = minargs;
if (!FUN_INTERPRETED(fp->fun)) {
JS_ASSERT(!(fp->fun->flags & JSFUN_FAST_NATIVE));
nslots += fp->fun->u.n.extra;
if (FUN_IS_SCRIPTED(fp->fun)) {
JSScriptedFunction *sfun;
sfun = FUN_TO_SCRIPTED(fp->fun);
if (nslots < sfun->nargs)
nslots = sfun->nargs;
} else {
JSNativeFunction *nfun;
JS_ASSERT(!(FUN_FLAGS(fp->fun) & JSFUN_FAST_NATIVE));
nfun = FUN_TO_NATIVE(fp->fun);
if (nslots < nfun->nargs)
nslots = nfun->nargs;
nslots += nfun->extra;
}
if (fp->fun->flags & JSFRAME_ROOTED_ARGV)
if (fp->flags & JSFRAME_ROOTED_ARGV)
skip = 2 + fp->argc;
}
TRACE_JSVALS(trc, 2 + nslots - skip, fp->argv - 2 + skip, "operand");
@ -3328,7 +3336,8 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
/* Do nothing. */
break;
case GCX_FUNCTION:
js_FinalizeFunction(cx, (JSFunction *) thing);
js_FinalizeFunction(cx,
(JSScriptedFunction *) thing);
break;
#if JS_HAS_XML_SUPPORT
case GCX_NAMESPACE:

Просмотреть файл

@ -52,15 +52,15 @@ JS_BEGIN_EXTERN_C
JS_STATIC_ASSERT(JSTRACE_STRING == 2);
#define JSTRACE_FUNCTION 3
#define JSTRACE_NAMESPACE 4
#define JSTRACE_QNAME 5
#define JSTRACE_XML 6
#define JSTRACE_SCRIPTED_FUNCTION 3
#define JSTRACE_NAMESPACE 4
#define JSTRACE_QNAME 5
#define JSTRACE_XML 6
/*
* One past the maximum trace kind.
*/
#define JSTRACE_LIMIT 7
#define JSTRACE_LIMIT 7
/*
* We use the trace kinds as the types for all GC things except external
@ -69,7 +69,8 @@ JS_STATIC_ASSERT(JSTRACE_STRING == 2);
#define GCX_OBJECT JSTRACE_OBJECT /* JSObject */
#define GCX_DOUBLE JSTRACE_DOUBLE /* jsdouble */
#define GCX_STRING JSTRACE_STRING /* JSString */
#define GCX_FUNCTION JSTRACE_FUNCTION /* JSFunction */
#define GCX_FUNCTION JSTRACE_SCRIPTED_FUNCTION
/* JSScriptedFunction */
#define GCX_NAMESPACE JSTRACE_NAMESPACE /* JSXMLNamespace */
#define GCX_QNAME JSTRACE_QNAME /* JSXMLQName */
#define GCX_XML JSTRACE_XML /* JSXML */
@ -235,14 +236,15 @@ js_IsAboutToBeFinalized(JSContext *cx, void *thing);
#if JS_HAS_XML_SUPPORT
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_XML)
#else
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_FUNCTION)
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= \
JSTRACE_SCRIPTED_FUNCTION)
#endif
/*
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_FUNCTION is the last non-xml
* trace kind when JS_HAS_XML_SUPPORT is false.
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_SCRIPTED_FUNCTION is the last
* non-xml trace kind when JS_HAS_XML_SUPPORT is false.
*/
JS_STATIC_ASSERT(JSTRACE_FUNCTION + 1 == JSTRACE_NAMESPACE);
JS_STATIC_ASSERT(JSTRACE_SCRIPTED_FUNCTION + 1 == JSTRACE_NAMESPACE);
/*
* Trace jsval when JSVAL_IS_OBJECT(v) can be an arbitrary GC thing casted as

Просмотреть файл

@ -645,7 +645,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
* insist that there is a call object for a heavyweight function call.
*/
JS_ASSERT(!fp->fun ||
!(fp->fun->flags & JSFUN_HEAVYWEIGHT) ||
!(FUN_FLAGS(fp->fun) & JSFUN_HEAVYWEIGHT) ||
fp->callobj);
JS_ASSERT(fp->scopeChain);
return fp->scopeChain;
@ -931,7 +931,7 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp)
vp[0] = ID_TO_VALUE(id);
}
#endif
obj = js_NewObject(cx, &js_NoSuchMethodClass, NULL, NULL);
obj = js_NewObject(cx, &js_NoSuchMethodClass, NULL, NULL, 0);
if (!obj) {
ok = JS_FALSE;
goto out;
@ -1088,20 +1088,27 @@ js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags)
have_fun:
/* Get private data and set derived locals from it. */
fun = GET_FUNCTION_PRIVATE(cx, funobj);
nslots = FUN_MINARGS(fun);
nslots = (nslots > argc) ? nslots - argc : 0;
if (FUN_INTERPRETED(fun)) {
if (FUN_IS_SCRIPTED(fun)) {
JSScriptedFunction *sfun;
sfun = FUN_TO_SCRIPTED(fun);
native = NULL;
script = fun->u.i.script;
nvars = fun->u.i.nvars;
script = sfun->script;
nvars = sfun->nvars;
nslots = (sfun->nargs > argc) ? sfun->nargs - argc : 0;
} else {
native = fun->u.n.native;
JSNativeFunction *nfun;
nfun = FUN_TO_NATIVE(fun);
native = nfun->native;
script = NULL;
nvars = 0;
nslots += fun->u.n.extra;
nslots = NATIVE_FUN_MINARGS(nfun);
nslots = (nslots > argc) ? nslots - argc : 0;
nslots += nfun->extra;
}
if (JSFUN_BOUND_METHOD_TEST(fun->flags)) {
if (JSFUN_BOUND_METHOD_TEST(FUN_FLAGS(fun))) {
/* Handle bound method special case. */
vp[1] = OBJECT_TO_JSVAL(parent);
} else if (!JSVAL_IS_OBJECT(vp[1])) {
@ -1124,7 +1131,7 @@ have_fun:
* JS_THIS or JS_THIS_OBJECT, and scripted functions will go through
* the appropriate this-computing bytecode, e.g., JSOP_THIS.
*/
if (native && (!fun || !(fun->flags & JSFUN_FAST_NATIVE))) {
if (native && (!fun || !(FUN_FLAGS(fun) & JSFUN_FAST_NATIVE))) {
if (!js_ComputeThis(cx, JS_FALSE, vp + 2)) {
ok = JS_FALSE;
goto out2;
@ -1164,7 +1171,7 @@ have_fun:
} while (--i != 0);
}
if (native && fun && (fun->flags & JSFUN_FAST_NATIVE)) {
if (native && fun && (FUN_FLAGS(fun) & JSFUN_FAST_NATIVE)) {
JSTempValueRooter tvr;
#ifdef DEBUG_NOT_THROWING
JSBool alreadyThrowing = cx->throwing;
@ -1286,7 +1293,7 @@ have_fun:
} else if (script) {
/* Use parent scope so js_GetCallObject can find the right "Call". */
frame.scopeChain = parent;
if (JSFUN_HEAVYWEIGHT_TEST(fun->flags)) {
if (JSFUN_HEAVYWEIGHT_TEST(FUN_FLAGS(fun))) {
/* Scope with a call object parented by the callee's parent. */
if (!js_GetCallObject(cx, &frame, parent)) {
ok = JS_FALSE;
@ -1401,7 +1408,7 @@ js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
JS_ASSERT(mode == JSACC_READ || mode == JSACC_WRITE);
if (cx->runtime->checkObjectAccess &&
VALUE_IS_FUNCTION(cx, fval) &&
FUN_INTERPRETED(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fval))) &&
FUN_IS_SCRIPTED(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fval))) &&
!cx->runtime->checkObjectAccess(cx, obj, ID_TO_VALUE(id), mode,
&fval)) {
return JS_FALSE;
@ -1835,11 +1842,16 @@ js_InvokeConstructor(JSContext *cx, jsval *vp, uintN argc)
if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) {
fun2 = GET_FUNCTION_PRIVATE(cx, obj2);
if (!FUN_INTERPRETED(fun2) && fun2->u.n.clasp)
clasp = fun2->u.n.clasp;
if (!FUN_IS_SCRIPTED(fun2)) {
JSNativeFunction *nfun;
nfun = FUN_TO_NATIVE(fun2);
if (nfun->clasp)
clasp = nfun->clasp;
}
}
}
obj = js_NewObject(cx, clasp, proto, parent);
obj = js_NewObject(cx, clasp, proto, parent, 0);
if (!obj)
return JS_FALSE;
@ -2452,6 +2464,7 @@ js_Interpret(JSContext *cx)
jsdouble d, d2;
JSClass *clasp;
JSFunction *fun;
JSScriptedFunction *sfun;
JSType type;
#if !JS_THREADED_INTERP && defined DEBUG
FILE *tracefp = NULL;
@ -3114,13 +3127,13 @@ interrupt:
switch (op) {
case JSOP_FORARG:
slot = GET_ARGNO(regs.pc);
JS_ASSERT(slot < fp->fun->nargs);
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nargs);
fp->argv[slot] = rval;
break;
case JSOP_FORVAR:
slot = GET_VARNO(regs.pc);
JS_ASSERT(slot < fp->fun->u.i.nvars);
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nvars);
fp->vars[slot] = rval;
break;
@ -3951,7 +3964,7 @@ interrupt:
do_arg_incop:
slot = GET_ARGNO(regs.pc);
JS_ASSERT(slot < fp->fun->nargs);
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nargs);
METER_SLOT_OP(op, slot);
vp = fp->argv + slot;
goto do_int_fast_incop;
@ -3987,7 +4000,7 @@ interrupt:
*/
do_var_incop:
slot = GET_VARNO(regs.pc);
JS_ASSERT(slot < fp->fun->u.i.nvars);
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nvars);
METER_SLOT_OP(op, slot);
vp = fp->vars + slot;
@ -4087,7 +4100,7 @@ interrupt:
BEGIN_CASE(JSOP_GETARGPROP)
i = ARGNO_LEN;
slot = GET_ARGNO(regs.pc);
JS_ASSERT(slot < fp->fun->nargs);
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nargs);
PUSH_OPND(fp->argv[slot]);
len = JSOP_GETARGPROP_LENGTH;
goto do_getprop_body;
@ -4095,7 +4108,7 @@ interrupt:
BEGIN_CASE(JSOP_GETVARPROP)
i = VARNO_LEN;
slot = GET_VARNO(regs.pc);
JS_ASSERT(slot < fp->fun->u.i.nvars);
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nvars);
PUSH_OPND(fp->vars[slot]);
len = JSOP_GETVARPROP_LENGTH;
goto do_getprop_body;
@ -4601,10 +4614,11 @@ interrupt:
vp = regs.sp - (argc + 2);
lval = *vp;
if (VALUE_IS_FUNCTION(cx, lval)) {
JSNativeFunction *nfun;
obj = JSVAL_TO_OBJECT(lval);
fun = GET_FUNCTION_PRIVATE(cx, obj);
if (FUN_INTERPRETED(fun)) {
if (FUN_IS_SCRIPTED(fun)) {
uintN nframeslots, nvars, missing;
JSArena *a;
jsuword nbytes;
@ -4616,8 +4630,9 @@ interrupt:
/* Compute the total number of stack slots needed by fun. */
nframeslots = JS_HOWMANY(sizeof(JSInlineFrame),
sizeof(jsval));
nvars = fun->u.i.nvars;
script = fun->u.i.script;
sfun = FUN_TO_SCRIPTED(fun);
nvars = sfun->nvars;
script = sfun->script;
atoms = script->atomMap.vector;
nbytes = (nframeslots + nvars + script->depth) *
sizeof(jsval);
@ -4625,10 +4640,10 @@ interrupt:
/* Allocate missing expected args adjacent to actuals. */
a = cx->stackPool.current;
newmark = (void *) a->avail;
if (fun->nargs <= argc) {
if (sfun->nargs <= argc) {
missing = 0;
} else {
newsp = vp + 2 + fun->nargs;
newsp = vp + 2 + sfun->nargs;
JS_ASSERT(newsp > regs.sp);
if ((jsuword) newsp <= a->limit) {
if ((jsuword) newsp > a->avail)
@ -4638,8 +4653,8 @@ interrupt:
} while (newsp != regs.sp);
missing = 0;
} else {
missing = fun->nargs - argc;
nbytes += (2 + fun->nargs) * sizeof(jsval);
missing = sfun->nargs - argc;
nbytes += (2 + sfun->nargs) * sizeof(jsval);
}
}
@ -4700,7 +4715,7 @@ interrupt:
newifp->mark = newmark;
/* Compute the 'this' parameter now that argv is set. */
JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags));
JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(sfun->flags));
JS_ASSERT(JSVAL_IS_OBJECT(vp[1]));
newifp->frame.thisp = (JSObject *)vp[1];
@ -4722,7 +4737,7 @@ interrupt:
}
/* Scope with a call object parented by callee's parent. */
if (JSFUN_HEAVYWEIGHT_TEST(fun->flags) &&
if (JSFUN_HEAVYWEIGHT_TEST(sfun->flags) &&
!js_GetCallObject(cx, &newifp->frame, parent)) {
goto bad_inline_call;
}
@ -4780,16 +4795,17 @@ interrupt:
}
#endif
if (fun->flags & JSFUN_FAST_NATIVE) {
JS_ASSERT(fun->u.n.extra == 0);
if (argc < fun->u.n.minargs) {
uintN nargs;
nfun = FUN_TO_NATIVE(fun);
if (nfun->flags & JSFUN_FAST_NATIVE) {
uintN nargs;
JS_ASSERT(nfun->extra == 0);
if (argc < nfun->minargs) {
/*
* If we can't fit missing args and local roots in
* this frame's operand stack, take the slow path.
*/
nargs = fun->u.n.minargs - argc;
nargs = nfun->minargs - argc;
if (regs.sp + nargs > fp->spbase + script->depth)
goto do_invoke;
do {
@ -4800,7 +4816,7 @@ interrupt:
JS_ASSERT(JSVAL_IS_OBJECT(vp[1]) ||
PRIMITIVE_THIS_TEST(fun, vp[1]));
ok = ((JSFastNative) fun->u.n.native)(cx, argc, vp);
ok = ((JSFastNative) nfun->native)(cx, argc, vp);
#ifdef INCLUDE_MOZILLA_DTRACE
if (VALUE_IS_FUNCTION(cx, lval)) {
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
@ -5394,7 +5410,7 @@ interrupt:
BEGIN_CASE(JSOP_GETARG)
BEGIN_CASE(JSOP_CALLARG)
slot = GET_ARGNO(regs.pc);
JS_ASSERT(slot < fp->fun->nargs);
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nargs);
METER_SLOT_OP(op, slot);
PUSH_OPND(fp->argv[slot]);
if (op == JSOP_CALLARG)
@ -5403,7 +5419,7 @@ interrupt:
BEGIN_CASE(JSOP_SETARG)
slot = GET_ARGNO(regs.pc);
JS_ASSERT(slot < fp->fun->nargs);
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nargs);
METER_SLOT_OP(op, slot);
vp = &fp->argv[slot];
GC_POKE(cx, *vp);
@ -5413,7 +5429,7 @@ interrupt:
BEGIN_CASE(JSOP_GETVAR)
BEGIN_CASE(JSOP_CALLVAR)
slot = GET_VARNO(regs.pc);
JS_ASSERT(slot < fp->fun->u.i.nvars);
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nvars);
METER_SLOT_OP(op, slot);
PUSH_OPND(fp->vars[slot]);
if (op == JSOP_CALLVAR)
@ -5422,7 +5438,7 @@ interrupt:
BEGIN_CASE(JSOP_SETVAR)
slot = GET_VARNO(regs.pc);
JS_ASSERT(slot < fp->fun->u.i.nvars);
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nvars);
METER_SLOT_OP(op, slot);
vp = &fp->vars[slot];
GC_POKE(cx, *vp);
@ -5601,8 +5617,8 @@ interrupt:
* and setters do not need a slot, their value is stored elsewhere
* in the property itself, not in obj slots.
*/
fun = GET_FUNCTION_PRIVATE(cx, obj);
flags = JSFUN_GSFLAG2ATTR(fun->flags);
sfun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
flags = JSFUN_GSFLAG2ATTR(sfun->flags);
if (flags) {
attrs |= flags | JSPROP_SHARED;
rval = JSVAL_VOID;
@ -5622,7 +5638,7 @@ interrupt:
* here at runtime as well as at compile-time, to handle eval
* as well as multiple HTML script tags.
*/
id = ATOM_TO_JSID(fun->atom);
id = ATOM_TO_JSID(sfun->atom);
ok = js_CheckRedeclaration(cx, parent, id, attrs, NULL, NULL);
if (ok) {
if (attrs == JSPROP_ENUMERATE) {
@ -5705,7 +5721,7 @@ interrupt:
obj2 = js_GetScopeChain(cx, fp);
if (!obj2)
goto error;
parent = js_NewObject(cx, &js_ObjectClass, NULL, obj2);
parent = js_NewObject(cx, &js_ObjectClass, NULL, obj2, 0);
if (!parent)
goto error;
@ -5738,16 +5754,17 @@ interrupt:
/*
* 4. Create a property in the object Result(1). The property's
* name is [fun->atom, the identifier parsed by the compiler],
* name is [sfun->atom, the identifier parsed by the compiler],
* value is Result(3), and attributes are { DontDelete, ReadOnly }.
*/
fun = GET_FUNCTION_PRIVATE(cx, obj);
attrs = JSFUN_GSFLAG2ATTR(fun->flags);
sfun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
attrs = JSFUN_GSFLAG2ATTR(sfun->flags);
if (attrs) {
attrs |= JSPROP_SHARED;
rval = JSVAL_VOID;
}
ok = OBJ_DEFINE_PROPERTY(cx, parent, ATOM_TO_JSID(fun->atom), rval,
ok = OBJ_DEFINE_PROPERTY(cx, parent, ATOM_TO_JSID(sfun->atom),
rval,
(attrs & JSPROP_GETTER)
? JS_EXTENSION (JSPropertyOp) obj
: JS_PropertyStub,
@ -5908,7 +5925,7 @@ interrupt:
JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
obj = (i == JSProto_Array)
? js_NewArrayObject(cx, 0, NULL)
: js_NewObject(cx, &js_ObjectClass, NULL, NULL);
: js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
if (!obj)
goto error;
PUSH_OPND(OBJECT_TO_JSVAL(obj));

Просмотреть файл

@ -397,7 +397,7 @@ extern const uint16 js_PrimitiveTestFlags[];
#define PRIMITIVE_THIS_TEST(fun,thisv) \
(JS_ASSERT(thisv != JSVAL_VOID), \
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS(FUN_FLAGS(fun)), \
js_PrimitiveTestFlags[JSVAL_TAG(thisv) - 1]))
/*

Просмотреть файл

@ -400,7 +400,7 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
* we use the parent slot to keep track of the iterable, we must
* fix it up after.
*/
iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL);
iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL, 0);
if (!iterobj)
goto bad;
@ -725,13 +725,13 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp)
jsval *newsp;
/* After the following return, failing control flow must goto bad. */
obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL);
obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL, 0);
if (!obj)
return NULL;
/* Load and compute stack slot counts. */
argc = fp->argc;
nargs = JS_MAX(argc, fp->fun->nargs);
nargs = JS_MAX(argc, FUN_TO_SCRIPTED(fp->fun)->nargs);
nvars = fp->nvars;
nslots = 2 + nargs + nvars + fp->script->depth;

Просмотреть файл

@ -863,8 +863,9 @@ obj_toSource(JSContext *cx, uintN argc, jsval *vp)
* they might appear here. This code can be confused by people
* defining Function.prototype.toString, so let's be cautious.
*/
if (JSFUN_GETTER_TEST(fun->flags) ||
JSFUN_SETTER_TEST(fun->flags)) { /* skip "getter/setter" */
if (JSFUN_GETTER_TEST(FUN_FLAGS(fun)) ||
JSFUN_SETTER_TEST(FUN_FLAGS(fun))) {
/* skip "getter/setter" */
const jschar *tmp = js_strchr_limit(vchars, ' ', end);
if (tmp)
vchars = tmp + 1;
@ -1754,7 +1755,7 @@ Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JS_ASSERT(!argc || JSVAL_IS_NULL(argv[0]) || JSVAL_IS_VOID(argv[0]));
if (cx->fp->flags & JSFRAME_CONSTRUCTING)
return JS_TRUE;
obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
}
@ -1895,7 +1896,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
{
JSObject *obj;
obj = js_NewObject(cx, &js_WithClass, proto, parent);
obj = js_NewObject(cx, &js_WithClass, proto, parent, 0);
if (!obj)
return NULL;
STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(cx->fp));
@ -1914,7 +1915,7 @@ js_NewBlockObject(JSContext *cx)
* scopes. Make sure obj has its own scope too, since clearing proto does
* not affect OBJ_SCOPE(obj).
*/
obj = js_NewObject(cx, &js_BlockClass, NULL, NULL);
obj = js_NewObject(cx, &js_BlockClass, NULL, NULL, 0);
if (!obj)
return NULL;
JS_LOCK_OBJ(cx, obj);
@ -1932,7 +1933,7 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, JSObject *parent,
{
JSObject *clone;
clone = js_NewObject(cx, &js_BlockClass, proto, parent);
clone = js_NewObject(cx, &js_BlockClass, proto, parent, 0);
if (!clone)
return NULL;
STOBJ_SET_SLOT(clone, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(fp));
@ -2418,7 +2419,8 @@ js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp)
}
JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
uintN extraBytes)
{
jsid id;
@ -2435,12 +2437,12 @@ js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
}
}
return js_NewObjectWithGivenProto(cx, clasp, proto, parent);
return js_NewObjectWithGivenProto(cx, clasp, proto, parent, extraBytes);
}
JSObject *
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent)
JSObject *parent, uintN extraBytes)
{
JSObject *obj;
JSObjectOps *ops;
@ -2464,7 +2466,8 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
* GC-thing allocations under js_GetClassPrototype or clasp->getObjectOps,
* to avoid displacing the newborn root for obj.
*/
obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT,
sizeof(JSObject) + extraBytes);
if (!obj)
goto earlybad;
@ -2766,7 +2769,7 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
proto = JSVAL_TO_OBJECT(rval);
}
obj = js_NewObject(cx, clasp, proto, parent);
obj = js_NewObject(cx, clasp, proto, parent, 0);
if (!obj)
goto out;
@ -4651,7 +4654,7 @@ js_PrimitiveToObject(JSContext *cx, jsval *vp)
JS_ASSERT(!JSVAL_IS_OBJECT(*vp));
JS_ASSERT(*vp != JSVAL_VOID);
clasp = PrimitiveClasses[JSVAL_TAG(*vp) - 1];
obj = js_NewObject(cx, clasp, NULL, NULL);
obj = js_NewObject(cx, clasp, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, *vp);

Просмотреть файл

@ -432,14 +432,15 @@ extern JSBool
js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp);
extern JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
uintN extraBytes);
/*
* See jsapi.h, JS_NewObjectWithGivenProto.
*/
extern JSObject *
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent);
JSObject *parent, uintN extraBytes);
/*
* Fast access to immutable standard objects (constructors and prototypes).

Просмотреть файл

@ -617,7 +617,7 @@ struct JSPrinter {
JSScript *script; /* script being printed */
jsbytecode *dvgfence; /* DecompileExpression fencepost */
jsbytecode **pcstack; /* DecompileExpression modelled stack */
JSFunction *fun; /* interpreted function */
JSScriptedFunction *fun; /* interpreted function */
jsuword *localNames; /* argument and variable names */
};
@ -630,8 +630,7 @@ struct JSPrinter {
#define JS_IN_GROUP_CONTEXT 0x10000
JSPrinter *
JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
uintN indent, JSBool pretty)
JS_NEW_PRINTER(JSContext *cx, const char *name, uintN indent, JSBool pretty)
{
JSPrinter *jp;
@ -646,15 +645,8 @@ JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
jp->script = NULL;
jp->dvgfence = NULL;
jp->pcstack = NULL;
jp->fun = fun;
jp->localNames = NULL;
if (fun && FUN_INTERPRETED(fun) && JS_GET_LOCAL_NAME_COUNT(fun)) {
jp->localNames = js_GetLocalNameArray(cx, fun, &jp->pool);
if (!jp->localNames) {
js_DestroyPrinter(jp);
return NULL;
}
}
jp->fun = NULL;
return jp;
}
@ -665,6 +657,21 @@ js_DestroyPrinter(JSPrinter *jp)
JS_free(jp->sprinter.context, jp);
}
static JSBool
InitFunctionPrinter(JSPrinter *jp, JSScriptedFunction *fun)
{
JS_ASSERT(!jp->fun);
JS_ASSERT(!jp->localNames);
if (JS_GET_LOCAL_NAME_COUNT(fun) != 0) {
jp->localNames = js_GetLocalNameArray(jp->sprinter.context, fun,
&jp->pool);
if (!jp->localNames)
return JS_FALSE;
}
jp->fun = fun;
return JS_TRUE;
}
JSString *
js_GetPrinterOutput(JSPrinter *jp)
{
@ -789,7 +796,7 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *pc,
* decompiled string on success.
*/
static char *
DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
DecompileExpression(JSContext *cx, JSScript *script, JSScriptedFunction *fun,
jsbytecode *pc);
/*
@ -1129,17 +1136,15 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
static JSAtom *
GetSlotAtom(JSPrinter *jp, JSBool argument, uintN slot)
{
JSFunction *fun;
JSAtom *name;
fun = jp->fun;
LOCAL_ASSERT_RV(jp->fun, NULL);
LOCAL_ASSERT_RV(jp->localNames, NULL);
if (argument) {
LOCAL_ASSERT_RV(slot < fun->nargs, NULL);
LOCAL_ASSERT_RV(slot < jp->fun->nargs, NULL);
} else {
LOCAL_ASSERT_RV(slot < fun->u.i.nvars, NULL);
slot += fun->nargs;
LOCAL_ASSERT_RV(slot < jp->fun->nvars, NULL);
slot += jp->fun->nargs;
}
name = JS_LOCAL_NAME_TO_ATOM(jp->localNames[slot]);
#if !JS_HAS_DESTRUCTURING
@ -1631,7 +1636,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
char **argv;
JSAtom *atom;
JSObject *obj;
JSFunction *fun;
JSScriptedFunction *fun;
JSString *str;
JSBool ok;
#if JS_HAS_XML_SUPPORT
@ -2020,12 +2025,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
obj);
do_function:
js_puts(jp, "\n");
fun = GET_FUNCTION_PRIVATE(cx, obj);
jp2 = JS_NEW_PRINTER(cx, "nested_function", fun,
jp2 = JS_NEW_PRINTER(cx, "nested_function",
jp->indent, jp->pretty);
if (!jp2)
return NULL;
ok = js_DecompileFunction(jp2);
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
ok = js_DecompileFunction(jp2, fun);
if (ok && jp2->sprinter.base)
js_puts(jp, jp2->sprinter.base);
js_DestroyPrinter(jp2);
@ -3767,9 +3772,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
SprintStack ss2;
LOAD_FUNCTION(0);
fun = GET_FUNCTION_PRIVATE(cx, obj);
LOCAL_ASSERT(FUN_INTERPRETED(fun));
inner = fun->u.i.script;
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
inner = fun->script;
/*
* All allocation when decompiling is LIFO, using malloc
@ -3884,10 +3888,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
* parenthesization without confusing getter/setter code
* that checks for JSOP_ANONFUNOBJ and JSOP_NAMEDFUNOBJ.
*/
fun = GET_FUNCTION_PRIVATE(cx, obj);
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
if (!(fun->flags & JSFUN_EXPR_CLOSURE))
indent |= JS_IN_GROUP_CONTEXT;
str = JS_DecompileFunction(cx, fun, indent);
str = JS_DecompileFunction(cx, SCRIPTED_TO_FUN(fun),
indent);
if (!str)
return NULL;
}
@ -4615,55 +4620,83 @@ out:
return ok;
}
static const char native_code_str[] = "\t[native code]\n";
JSBool
js_DecompileNativeFunction(JSPrinter *jp, JSNativeFunction *fun)
{
if (jp->pretty)
js_printf(jp, "\t");
if (JSFUN_GETTER_TEST(fun->flags))
js_printf(jp, "%s ", js_getter_str);
else if (JSFUN_SETTER_TEST(fun->flags))
js_printf(jp, "%s ", js_setter_str);
js_printf(jp, "%s ", js_function_str);
if (fun->atom && !QuoteString(&jp->sprinter, ATOM_TO_STRING(fun->atom), 0))
return JS_FALSE;
js_printf(jp, "() {\n");
jp->indent += 4;
js_printf(jp, native_code_str);
jp->indent -= 4;
js_printf(jp, "\t}");
return JS_TRUE;
}
JSBool
js_DecompileNativeFunctionBody(JSPrinter *jp, JSNativeFunction *fun)
{
js_printf(jp, native_code_str);
return JS_TRUE;
}
JSBool
js_DecompileScript(JSPrinter *jp, JSScript *script)
{
return DecompileCode(jp, script, script->code, (uintN)script->length, 0);
}
static const char native_code_str[] = "\t[native code]\n";
JSBool
js_DecompileFunctionBody(JSPrinter *jp)
js_DecompileFunctionBody(JSPrinter *jp, JSScriptedFunction *fun)
{
JSScript *script;
JS_ASSERT(jp->fun);
JS_ASSERT(!jp->script);
if (!FUN_INTERPRETED(jp->fun)) {
js_printf(jp, native_code_str);
return JS_TRUE;
}
script = jp->fun->u.i.script;
JS_ASSERT(!jp->fun);
if (!InitFunctionPrinter(jp, fun))
return JS_FALSE;
script = fun->script;
return DecompileCode(jp, script, script->code, (uintN)script->length, 0);
}
JSBool
js_DecompileFunction(JSPrinter *jp)
js_DecompileFunction(JSPrinter *jp, JSScriptedFunction *fun)
{
JSFunction *fun;
uintN i;
JSAtom *param;
jsbytecode *pc, *endpc;
ptrdiff_t len;
JSBool ok;
#ifdef JS_HAS_DESTRUCTURING
SprintStack ss;
void *mark;
#endif
fun = jp->fun;
JS_ASSERT(fun);
JS_ASSERT(!jp->script);
if (!InitFunctionPrinter(jp, fun))
return JS_FALSE;
/*
* If pretty, conform to ECMA-262 Edition 3, 15.3.4.2, by decompiling a
* FunctionDeclaration. Otherwise, check the JSFUN_LAMBDA flag and force
* an expression by parenthesizing.
*/
if (jp->pretty) {
if (jp->pretty)
js_printf(jp, "\t");
} else {
if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
js_puts(jp, "(");
}
else if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
js_puts(jp, "(");
if (JSFUN_GETTER_TEST(fun->flags))
js_printf(jp, "%s ", js_getter_str);
else if (JSFUN_SETTER_TEST(fun->flags))
@ -4674,102 +4707,89 @@ js_DecompileFunction(JSPrinter *jp)
return JS_FALSE;
js_puts(jp, "(");
if (!FUN_INTERPRETED(fun)) {
js_printf(jp, ") {\n");
jp->indent += 4;
js_printf(jp, native_code_str);
jp->indent -= 4;
js_printf(jp, "\t}");
} else {
#ifdef JS_HAS_DESTRUCTURING
SprintStack ss;
void *mark;
#endif
/* Print the parameters. */
pc = fun->u.i.script->main;
endpc = pc + fun->u.i.script->length;
ok = JS_TRUE;
/* Print the parameters. */
pc = fun->script->main;
endpc = pc + fun->script->length;
ok = JS_TRUE;
#ifdef JS_HAS_DESTRUCTURING
/* Skip JSOP_GENERATOR in case of destructuring parameters. */
if (*pc == JSOP_GENERATOR)
pc += JSOP_GENERATOR_LENGTH;
/* Skip JSOP_GENERATOR in case of destructuring parameters. */
if (*pc == JSOP_GENERATOR)
pc += JSOP_GENERATOR_LENGTH;
ss.printer = NULL;
jp->script = fun->u.i.script;
mark = JS_ARENA_MARK(&jp->sprinter.context->tempPool);
ss.printer = NULL;
jp->script = fun->script;
mark = JS_ARENA_MARK(&jp->sprinter.context->tempPool);
#endif
for (i = 0; i < fun->nargs; i++) {
if (i > 0)
js_puts(jp, ", ");
for (i = 0; i < fun->nargs; i++) {
if (i > 0)
js_puts(jp, ", ");
param = GetSlotAtom(jp, JS_TRUE, i);
param = GetSlotAtom(jp, JS_TRUE, i);
#if JS_HAS_DESTRUCTURING
#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, JS_FALSE)
if (!param) {
ptrdiff_t todo;
const char *lval;
if (!param) {
ptrdiff_t todo;
const char *lval;
LOCAL_ASSERT(*pc == JSOP_GETARG);
pc += JSOP_GETARG_LENGTH;
LOCAL_ASSERT(*pc == JSOP_DUP);
if (!ss.printer) {
ok = InitSprintStack(jp->sprinter.context, &ss, jp,
fun->u.i.script->depth);
if (!ok)
break;
}
pc = DecompileDestructuring(&ss, pc, endpc);
if (!pc) {
ok = JS_FALSE;
LOCAL_ASSERT(*pc == JSOP_GETARG);
pc += JSOP_GETARG_LENGTH;
LOCAL_ASSERT(*pc == JSOP_DUP);
if (!ss.printer) {
ok = InitSprintStack(jp->sprinter.context, &ss, jp,
fun->script->depth);
if (!ok)
break;
}
LOCAL_ASSERT(*pc == JSOP_POP);
pc += JSOP_POP_LENGTH;
lval = PopStr(&ss, JSOP_NOP);
todo = SprintCString(&jp->sprinter, lval);
if (todo < 0) {
ok = JS_FALSE;
break;
}
continue;
}
pc = DecompileDestructuring(&ss, pc, endpc);
if (!pc) {
ok = JS_FALSE;
break;
}
LOCAL_ASSERT(*pc == JSOP_POP);
pc += JSOP_POP_LENGTH;
lval = PopStr(&ss, JSOP_NOP);
todo = SprintCString(&jp->sprinter, lval);
if (todo < 0) {
ok = JS_FALSE;
break;
}
continue;
}
#undef LOCAL_ASSERT
#endif
if (!QuoteString(&jp->sprinter, ATOM_TO_STRING(param), 0)) {
ok = JS_FALSE;
break;
}
if (!QuoteString(&jp->sprinter, ATOM_TO_STRING(param), 0)) {
ok = JS_FALSE;
break;
}
}
#ifdef JS_HAS_DESTRUCTURING
jp->script = NULL;
JS_ARENA_RELEASE(&jp->sprinter.context->tempPool, mark);
jp->script = NULL;
JS_ARENA_RELEASE(&jp->sprinter.context->tempPool, mark);
#endif
if (!ok)
return JS_FALSE;
if (fun->flags & JSFUN_EXPR_CLOSURE) {
js_printf(jp, ") ");
} else {
js_printf(jp, ") {\n");
jp->indent += 4;
}
if (!ok)
return JS_FALSE;
if (fun->flags & JSFUN_EXPR_CLOSURE) {
js_printf(jp, ") ");
} else {
js_printf(jp, ") {\n");
jp->indent += 4;
}
len = fun->u.i.script->code + fun->u.i.script->length - pc;
ok = DecompileCode(jp, fun->u.i.script, pc, (uintN)len, 0);
if (!ok)
return JS_FALSE;
len = fun->script->code + fun->script->length - pc;
ok = DecompileCode(jp, fun->script, pc, (uintN)len, 0);
if (!ok)
return JS_FALSE;
if (!(fun->flags & JSFUN_EXPR_CLOSURE)) {
jp->indent -= 4;
js_printf(jp, "\t}");
}
if (!(fun->flags & JSFUN_EXPR_CLOSURE)) {
jp->indent -= 4;
js_printf(jp, "\t}");
}
if (!jp->pretty && !jp->grouped && (fun->flags & JSFUN_LAMBDA))
@ -4861,7 +4881,9 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
goto do_fallback;
}
name = DecompileExpression(cx, script, fp->fun, pc);
name = DecompileExpression(cx, script,
fp->fun ? FUN_TO_SCRIPTED(fp->fun) : NULL,
pc);
if (name != FAILED_EXPRESSION_DECOMPILER)
return name;
@ -4876,7 +4898,7 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
}
static char *
DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
DecompileExpression(JSContext *cx, JSScript *script, JSScriptedFunction *fun,
jsbytecode *pc)
{
JSOp op;
@ -4957,13 +4979,16 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
}
name = NULL;
jp = JS_NEW_PRINTER(cx, "js_DecompileValueGenerator", fun, 0, JS_FALSE);
jp = JS_NEW_PRINTER(cx, "js_DecompileValueGenerator", 0, JS_FALSE);
if (jp) {
jp->dvgfence = end;
jp->pcstack = pcstack;
if (DecompileCode(jp, script, begin, (uintN) len, (uintN) pcdepth)) {
name = (jp->sprinter.base) ? jp->sprinter.base : (char *) "";
name = JS_strdup(cx, name);
if (!fun || InitFunctionPrinter(jp, fun)) {
jp->dvgfence = end;
jp->pcstack = pcstack;
if (DecompileCode(jp, script, begin, (uintN) len,
(uintN) pcdepth)) {
name = (jp->sprinter.base) ? jp->sprinter.base : (char *) "";
name = JS_strdup(cx, name);
}
}
js_DestroyPrinter(jp);
}

Просмотреть файл

@ -282,16 +282,15 @@ js_QuoteString(JSContext *cx, JSString *str, jschar quote);
*/
#ifdef JS_ARENAMETER
# define JS_NEW_PRINTER(cx, name, fun, indent, pretty) \
js_NewPrinter(cx, name, fun, indent, pretty)
# define JS_NEW_PRINTER(cx, name, indent, pretty) \
js_NewPrinter(cx, name, indent, pretty)
#else
# define JS_NEW_PRINTER(cx, name, fun, indent, pretty) \
js_NewPrinter(cx, fun, indent, pretty)
# define JS_NEW_PRINTER(cx, name, indent, pretty) \
js_NewPrinter(cx, indent, pretty)
#endif
extern JSPrinter *
JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
uintN indent, JSBool pretty);
JS_NEW_PRINTER(JSContext *cx, const char *name, uintN indent, JSBool pretty);
extern void
js_DestroyPrinter(JSPrinter *jp);
@ -361,14 +360,20 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
/*
* Decompilers, for script, function, and expression pretty-printing.
*/
extern JSBool
js_DecompileNativeFunctionBody(JSPrinter *jp, JSNativeFunction *fun);
JSBool
js_DecompileNativeFunction(JSPrinter *jp, JSNativeFunction *fun);
extern JSBool
js_DecompileScript(JSPrinter *jp, JSScript *script);
extern JSBool
js_DecompileFunctionBody(JSPrinter *jp);
js_DecompileFunctionBody(JSPrinter *jp, JSScriptedFunction *fun);
extern JSBool
js_DecompileFunction(JSPrinter *jp);
js_DecompileFunction(JSPrinter *jp, JSScriptedFunction *fun);
/*
* Find the source expression that resulted in v, and return a newly allocated

Просмотреть файл

@ -891,7 +891,8 @@ FunctionBody(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
* handler attribute in an HTML <INPUT> tag.
*/
JSBool
js_CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals,
js_CompileFunctionBody(JSContext *cx, JSScriptedFunction *fun,
JSPrincipals *principals,
const jschar *chars, size_t length,
const char *filename, uintN lineno)
{
@ -997,7 +998,7 @@ BindArg(JSContext *cx, JSAtom *atom, JSTreeContext *tc)
}
static JSBool
BindLocalVariable(JSContext *cx, JSFunction *fun, JSAtom *atom,
BindLocalVariable(JSContext *cx, JSScriptedFunction *fun, JSAtom *atom,
JSLocalKind localKind)
{
JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
@ -1055,17 +1056,16 @@ BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom,
}
#endif /* JS_HAS_DESTRUCTURING */
static JSFunction *
static JSScriptedFunction *
NewCompilerFunction(JSContext *cx, JSTreeContext *tc, JSAtom *atom,
uintN lambda)
{
JSObject *parent;
JSFunction *fun;
JSScriptedFunction *fun;
JS_ASSERT((lambda & ~JSFUN_LAMBDA) == 0);
parent = (tc->flags & TCF_IN_FUNCTION) ? tc->fun->object : cx->fp->varobj;
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED | lambda,
parent, atom);
fun = js_NewScriptedFunction(cx, NULL, lambda, parent, atom);
if (fun && !(tc->flags & TCF_COMPILE_N_GO)) {
STOBJ_SET_PARENT(fun->object, NULL);
STOBJ_SET_PROTO(fun->object, NULL);
@ -1083,7 +1083,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
JSAtom *funAtom;
JSParsedObjectBox *funpob;
JSAtomListElement *ale;
JSFunction *fun;
JSScriptedFunction *fun;
JSTreeContext funtc;
#if JS_HAS_DESTRUCTURING
JSParseNode *item, *list = NULL;
@ -4253,7 +4253,7 @@ GeneratorExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
uintN oldflags, JSParseNode *pn, JSParseNode *kid)
{
JSParseNode *body, *lambda;
JSFunction *fun;
JSScriptedFunction *fun;
/* Initialize pn, connecting it to kid. */
JS_ASSERT(pn->pn_arity == PN_UNARY);

Просмотреть файл

@ -464,7 +464,8 @@ js_CompileScript(JSContext *cx, JSObject *obj, JSPrincipals *principals,
FILE *file, const char *filename, uintN lineno);
extern JSBool
js_CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals,
js_CompileFunctionBody(JSContext *cx, JSScriptedFunction *fun,
JSPrincipals *principals,
const jschar *chars, size_t length,
const char *filename, uintN lineno);

Просмотреть файл

@ -92,10 +92,12 @@ typedef struct JSArgumentFormatMap JSArgumentFormatMap;
typedef struct JSCodeGenerator JSCodeGenerator;
typedef struct JSGCThing JSGCThing;
typedef struct JSGenerator JSGenerator;
typedef struct JSNativeFunction JSNativeFunction;
typedef struct JSParseContext JSParseContext;
typedef struct JSParsedObjectBox JSParsedObjectBox;
typedef struct JSParseNode JSParseNode;
typedef struct JSPropCacheEntry JSPropCacheEntry;
typedef struct JSScriptedFunction JSScriptedFunction;
typedef struct JSSharpObjectMap JSSharpObjectMap;
typedef struct JSTempValueRooter JSTempValueRooter;
typedef struct JSThread JSThread;
@ -237,7 +239,7 @@ typedef union JSTempValueUnion {
jsval value;
JSObject *object;
JSString *string;
JSFunction *function;
JSScriptedFunction *function;
JSXML *xml;
JSXMLQName *qname;
JSTempValueTrace trace;

Просмотреть файл

@ -3868,7 +3868,7 @@ regexp_xdrObject(JSXDRState *xdr, JSObject **objp)
return JS_FALSE;
}
if (xdr->mode == JSXDR_DECODE) {
obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL);
obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
STOBJ_SET_PARENT(obj, NULL);
@ -4236,7 +4236,7 @@ RegExp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
/* Otherwise, replace obj with a new RegExp object. */
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
@ -4296,7 +4296,7 @@ js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
if (!re)
return NULL;
JS_PUSH_TEMP_ROOT_STRING(cx, str, &tvr);
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, re)) {
js_DestroyRegExp(cx, re);
obj = NULL;
@ -4314,7 +4314,7 @@ js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent)
JSRegExp *re;
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
clone = js_NewObject(cx, &js_RegExpClass, NULL, parent);
clone = js_NewObject(cx, &js_RegExpClass, NULL, parent, 0);
if (!clone)
return NULL;
re = (JSRegExp *) JS_GetPrivate(cx, obj);

Просмотреть файл

@ -880,7 +880,7 @@ Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
/* If not constructing, replace obj with a new Script object. */
if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
@ -904,7 +904,7 @@ script_static_thaw(JSContext *cx, uintN argc, jsval *vp)
{
JSObject *obj;
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
vp[1] = OBJECT_TO_JSVAL(obj);
@ -1407,7 +1407,7 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
uint32 mainLength, prologLength, nsrcnotes;
JSScript *script;
const char *filename;
JSFunction *fun;
JSScriptedFunction *fun;
/* The counts of indexed things must be checked during code generation. */
JS_ASSERT(cg->atomList.count <= INDEX_LIMIT);
@ -1452,16 +1452,13 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
if (cg->regexpList.length != 0)
FinishParsedObjects(&cg->regexpList, JS_SCRIPT_REGEXPS(script));
/*
* We initialize fun->u.script to be the script constructed above
* so that the debugger has a valid FUN_SCRIPT(fun).
*/
/* Initialize fun->script early for the debugger. */
fun = NULL;
if (cg->treeContext.flags & TCF_IN_FUNCTION) {
fun = cg->treeContext.fun;
JS_ASSERT(FUN_INTERPRETED(fun) && !FUN_SCRIPT(fun));
JS_ASSERT(!fun->script);
js_FreezeLocalNames(cx, fun);
fun->u.i.script = script;
fun->script = script;
#ifdef CHECK_SCRIPT_OWNER
script->owner = NULL;
#endif
@ -1485,21 +1482,22 @@ bad:
return NULL;
}
JS_FRIEND_API(void)
js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun)
void
js_CallNewScriptHook(JSContext *cx, JSScript *script, JSScriptedFunction *fun)
{
JSNewScriptHook hook;
hook = cx->debugHooks->newScriptHook;
if (hook) {
JS_KEEP_ATOMS(cx->runtime);
hook(cx, script->filename, script->lineno, script, fun,
hook(cx, script->filename, script->lineno, script,
fun ? SCRIPTED_TO_FUN(fun) : NULL,
cx->debugHooks->newScriptHookData);
JS_UNKEEP_ATOMS(cx->runtime);
}
}
JS_FRIEND_API(void)
void
js_CallDestroyScriptHook(JSContext *cx, JSScript *script)
{
JSDestroyScriptHook hook;
@ -1679,7 +1677,7 @@ uintN
js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
{
JSObject *obj;
JSFunction *fun;
JSScriptedFunction *fun;
uintN lineno;
ptrdiff_t offset, target;
jssrcnote *sn;
@ -1697,9 +1695,8 @@ js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
pc += js_CodeSpec[*pc].length;
if (*pc == JSOP_DEFFUN) {
GET_FUNCTION_FROM_BYTECODE(script, pc, 0, obj);
fun = GET_FUNCTION_PRIVATE(cx, obj);
JS_ASSERT(FUN_INTERPRETED(fun));
return fun->u.i.script->lineno;
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
return fun->script->lineno;
}
/*

Просмотреть файл

@ -227,10 +227,10 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg);
* of js_XDRScript, the hook should be invoked only after successful decode
* of any owning function (the fun parameter) or script object (null fun).
*/
extern JS_FRIEND_API(void)
js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun);
extern void
js_CallNewScriptHook(JSContext *cx, JSScript *script, JSScriptedFunction *fun);
extern JS_FRIEND_API(void)
extern void
js_CallDestroyScriptHook(JSContext *cx, JSScript *script);
extern void

Просмотреть файл

@ -331,7 +331,7 @@ js_GetXMLNamespaceObject(JSContext *cx, JSXMLNamespace *ns)
JS_ASSERT(JS_GetPrivate(cx, obj) == ns);
return obj;
}
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, ns)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -607,7 +607,7 @@ js_GetXMLQNameObject(JSContext *cx, JSXMLQName *qn)
JS_ASSERT(JS_GetPrivate(cx, obj) == qn);
return obj;
}
obj = js_NewObject(cx, &js_QNameClass.base, NULL, NULL);
obj = js_NewObject(cx, &js_QNameClass.base, NULL, NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -632,7 +632,7 @@ js_GetAttributeNameObject(JSContext *cx, JSXMLQName *qn)
return NULL;
}
obj = js_NewObject(cx, &js_AttributeNameClass, NULL, NULL);
obj = js_NewObject(cx, &js_AttributeNameClass, NULL, NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -748,7 +748,7 @@ Namespace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
/* Create and return a new QName object exactly as if constructed. */
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -830,6 +830,7 @@ QName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsval nameval, nsval;
JSBool isQName, isNamespace;
JSFunction *fun;
JSXMLQName *qn;
JSString *uri, *prefix, *name;
JSObject *nsobj;
@ -854,9 +855,8 @@ QName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
* Use the constructor's clasp so we can be shared by AttributeName
* (see below after this function).
*/
obj = js_NewObject(cx,
JS_ValueToFunction(cx, argv[-2])->u.n.clasp,
NULL, NULL);
fun = JS_ValueToFunction(cx, argv[-2]);
obj = js_NewObject(cx, FUN_TO_NATIVE(fun)->clasp, NULL, NULL, 0);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
@ -7584,7 +7584,7 @@ NewXMLObject(JSContext *cx, JSXML *xml)
{
JSObject *obj;
obj = js_NewObject(cx, &js_XMLClass, NULL, NULL);
obj = js_NewObject(cx, &js_XMLClass, NULL, NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, xml)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
return NULL;
@ -7713,7 +7713,7 @@ js_InitXMLClass(JSContext *cx, JSObject *obj)
fun = JS_DefineFunction(cx, obj, js_XMLList_str, XMLList, 1, 0);
if (!fun)
return NULL;
if (!js_SetClassPrototype(cx, fun->object, proto,
if (!js_SetClassPrototype(cx, &FUN_TO_NATIVE(fun)->object, proto,
JSPROP_READONLY | JSPROP_PERMANENT)) {
return NULL;
}
@ -7877,7 +7877,7 @@ js_SetDefaultXMLNamespace(JSContext *cx, jsval v)
return JS_FALSE;
}
} else {
JS_ASSERT(fp->fun && !JSFUN_HEAVYWEIGHT_TEST(fp->fun->flags));
JS_ASSERT(fp->fun && !JSFUN_HEAVYWEIGHT_TEST(FUN_FLAGS(fp->fun)));
}
fp->xmlNamespace = JSVAL_TO_OBJECT(v);
return JS_TRUE;
@ -7997,7 +7997,8 @@ js_GetAnyName(JSContext *cx, jsval *vp)
break;
}
obj = js_NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL, NULL);
obj = js_NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL,
NULL, 0);
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
ok = JS_FALSE;
@ -8311,7 +8312,7 @@ js_StepXMLListFilter(JSContext *cx, JSBool initialized)
return JS_FALSE;
}
filterobj = js_NewObject(cx, &js_XMLFilterClass, NULL, NULL);
filterobj = js_NewObject(cx, &js_XMLFilterClass, NULL, NULL, 0);
if (!filterobj)
return JS_FALSE;

Просмотреть файл

@ -53,10 +53,10 @@
#include "jsj_private.h"
#include "jsjava.h"
#include "jsdbgapi.h"
#include "jsarena.h"
#include "jsfun.h"
#include "jscntxt.h" /* For js_ReportErrorAgain().*/
#include "jsdbgapi.h"
#include "jsfun.h"
#include "jsscript.h"
#include "netscape_javascript_JSObject.h" /* javah-generated headers */

Просмотреть файл

@ -533,12 +533,12 @@ nsXPConnect::Collect()
return gCollected;
}
// JSTRACE_FUNCTION can hold on to a lot of objects, adding it to the cycle
// collector reduces the number of edges to those objects.
// JSTRACE_SCRIPTED_FUNCTION can hold on to a lot of objects, adding it to the
// cycle collector reduces the number of edges to those objects.
// JSTRACE_XML can recursively hold on to more JSTRACE_XML objects, adding it to
// the cycle collector avoids stack overflow.
#define ADD_TO_CC(_kind) \
((_kind) == JSTRACE_OBJECT || (_kind) == JSTRACE_FUNCTION || \
((_kind) == JSTRACE_OBJECT || (_kind) == JSTRACE_SCRIPTED_FUNCTION || \
(_kind) == JSTRACE_XML)
#ifdef DEBUG_CC