зеркало из https://github.com/mozilla/gecko-dev.git
bugs 31003 and (mostly) 68045, r=rogerl, sr=shaver&hyatt
- Fix bug where script jssrcnote vector terminator was not XDRed. - Ensure that memory is cleared by serializing zero padding bytes as needed under JS_XDRBytes and JS_XDRString. - Fix JS_XDRValue to handle undefined and null JS types properly (bug 31003). Also make it cast from jsint to uint32 and back carefully, so as to work with negative numbers even on targets where jsval is a signed 64 bit type. - Add JS_XDRScript public API. - Optimize the per-JSXDRState class registry so it uses a JSDHashTable upon searching for a class-id by name in an overpopulated (for linear search) registry table. - Clean up API nits such as JS_XDRNewBase => JS_XDRInitBase, with parameter list rotation to put cx last (JS_XDRInitBase is an infallible init helper, not an error-reporting, cx-comes-first, API entry point). - Fix some XXX comments, unneeded masks, other nits. - Make sure all JS XDR API functions start with JS_XDR.
This commit is contained in:
Родитель
5496fd604a
Коммит
69ab37f337
|
@ -3096,9 +3096,9 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
clasp = OBJ_GET_CLASS(cx, *objp);
|
clasp = OBJ_GET_CLASS(cx, *objp);
|
||||||
className = clasp->name;
|
className = clasp->name;
|
||||||
classId = JS_FindClassIdByName(xdr, className);
|
classId = JS_XDRFindClassIdByName(xdr, className);
|
||||||
classDef = !classId;
|
classDef = !classId;
|
||||||
if (classDef && !JS_RegisterClass(xdr, clasp, &classId))
|
if (classDef && !JS_XDRRegisterClass(xdr, clasp, &classId))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
} else {
|
} else {
|
||||||
classDef = 0;
|
classDef = 0;
|
||||||
|
@ -3123,11 +3123,11 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
|
||||||
if (!ok)
|
if (!ok)
|
||||||
goto out;
|
goto out;
|
||||||
clasp = OBJ_GET_CLASS(cx, proto);
|
clasp = OBJ_GET_CLASS(cx, proto);
|
||||||
ok = JS_RegisterClass(xdr, clasp, &classId);
|
ok = JS_XDRRegisterClass(xdr, clasp, &classId);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
clasp = JS_FindClassById(xdr, classId);
|
clasp = JS_XDRFindClassById(xdr, classId);
|
||||||
if (!clasp) {
|
if (!clasp) {
|
||||||
char numBuf[12];
|
char numBuf[12];
|
||||||
JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)classId);
|
JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)classId);
|
||||||
|
@ -3312,4 +3312,3 @@ void printAtom(JSAtom *atom) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,7 @@ script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
|
||||||
#if JS_HAS_XDR
|
#if JS_HAS_XDR
|
||||||
static JSBool
|
static JSBool
|
||||||
XDRAtom1(JSXDRState *xdr, JSAtomListElement *ale)
|
XDRAtomListElement(JSXDRState *xdr, JSAtomListElement *ale)
|
||||||
{
|
{
|
||||||
jsval value;
|
jsval value;
|
||||||
jsatomid index;
|
jsatomid index;
|
||||||
|
@ -295,7 +295,7 @@ XDRAtomMap(JSXDRState *xdr, JSAtomMap *map)
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &cx->tempPool);
|
JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &cx->tempPool);
|
||||||
if (!ale ||
|
if (!ale ||
|
||||||
!XDRAtom1(xdr, ale)) {
|
!XDRAtomListElement(xdr, ale)) {
|
||||||
if (!ale)
|
if (!ale)
|
||||||
JS_ReportOutOfMemory(cx);
|
JS_ReportOutOfMemory(cx);
|
||||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||||
|
@ -316,7 +316,7 @@ XDRAtomMap(JSXDRState *xdr, JSAtomMap *map)
|
||||||
for (i = 0; i < map->length; i++) {
|
for (i = 0; i < map->length; i++) {
|
||||||
ALE_SET_ATOM(&ale, map->vector[i]);
|
ALE_SET_ATOM(&ale, map->vector[i]);
|
||||||
ALE_SET_INDEX(&ale, i);
|
ALE_SET_INDEX(&ale, i);
|
||||||
if (!XDRAtom1(xdr, &ale))
|
if (!XDRAtomListElement(xdr, &ale))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,7 +348,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
|
||||||
*hasMagic = JS_TRUE;
|
*hasMagic = JS_TRUE;
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
jssrcnote *end = script->notes;
|
jssrcnote *sn = script->notes;
|
||||||
length = script->length;
|
length = script->length;
|
||||||
prologLength = script->main - script->code;
|
prologLength = script->main - script->code;
|
||||||
version = (int32) script->version;
|
version = (int32) script->version;
|
||||||
|
@ -363,9 +363,10 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Count the src notes. */
|
/* Count the src notes. */
|
||||||
while (!SN_IS_TERMINATOR(end))
|
while (!SN_IS_TERMINATOR(sn))
|
||||||
end = SN_NEXT(end);
|
sn = SN_NEXT(sn);
|
||||||
notelen = end - script->notes;
|
notelen = sn - script->notes;
|
||||||
|
notelen++; /* room for the terminator */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JS_XDRUint32(xdr, &length))
|
if (!JS_XDRUint32(xdr, &length))
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "jstypes.h"
|
#include "jstypes.h"
|
||||||
#include "jsutil.h" /* Added by JSIFY */
|
#include "jsutil.h" /* Added by JSIFY */
|
||||||
|
#include "jsdhash.h"
|
||||||
#include "jsprf.h"
|
#include "jsprf.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jscntxt.h"
|
#include "jscntxt.h"
|
||||||
|
@ -72,27 +73,20 @@ typedef struct JSXDRMemState {
|
||||||
} \
|
} \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
|
||||||
/* XXXbe why does NEED even allow or cope with non-ENCODE mode? */
|
|
||||||
#define MEM_NEED(xdr, bytes) \
|
#define MEM_NEED(xdr, bytes) \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
if ((xdr)->mode == JSXDR_ENCODE) { \
|
if ((xdr)->mode == JSXDR_ENCODE) { \
|
||||||
uint32 _new_limit = JS_ROUNDUP(MEM_COUNT(xdr) + bytes, MEM_BLOCK);\
|
uint32 new_limit_ = JS_ROUNDUP(MEM_COUNT(xdr) + bytes, MEM_BLOCK);\
|
||||||
if (MEM_LIMIT(xdr) && \
|
if (MEM_LIMIT(xdr) && \
|
||||||
MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
|
MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
|
||||||
void *_data = JS_realloc((xdr)->cx, \
|
void *data_ = JS_realloc((xdr)->cx, (xdr)->data, new_limit_); \
|
||||||
(xdr)->data, \
|
if (!data_) \
|
||||||
_new_limit); \
|
|
||||||
if (!_data) \
|
|
||||||
return 0; \
|
return 0; \
|
||||||
(xdr)->data = _data; \
|
(xdr)->data = data_; \
|
||||||
MEM_LIMIT(xdr) = _new_limit; \
|
MEM_LIMIT(xdr) = new_limit_; \
|
||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
if (MEM_LIMIT(xdr) < MEM_COUNT(xdr) + bytes) { \
|
MEM_LEFT(xdr, bytes); \
|
||||||
JS_ReportErrorNumber((xdr)->cx, js_GetErrorMessage, NULL, \
|
|
||||||
JSMSG_END_OF_DATA); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
} \
|
} \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
|
||||||
|
@ -211,8 +205,7 @@ mem_tell(JSXDRState *xdr)
|
||||||
static void
|
static void
|
||||||
mem_finalize(JSXDRState *xdr)
|
mem_finalize(JSXDRState *xdr)
|
||||||
{
|
{
|
||||||
JSContext *cx = xdr->cx;
|
JS_free(xdr->cx, xdr->data);
|
||||||
JS_free(cx, xdr->data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSXDROps xdrmem_ops = {
|
static JSXDROps xdrmem_ops = {
|
||||||
|
@ -221,12 +214,13 @@ static JSXDROps xdrmem_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
JS_PUBLIC_API(void)
|
||||||
JS_XDRNewBase(JSContext *cx, JSXDRState *xdr, JSXDRMode mode)
|
JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx)
|
||||||
{
|
{
|
||||||
xdr->cx = cx;
|
|
||||||
xdr->mode = mode;
|
xdr->mode = mode;
|
||||||
|
xdr->cx = cx;
|
||||||
xdr->registry = NULL;
|
xdr->registry = NULL;
|
||||||
xdr->nclasses = 0;
|
xdr->numclasses = xdr->maxclasses = 0;
|
||||||
|
xdr->reghash = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSXDRState *)
|
JS_PUBLIC_API(JSXDRState *)
|
||||||
|
@ -235,7 +229,7 @@ JS_XDRNewMem(JSContext *cx, JSXDRMode mode)
|
||||||
JSXDRState *xdr = (JSXDRState *) JS_malloc(cx, sizeof(JSXDRMemState));
|
JSXDRState *xdr = (JSXDRState *) JS_malloc(cx, sizeof(JSXDRMemState));
|
||||||
if (!xdr)
|
if (!xdr)
|
||||||
return NULL;
|
return NULL;
|
||||||
JS_XDRNewBase(cx, xdr, mode);
|
JS_XDRInitBase(xdr, mode, cx);
|
||||||
if (mode == JSXDR_ENCODE) {
|
if (mode == JSXDR_ENCODE) {
|
||||||
if (!(xdr->data = JS_malloc(cx, MEM_BLOCK))) {
|
if (!(xdr->data = JS_malloc(cx, MEM_BLOCK))) {
|
||||||
JS_free(cx, xdr);
|
JS_free(cx, xdr);
|
||||||
|
@ -270,13 +264,26 @@ JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32 len)
|
||||||
MEM_PRIV(xdr)->count = 0;
|
MEM_PRIV(xdr)->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(void)
|
||||||
|
JS_XDRDestroy(JSXDRState *xdr)
|
||||||
|
{
|
||||||
|
JSContext *cx = xdr->cx;
|
||||||
|
xdr->ops->finalize(xdr);
|
||||||
|
if (xdr->registry) {
|
||||||
|
JS_free(cx, xdr->registry);
|
||||||
|
if (xdr->reghash)
|
||||||
|
JS_DHashTableDestroy(xdr->reghash);
|
||||||
|
}
|
||||||
|
JS_free(cx, xdr);
|
||||||
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_XDRUint8(JSXDRState *xdr, uint8 *b)
|
JS_XDRUint8(JSXDRState *xdr, uint8 *b)
|
||||||
{
|
{
|
||||||
uint32 l = *b;
|
uint32 l = *b;
|
||||||
if (!JS_XDRUint32(xdr, &l))
|
if (!JS_XDRUint32(xdr, &l))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
*b = (uint8) l & 0xff;
|
*b = (uint8) l;
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,14 +293,14 @@ JS_XDRUint16(JSXDRState *xdr, uint16 *s)
|
||||||
uint32 l = *s;
|
uint32 l = *s;
|
||||||
if (!JS_XDRUint32(xdr, &l))
|
if (!JS_XDRUint32(xdr, &l))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
*s = (uint16) l & 0xffff;
|
*s = (uint16) l;
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_XDRUint32(JSXDRState *xdr, uint32 *lp)
|
JS_XDRUint32(JSXDRState *xdr, uint32 *lp)
|
||||||
{
|
{
|
||||||
JSBool ok = JS_FALSE;
|
JSBool ok = JS_TRUE;
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
uint32 xl = JSXDR_SWAB32(*lp);
|
uint32 xl = JSXDR_SWAB32(*lp);
|
||||||
ok = xdr->ops->set32(xdr, &xl);
|
ok = xdr->ops->set32(xdr, &xl);
|
||||||
|
@ -307,6 +314,10 @@ JS_XDRUint32(JSXDRState *xdr, uint32 *lp)
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_XDRBytes(JSXDRState *xdr, char **bytesp, uint32 len)
|
JS_XDRBytes(JSXDRState *xdr, char **bytesp, uint32 len)
|
||||||
{
|
{
|
||||||
|
uint32 padlen;
|
||||||
|
char *padbp;
|
||||||
|
static char padbuf[JSXDR_ALIGN-1];
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
if (!xdr->ops->setbytes(xdr, bytesp, len))
|
if (!xdr->ops->setbytes(xdr, bytesp, len))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
@ -316,8 +327,13 @@ JS_XDRBytes(JSXDRState *xdr, char **bytesp, uint32 len)
|
||||||
}
|
}
|
||||||
len = xdr->ops->tell(xdr);
|
len = xdr->ops->tell(xdr);
|
||||||
if (len % JSXDR_ALIGN) {
|
if (len % JSXDR_ALIGN) {
|
||||||
if (!xdr->ops->seek(xdr, JSXDR_ALIGN - (len % JSXDR_ALIGN),
|
padlen = JSXDR_ALIGN - (len % JSXDR_ALIGN);
|
||||||
JSXDR_SEEK_CUR)) {
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
|
padbp = padbuf;
|
||||||
|
if (!xdr->ops->setbytes(xdr, &padbp, padlen))
|
||||||
|
return JS_FALSE;
|
||||||
|
} else {
|
||||||
|
if (!xdr->ops->seek(xdr, padlen, JSXDR_SEEK_CUR))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,7 +390,7 @@ JS_XDRCStringOrNull(JSXDRState *xdr, char **sp)
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_XDRString(JSXDRState *xdr, JSString **strp)
|
JS_XDRString(JSXDRState *xdr, JSString **strp)
|
||||||
{
|
{
|
||||||
uint32 i, len, nbytes;
|
uint32 i, len, padlen, nbytes;
|
||||||
jschar *chars = NULL, *raw;
|
jschar *chars = NULL, *raw;
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
if (xdr->mode == JSXDR_ENCODE)
|
||||||
|
@ -383,20 +399,25 @@ JS_XDRString(JSXDRState *xdr, JSString **strp)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
nbytes = len * sizeof(jschar);
|
nbytes = len * sizeof(jschar);
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (xdr->mode == JSXDR_DECODE) {
|
||||||
chars = (*strp)->chars;
|
|
||||||
} else if (xdr->mode == JSXDR_DECODE) {
|
|
||||||
if (!(chars = (jschar *) JS_malloc(xdr->cx, nbytes + sizeof(jschar))))
|
if (!(chars = (jschar *) JS_malloc(xdr->cx, nbytes + sizeof(jschar))))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
} else {
|
||||||
|
chars = (*strp)->chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes % JSXDR_ALIGN)
|
padlen = nbytes % JSXDR_ALIGN;
|
||||||
nbytes += JSXDR_ALIGN - (nbytes % JSXDR_ALIGN);
|
if (padlen) {
|
||||||
|
padlen = JSXDR_ALIGN - padlen;
|
||||||
|
nbytes += padlen;
|
||||||
|
}
|
||||||
if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes)))
|
if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes)))
|
||||||
goto bad;
|
goto bad;
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
raw[i] = JSXDR_SWAB16(chars[i]);
|
raw[i] = JSXDR_SWAB16(chars[i]);
|
||||||
|
if (padlen)
|
||||||
|
memset((char *)raw + nbytes - padlen, 0, padlen);
|
||||||
} else if (xdr->mode == JSXDR_DECODE) {
|
} else if (xdr->mode == JSXDR_DECODE) {
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
chars[i] = JSXDR_SWAB16(raw[i]);
|
chars[i] = JSXDR_SWAB16(raw[i]);
|
||||||
|
@ -435,10 +456,10 @@ JS_XDRDouble(JSXDRState *xdr, jsdouble **dp)
|
||||||
#if IS_BIG_ENDIAN
|
#if IS_BIG_ENDIAN
|
||||||
if (!JS_XDRUint32(xdr, (uint32 *)&d + 1) ||
|
if (!JS_XDRUint32(xdr, (uint32 *)&d + 1) ||
|
||||||
!JS_XDRUint32(xdr, (uint32 *)&d))
|
!JS_XDRUint32(xdr, (uint32 *)&d))
|
||||||
#else /* !IS_BIG_ENDIAN */
|
#else
|
||||||
if (!JS_XDRUint32(xdr, (uint32 *)&d) ||
|
if (!JS_XDRUint32(xdr, (uint32 *)&d) ||
|
||||||
!JS_XDRUint32(xdr, (uint32 *)&d + 1))
|
!JS_XDRUint32(xdr, (uint32 *)&d + 1))
|
||||||
#endif /* IS_BIG_ENDIAN */
|
#endif
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (xdr->mode == JSXDR_DECODE) {
|
||||||
*dp = JS_NewDouble(xdr->cx, d);
|
*dp = JS_NewDouble(xdr->cx, d);
|
||||||
|
@ -448,14 +469,33 @@ JS_XDRDouble(JSXDRState *xdr, jsdouble **dp)
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* These are magic: see jsapi.h, near the top, for the real jsval tags. */
|
||||||
|
#define JSVAL_XDRNULL 0x8
|
||||||
|
#define JSVAL_XDRVOID 0xA
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_XDRValue(JSXDRState *xdr, jsval *vp)
|
JS_XDRValue(JSXDRState *xdr, jsval *vp)
|
||||||
{
|
{
|
||||||
uint32 type = JSVAL_TAG(*vp);
|
uint32 type;
|
||||||
|
|
||||||
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
|
if (JSVAL_IS_NULL(*vp))
|
||||||
|
type = JSVAL_XDRNULL;
|
||||||
|
else if (JSVAL_IS_VOID(*vp))
|
||||||
|
type = JSVAL_XDRVOID;
|
||||||
|
else
|
||||||
|
type = JSVAL_TAG(*vp);
|
||||||
|
}
|
||||||
if (!JS_XDRUint32(xdr, &type))
|
if (!JS_XDRUint32(xdr, &type))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case JSVAL_XDRNULL:
|
||||||
|
*vp = JSVAL_NULL;
|
||||||
|
break;
|
||||||
|
case JSVAL_XDRVOID:
|
||||||
|
*vp = JSVAL_VOID;
|
||||||
|
break;
|
||||||
case JSVAL_STRING: {
|
case JSVAL_STRING: {
|
||||||
JSString *str = JSVAL_TO_STRING(*vp);
|
JSString *str = JSVAL_TO_STRING(*vp);
|
||||||
if (!JS_XDRString(xdr, &str))
|
if (!JS_XDRString(xdr, &str))
|
||||||
|
@ -494,20 +534,16 @@ JS_XDRValue(JSXDRState *xdr, jsval *vp)
|
||||||
*vp = BOOLEAN_TO_JSVAL((JSBool)b);
|
*vp = BOOLEAN_TO_JSVAL((JSBool)b);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JSVAL_VOID:
|
|
||||||
if (!JS_XDRUint32(xdr, (uint32 *)vp))
|
|
||||||
return JS_FALSE;
|
|
||||||
break;
|
|
||||||
default: {
|
default: {
|
||||||
char numBuf[12];
|
char numBuf[12];
|
||||||
if (type & JSVAL_INT) {
|
if (type & JSVAL_INT) {
|
||||||
uint32 i;
|
uint32 i;
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
if (xdr->mode == JSXDR_ENCODE)
|
||||||
i = JSVAL_TO_INT(*vp);
|
i = (uint32) JSVAL_TO_INT(*vp);
|
||||||
if (!JS_XDRUint32(xdr, &i))
|
if (!JS_XDRUint32(xdr, &i))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
if (xdr->mode == JSXDR_DECODE)
|
||||||
*vp = INT_TO_JSVAL(i);
|
*vp = INT_TO_JSVAL((int32) i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
JS_snprintf(numBuf, sizeof numBuf, "%#lx", type);
|
JS_snprintf(numBuf, sizeof numBuf, "%#lx", type);
|
||||||
|
@ -519,62 +555,110 @@ JS_XDRValue(JSXDRState *xdr, jsval *vp)
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_PUBLIC_API(void)
|
JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
||||||
JS_XDRDestroy(JSXDRState *xdr)
|
|
||||||
{
|
{
|
||||||
JSContext *cx = xdr->cx;
|
JSBool hasMagic;
|
||||||
xdr->ops->finalize(xdr);
|
|
||||||
if (xdr->registry)
|
return js_XDRScript(xdr, scriptp, &hasMagic);
|
||||||
JS_free(cx, xdr->registry);
|
|
||||||
JS_free(cx, xdr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define REGISTRY_CHUNK 4
|
#define CLASS_REGISTRY_MIN 8
|
||||||
|
#define CLASS_INDEX_TO_ID(i) ((i)+1)
|
||||||
|
#define CLASS_ID_TO_INDEX(id) ((id)-1)
|
||||||
|
|
||||||
|
typedef struct JSRegHashEntry {
|
||||||
|
JSDHashEntryHdr hdr;
|
||||||
|
const char *name;
|
||||||
|
uint32 index;
|
||||||
|
} JSRegHashEntry;
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_RegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *idp)
|
JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *idp)
|
||||||
{
|
{
|
||||||
uintN nclasses;
|
uintN numclasses, maxclasses;
|
||||||
JSClass **registry;
|
JSClass **registry;
|
||||||
|
|
||||||
nclasses = xdr->nclasses;
|
numclasses = xdr->numclasses;
|
||||||
if (nclasses == 0) {
|
maxclasses = xdr->maxclasses;
|
||||||
|
if (numclasses == maxclasses) {
|
||||||
|
maxclasses = (maxclasses == 0) ? CLASS_REGISTRY_MIN : maxclasses << 1;
|
||||||
registry = (JSClass **)
|
registry = (JSClass **)
|
||||||
JS_malloc(xdr->cx, REGISTRY_CHUNK * sizeof(JSClass *));
|
JS_realloc(xdr->cx, xdr->registry, maxclasses * sizeof(JSClass *));
|
||||||
} else if (nclasses % REGISTRY_CHUNK == 0) {
|
|
||||||
registry = (JSClass **)
|
|
||||||
JS_realloc(xdr->cx,
|
|
||||||
xdr->registry,
|
|
||||||
(nclasses + REGISTRY_CHUNK) * sizeof(JSClass *));
|
|
||||||
} else {
|
|
||||||
registry = xdr->registry;
|
|
||||||
}
|
|
||||||
if (!registry)
|
if (!registry)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
registry[nclasses++] = clasp;
|
|
||||||
xdr->registry = registry;
|
xdr->registry = registry;
|
||||||
xdr->nclasses = nclasses;
|
xdr->maxclasses = maxclasses;
|
||||||
*idp = nclasses;
|
} else {
|
||||||
|
JS_ASSERT(numclasses && numclasses < maxclasses);
|
||||||
|
registry = xdr->registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
registry[numclasses] = clasp;
|
||||||
|
if (xdr->reghash) {
|
||||||
|
JSRegHashEntry *entry = (JSRegHashEntry *)
|
||||||
|
JS_DHashTableOperate(xdr->reghash, clasp->name, JS_DHASH_ADD);
|
||||||
|
if (!entry) {
|
||||||
|
JS_ReportOutOfMemory(xdr->cx);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
entry->name = clasp->name;
|
||||||
|
entry->index = numclasses;
|
||||||
|
}
|
||||||
|
*idp = CLASS_INDEX_TO_ID(numclasses);
|
||||||
|
xdr->numclasses = ++numclasses;
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(uint32)
|
JS_PUBLIC_API(uint32)
|
||||||
JS_FindClassIdByName(JSXDRState *xdr, const char *name)
|
JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name)
|
||||||
{
|
{
|
||||||
uintN i;
|
uintN i, numclasses;
|
||||||
|
|
||||||
for (i = 0; i < xdr->nclasses; i++) {
|
numclasses = xdr->numclasses;
|
||||||
|
if (numclasses >= 10) {
|
||||||
|
JSRegHashEntry *entry;
|
||||||
|
|
||||||
|
/* Bootstrap reghash from registry on first overpopulated Find. */
|
||||||
|
if (!xdr->reghash) {
|
||||||
|
xdr->reghash = JS_NewDHashTable(JS_DHashGetStubOps(), NULL,
|
||||||
|
sizeof(JSRegHashEntry),
|
||||||
|
numclasses);
|
||||||
|
if (xdr->reghash) {
|
||||||
|
for (i = 0; i < numclasses; i++) {
|
||||||
|
JSClass *clasp = xdr->registry[i];
|
||||||
|
entry = (JSRegHashEntry *)
|
||||||
|
JS_DHashTableOperate(xdr->reghash, clasp->name,
|
||||||
|
JS_DHASH_ADD);
|
||||||
|
entry->name = clasp->name;
|
||||||
|
entry->index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we managed to create reghash, use it for O(1) Find. */
|
||||||
|
if (xdr->reghash) {
|
||||||
|
entry = (JSRegHashEntry *)
|
||||||
|
JS_DHashTableOperate(xdr->reghash, name, JS_DHASH_LOOKUP);
|
||||||
|
if (JS_DHASH_ENTRY_IS_BUSY(&entry->hdr))
|
||||||
|
return CLASS_INDEX_TO_ID(entry->index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only a few classes, or we couldn't malloc reghash: use linear search. */
|
||||||
|
for (i = 0; i < numclasses; i++) {
|
||||||
if (!strcmp(name, xdr->registry[i]->name))
|
if (!strcmp(name, xdr->registry[i]->name))
|
||||||
return i+1;
|
return CLASS_INDEX_TO_ID(i);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSClass *)
|
JS_PUBLIC_API(JSClass *)
|
||||||
JS_FindClassById(JSXDRState *xdr, uint32 id)
|
JS_XDRFindClassById(JSXDRState *xdr, uint32 id)
|
||||||
{
|
{
|
||||||
if (id > xdr->nclasses)
|
uintN i = CLASS_ID_TO_INDEX(id);
|
||||||
|
|
||||||
|
if (i >= xdr->numclasses)
|
||||||
return NULL;
|
return NULL;
|
||||||
return xdr->registry[id-1];
|
return xdr->registry[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,11 +66,11 @@ JS_BEGIN_EXTERN_C
|
||||||
#define JSXDR_SWAB32(x) x
|
#define JSXDR_SWAB32(x) x
|
||||||
#define JSXDR_SWAB16(x) x
|
#define JSXDR_SWAB16(x) x
|
||||||
#elif defined IS_BIG_ENDIAN
|
#elif defined IS_BIG_ENDIAN
|
||||||
#define JSXDR_SWAB32(x) (((x) >> 24) | \
|
#define JSXDR_SWAB32(x) (((uint32)(x) >> 24) | \
|
||||||
(((x) >> 8) & 0xff00) | \
|
(((uint32)(x) >> 8) & 0xff00) | \
|
||||||
(((x) << 8) & 0xff0000) | \
|
(((uint32)(x) << 8) & 0xff0000) | \
|
||||||
((x) << 24))
|
((uint32)(x) << 24))
|
||||||
#define JSXDR_SWAB16(x) (((x) >> 8) | ((x) << 8))
|
#define JSXDR_SWAB16(x) (((uint16)(x) >> 8) | ((uint16)(x) << 8))
|
||||||
#else
|
#else
|
||||||
#error "unknown byte order"
|
#error "unknown byte order"
|
||||||
#endif
|
#endif
|
||||||
|
@ -105,12 +105,14 @@ struct JSXDRState {
|
||||||
JSXDROps *ops;
|
JSXDROps *ops;
|
||||||
JSContext *cx;
|
JSContext *cx;
|
||||||
JSClass **registry;
|
JSClass **registry;
|
||||||
uintN nclasses;
|
uintN numclasses;
|
||||||
|
uintN maxclasses;
|
||||||
|
void *reghash;
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
JS_XDRNewBase(JSContext *cx, JSXDRState *xdr, JSXDRMode mode);
|
JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSXDRState *)
|
extern JS_PUBLIC_API(JSXDRState *)
|
||||||
JS_XDRNewMem(JSContext *cx, JSXDRMode mode);
|
JS_XDRNewMem(JSContext *cx, JSXDRMode mode);
|
||||||
|
@ -155,16 +157,20 @@ extern JS_PUBLIC_API(JSBool)
|
||||||
JS_XDRValue(JSXDRState *xdr, jsval *vp);
|
JS_XDRValue(JSXDRState *xdr, jsval *vp);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
extern JS_PUBLIC_API(JSBool)
|
||||||
JS_RegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *lp);
|
JS_XDRScript(JSXDRState *xdr, JSScript **scriptp);
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(JSBool)
|
||||||
|
JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *lp);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(uint32)
|
extern JS_PUBLIC_API(uint32)
|
||||||
JS_FindClassIdByName(JSXDRState *xdr, const char *name);
|
JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSClass *)
|
extern JS_PUBLIC_API(JSClass *)
|
||||||
JS_FindClassById(JSXDRState *xdr, uint32 id);
|
JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
|
||||||
|
|
||||||
/* Magic values */
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Magic numbers.
|
||||||
|
*/
|
||||||
#define JSXDR_MAGIC_SCRIPT_1 0xdead0001
|
#define JSXDR_MAGIC_SCRIPT_1 0xdead0001
|
||||||
#define JSXDR_MAGIC_SCRIPT_2 0xdead0002
|
#define JSXDR_MAGIC_SCRIPT_2 0xdead0002
|
||||||
#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_2
|
#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_2
|
||||||
|
|
Загрузка…
Ссылка в новой задаче