зеркало из https://github.com/mozilla/gecko-dev.git
Bug 463243 - Assert correct type in JSVAL_TO_* (and vice versa) macros to fail fast when type errors happen. r=brendan
This commit is contained in:
Родитель
8981e06c54
Коммит
1ff6d486e9
|
@ -1991,7 +1991,7 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, void *aScope, void *aHandler
|
|||
|
||||
AutoFreeJSStack stackGuard(mContext, mark); // ensure always freed.
|
||||
|
||||
jsval funval = OBJECT_TO_JSVAL(aHandler);
|
||||
jsval funval = OBJECT_TO_JSVAL(static_cast<JSObject *>(aHandler));
|
||||
JSAutoRequest ar(mContext);
|
||||
PRBool ok = ::JS_CallFunctionValue(mContext, target,
|
||||
funval, argc, argv, &rval);
|
||||
|
|
|
@ -743,6 +743,21 @@ JS_NewRuntime(uint32 maxbytes)
|
|||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
|
||||
/*
|
||||
* If it were possible for pure inline function calls with constant
|
||||
* arguments to be computed at compile time, these would be static
|
||||
* assertions, but since it isn't, this is the best we can do.
|
||||
*/
|
||||
JS_ASSERT(JSVAL_NULL == OBJECT_TO_JSVAL(NULL));
|
||||
JS_ASSERT(JSVAL_ZERO == INT_TO_JSVAL(0));
|
||||
JS_ASSERT(JSVAL_ONE == INT_TO_JSVAL(1));
|
||||
JS_ASSERT(JSVAL_FALSE == BOOLEAN_TO_JSVAL(JS_FALSE));
|
||||
JS_ASSERT(JSVAL_TRUE == BOOLEAN_TO_JSVAL(JS_TRUE));
|
||||
|
||||
JS_ASSERT(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID) == 2);
|
||||
JS_ASSERT(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_HOLE) == 3);
|
||||
JS_ASSERT(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_ARETURN) == 4);
|
||||
|
||||
js_NewRuntimeWasCalled = JS_TRUE;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
|
109
js/src/jsapi.h
109
js/src/jsapi.h
|
@ -83,13 +83,54 @@ JS_BEGIN_EXTERN_C
|
|||
/* Objects, strings, and doubles are GC'ed. */
|
||||
#define JSVAL_IS_GCTHING(v) (!((v) & JSVAL_INT) && \
|
||||
JSVAL_TAG(v) != JSVAL_BOOLEAN)
|
||||
#define JSVAL_TO_GCTHING(v) ((void *)JSVAL_CLRTAG(v))
|
||||
#define JSVAL_TO_OBJECT(v) ((JSObject *)JSVAL_TO_GCTHING(v))
|
||||
#define JSVAL_TO_DOUBLE(v) ((jsdouble *)JSVAL_TO_GCTHING(v))
|
||||
#define JSVAL_TO_STRING(v) ((JSString *)JSVAL_TO_GCTHING(v))
|
||||
#define OBJECT_TO_JSVAL(obj) ((jsval)(obj))
|
||||
#define DOUBLE_TO_JSVAL(dp) JSVAL_SETTAG((jsval)(dp), JSVAL_DOUBLE)
|
||||
#define STRING_TO_JSVAL(str) JSVAL_SETTAG((jsval)(str), JSVAL_STRING)
|
||||
|
||||
static JS_ALWAYS_INLINE void *
|
||||
JSVAL_TO_GCTHING(jsval v)
|
||||
{
|
||||
JS_ASSERT(JSVAL_IS_GCTHING(v));
|
||||
return (void *) JSVAL_CLRTAG(v);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSObject *
|
||||
JSVAL_TO_OBJECT(jsval v)
|
||||
{
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(v));
|
||||
return (JSObject *) JSVAL_TO_GCTHING(v);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsdouble *
|
||||
JSVAL_TO_DOUBLE(jsval v)
|
||||
{
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE(v));
|
||||
return (jsdouble *) JSVAL_TO_GCTHING(v);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSString *
|
||||
JSVAL_TO_STRING(jsval v)
|
||||
{
|
||||
JS_ASSERT(JSVAL_IS_STRING(v));
|
||||
return (JSString *) JSVAL_TO_GCTHING(v);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval
|
||||
OBJECT_TO_JSVAL(JSObject *obj)
|
||||
{
|
||||
JS_STATIC_ASSERT(JSVAL_OBJECT == 0);
|
||||
JS_ASSERT(((jsval) obj & JSVAL_TAGBITS) == JSVAL_OBJECT);
|
||||
return (jsval) obj;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval
|
||||
DOUBLE_TO_JSVAL(jsdouble *dp)
|
||||
{
|
||||
return JSVAL_SETTAG((jsval) dp, JSVAL_DOUBLE);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval
|
||||
STRING_TO_JSVAL(JSString *str)
|
||||
{
|
||||
return JSVAL_SETTAG((jsval) str, JSVAL_STRING);
|
||||
}
|
||||
|
||||
/* Lock and unlock the GC thing held by a jsval. */
|
||||
#define JSVAL_LOCK(cx,v) (JSVAL_IS_GCTHING(v) \
|
||||
|
@ -109,10 +150,45 @@ JS_BEGIN_EXTERN_C
|
|||
#define JSVAL_TO_INT(v) ((jsint)(v) >> 1)
|
||||
#define INT_TO_JSVAL(i) (((jsval)(i) << 1) | JSVAL_INT)
|
||||
|
||||
/* Convert between boolean and jsval. */
|
||||
#define JSVAL_TO_BOOLEAN(v) ((JSBool)((v) >> JSVAL_TAGBITS))
|
||||
#define BOOLEAN_TO_JSVAL(b) JSVAL_SETTAG((jsval)(b) << JSVAL_TAGBITS, \
|
||||
JSVAL_BOOLEAN)
|
||||
/*
|
||||
* A pseudo-boolean is a 29-bit (for 32-bit jsval) or 61-bit (for 64-bit jsval)
|
||||
* value other than 0 or 1 encoded as a jsval whose tag is JSVAL_BOOLEAN.
|
||||
*
|
||||
* JSVAL_VOID happens to be defined as a jsval encoding a pseudo-boolean, but
|
||||
* embedders MUST NOT rely on this. All other possible pseudo-boolean values
|
||||
* are implementation-reserved and MUST NOT be constructed by any embedding of
|
||||
* SpiderMonkey.
|
||||
*/
|
||||
#define JSVAL_TO_PSEUDO_BOOLEAN(v) ((JSBool) ((v) >> JSVAL_TAGBITS))
|
||||
#define PSEUDO_BOOLEAN_TO_JSVAL(b) \
|
||||
JSVAL_SETTAG((jsval) (b) << JSVAL_TAGBITS, JSVAL_BOOLEAN)
|
||||
|
||||
/*
|
||||
* Well-known JS values. The extern'd variables are initialized when the
|
||||
* first JSContext is created by JS_NewContext (see below).
|
||||
*/
|
||||
#define JSVAL_NULL ((jsval) 0)
|
||||
#define JSVAL_ZERO INT_TO_JSVAL(0)
|
||||
#define JSVAL_ONE INT_TO_JSVAL(1)
|
||||
#define JSVAL_FALSE PSEUDO_BOOLEAN_TO_JSVAL(JS_FALSE)
|
||||
#define JSVAL_TRUE PSEUDO_BOOLEAN_TO_JSVAL(JS_TRUE)
|
||||
#define JSVAL_VOID PSEUDO_BOOLEAN_TO_JSVAL(2)
|
||||
|
||||
|
||||
/* Convert between boolean and jsval, asserting that inputs are valid. */
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_TO_BOOLEAN(jsval v)
|
||||
{
|
||||
JS_ASSERT(v == JSVAL_TRUE || v == JSVAL_FALSE);
|
||||
return JSVAL_TO_PSEUDO_BOOLEAN(v);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval
|
||||
BOOLEAN_TO_JSVAL(JSBool b)
|
||||
{
|
||||
JS_ASSERT(b == JS_TRUE || b == JS_FALSE);
|
||||
return PSEUDO_BOOLEAN_TO_JSVAL(b);
|
||||
}
|
||||
|
||||
/* A private data pointer (2-byte-aligned) can be stored as an int jsval. */
|
||||
#define JSVAL_TO_PRIVATE(v) ((void *)((v) & ~JSVAL_INT))
|
||||
|
@ -179,17 +255,6 @@ JS_BEGIN_EXTERN_C
|
|||
*/
|
||||
#define JSFUN_GENERIC_NATIVE JSFUN_LAMBDA
|
||||
|
||||
/*
|
||||
* Well-known JS values. The extern'd variables are initialized when the
|
||||
* first JSContext is created by JS_NewContext (see below).
|
||||
*/
|
||||
#define JSVAL_VOID BOOLEAN_TO_JSVAL(2)
|
||||
#define JSVAL_NULL OBJECT_TO_JSVAL(0)
|
||||
#define JSVAL_ZERO INT_TO_JSVAL(0)
|
||||
#define JSVAL_ONE INT_TO_JSVAL(1)
|
||||
#define JSVAL_FALSE BOOLEAN_TO_JSVAL(JS_FALSE)
|
||||
#define JSVAL_TRUE BOOLEAN_TO_JSVAL(JS_TRUE)
|
||||
|
||||
/*
|
||||
* Microseconds since the epoch, midnight, January 1, 1970 UTC. See the
|
||||
* comment in jstypes.h regarding safe int64 usage.
|
||||
|
|
|
@ -78,7 +78,6 @@ js_AtomToPrintableString(JSContext *cx, JSAtom *atom)
|
|||
* asserts check these relations.
|
||||
*/
|
||||
JS_STATIC_ASSERT(JSTYPE_LIMIT == 8);
|
||||
JS_STATIC_ASSERT(JSVAL_TO_BOOLEAN(JSVAL_VOID) == 2);
|
||||
JS_STATIC_ASSERT(JSTYPE_VOID == 0);
|
||||
|
||||
const char *const js_common_atom_names[] = {
|
||||
|
|
|
@ -54,10 +54,10 @@ JS_BEGIN_EXTERN_C
|
|||
*
|
||||
* JSVAL_ARETURN is used to throw asynchronous return for generator.close().
|
||||
*
|
||||
* NB: BOOLEAN_TO_JSVAL(2) is JSVAL_VOID (see jsapi.h).
|
||||
* NB: PSEUDO_BOOLEAN_TO_JSVAL(2) is JSVAL_VOID (see jsapi.h).
|
||||
*/
|
||||
#define JSVAL_HOLE BOOLEAN_TO_JSVAL(3)
|
||||
#define JSVAL_ARETURN BOOLEAN_TO_JSVAL(4)
|
||||
#define JSVAL_HOLE PSEUDO_BOOLEAN_TO_JSVAL(3)
|
||||
#define JSVAL_ARETURN PSEUDO_BOOLEAN_TO_JSVAL(4)
|
||||
|
||||
extern JSClass js_BooleanClass;
|
||||
|
||||
|
|
|
@ -383,7 +383,8 @@ js_TypeOfObject(JSContext* cx, JSObject* obj)
|
|||
JSString* FASTCALL
|
||||
js_TypeOfBoolean(JSContext* cx, int32 unboxed)
|
||||
{
|
||||
jsval boxed = BOOLEAN_TO_JSVAL(unboxed);
|
||||
/* Watch out for pseudo-booleans. */
|
||||
jsval boxed = PSEUDO_BOOLEAN_TO_JSVAL(unboxed);
|
||||
JS_ASSERT(JSVAL_IS_VOID(boxed) || JSVAL_IS_BOOLEAN(boxed));
|
||||
JSType type = JS_TypeOfValue(cx, boxed);
|
||||
return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
|
||||
|
@ -392,8 +393,9 @@ js_TypeOfBoolean(JSContext* cx, int32 unboxed)
|
|||
jsdouble FASTCALL
|
||||
js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed)
|
||||
{
|
||||
if (unboxed == JSVAL_TO_BOOLEAN(JSVAL_VOID))
|
||||
if (unboxed == JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID))
|
||||
return js_NaN;
|
||||
JS_ASSERT(unboxed == JS_TRUE || unboxed == JS_FALSE);
|
||||
return unboxed;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ struct JSTraceableNative {
|
|||
* in use. If it is, a performance regression occurs, not an actual runtime
|
||||
* error.
|
||||
*/
|
||||
#define JSVAL_ERROR_COOKIE OBJECT_TO_JSVAL((void*)0x10)
|
||||
#define JSVAL_ERROR_COOKIE OBJECT_TO_JSVAL((JSObject*)0x10)
|
||||
|
||||
/* Macros used by JS_DEFINE_CALLINFOn. */
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -651,7 +651,8 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
#endif
|
||||
ok = !wp->setter ||
|
||||
((sprop->attrs & JSPROP_SETTER)
|
||||
? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(wp->setter),
|
||||
? js_InternalCall(cx, obj,
|
||||
OBJECT_TO_JSVAL((JSObject *)wp->setter),
|
||||
1, vp, vp)
|
||||
: wp->setter(cx, OBJ_THIS_OBJECT(cx, obj), userid, vp));
|
||||
if (injectFrame) {
|
||||
|
|
|
@ -3590,7 +3590,7 @@ js_Interpret(JSContext *cx)
|
|||
JSXMLObjectOps *ops; \
|
||||
\
|
||||
ops = (JSXMLObjectOps *) obj2->map->ops; \
|
||||
if (obj2 == JSVAL_TO_OBJECT(rval)) \
|
||||
if (JSVAL_IS_OBJECT(rval) && obj2 == JSVAL_TO_OBJECT(rval)) \
|
||||
rval = lval; \
|
||||
if (!ops->equality(cx, obj2, rval, &cond)) \
|
||||
goto error; \
|
||||
|
|
|
@ -1879,7 +1879,7 @@ obj_lookupGetter(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (OBJ_IS_NATIVE(pobj)) {
|
||||
sprop = (JSScopeProperty *) prop;
|
||||
if (sprop->attrs & JSPROP_GETTER)
|
||||
*vp = OBJECT_TO_JSVAL(sprop->getter);
|
||||
*vp = OBJECT_TO_JSVAL((JSObject *) sprop->getter);
|
||||
}
|
||||
OBJ_DROP_PROPERTY(cx, pobj, prop);
|
||||
}
|
||||
|
@ -1904,7 +1904,7 @@ obj_lookupSetter(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (OBJ_IS_NATIVE(pobj)) {
|
||||
sprop = (JSScopeProperty *) prop;
|
||||
if (sprop->attrs & JSPROP_SETTER)
|
||||
*vp = OBJECT_TO_JSVAL(sprop->setter);
|
||||
*vp = OBJECT_TO_JSVAL((JSObject *) sprop->setter);
|
||||
}
|
||||
OBJ_DROP_PROPERTY(cx, pobj, prop);
|
||||
}
|
||||
|
|
|
@ -334,8 +334,8 @@ struct JSScopeProperty {
|
|||
#define SPROP_GET(cx,sprop,obj,obj2,vp) \
|
||||
(((sprop)->attrs & JSPROP_GETTER) \
|
||||
? js_InternalGetOrSet(cx, obj, (sprop)->id, \
|
||||
OBJECT_TO_JSVAL((sprop)->getter), JSACC_READ, \
|
||||
0, 0, vp) \
|
||||
OBJECT_TO_JSVAL((JSObject *) (sprop)->getter), \
|
||||
JSACC_READ, 0, 0, vp) \
|
||||
: (sprop)->getter(cx, OBJ_THIS_OBJECT(cx,obj), SPROP_USERID(sprop), vp))
|
||||
|
||||
/*
|
||||
|
@ -345,8 +345,8 @@ struct JSScopeProperty {
|
|||
#define SPROP_SET(cx,sprop,obj,obj2,vp) \
|
||||
(((sprop)->attrs & JSPROP_SETTER) \
|
||||
? js_InternalGetOrSet(cx, obj, (sprop)->id, \
|
||||
OBJECT_TO_JSVAL((sprop)->setter), JSACC_WRITE, \
|
||||
1, vp, vp) \
|
||||
OBJECT_TO_JSVAL((JSObject *) (sprop)->setter), \
|
||||
JSACC_WRITE, 1, vp, vp) \
|
||||
: ((sprop)->attrs & JSPROP_GETTER) \
|
||||
? (JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, \
|
||||
JSMSG_GETTER_ONLY, NULL), JS_FALSE) \
|
||||
|
|
|
@ -1456,8 +1456,9 @@ ValueToNative(JSContext* cx, jsval v, uint8 type, double* slot)
|
|||
debug_only_v(printf("double<%g> ", d);)
|
||||
return;
|
||||
case JSVAL_BOOLEAN:
|
||||
/* Watch out for pseudo-booleans. */
|
||||
JS_ASSERT(tag == JSVAL_BOOLEAN);
|
||||
*(JSBool*)slot = JSVAL_TO_BOOLEAN(v);
|
||||
*(JSBool*)slot = JSVAL_TO_PSEUDO_BOOLEAN(v);
|
||||
debug_only_v(printf("boolean<%d> ", *(JSBool*)slot);)
|
||||
return;
|
||||
case JSVAL_STRING:
|
||||
|
@ -1540,7 +1541,8 @@ NativeToValue(JSContext* cx, jsval& v, uint8 type, double* slot)
|
|||
jsdouble d;
|
||||
switch (type) {
|
||||
case JSVAL_BOOLEAN:
|
||||
v = BOOLEAN_TO_JSVAL(*(JSBool*)slot);
|
||||
/* Watch out for pseudo-booleans. */
|
||||
v = PSEUDO_BOOLEAN_TO_JSVAL(*(JSBool*)slot);
|
||||
debug_only_v(printf("boolean<%d> ", *(JSBool*)slot);)
|
||||
break;
|
||||
case JSVAL_INT:
|
||||
|
@ -4909,7 +4911,7 @@ TraceRecorder::ifop()
|
|||
|
||||
if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
|
||||
/* Test for boolean is true, negate later if we are testing for false. */
|
||||
cond = JSVAL_TO_BOOLEAN(v) == 1;
|
||||
cond = JSVAL_TO_PSEUDO_BOOLEAN(v) == JS_TRUE;
|
||||
x = lir->ins2i(LIR_eq, v_ins, 1);
|
||||
} else if (isNumber(v)) {
|
||||
jsdouble d = asNumber(v);
|
||||
|
@ -5178,10 +5180,10 @@ TraceRecorder::equalityHelper(jsval l, jsval r, LIns* l_ins, LIns* r_ins,
|
|||
fp = true;
|
||||
}
|
||||
} else if (JSVAL_IS_NULL(l) && JSVAL_TAG(r) == JSVAL_BOOLEAN) {
|
||||
l_ins = lir->insImm(JSVAL_TO_BOOLEAN(JSVAL_VOID));
|
||||
l_ins = lir->insImm(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID));
|
||||
cond = (r == JSVAL_VOID);
|
||||
} else if (JSVAL_TAG(l) == JSVAL_BOOLEAN && JSVAL_IS_NULL(r)) {
|
||||
r_ins = lir->insImm(JSVAL_TO_BOOLEAN(JSVAL_VOID));
|
||||
r_ins = lir->insImm(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID));
|
||||
cond = (l == JSVAL_VOID);
|
||||
} else if (isNumber(l) && JSVAL_IS_STRING(r)) {
|
||||
args[0] = r_ins, args[1] = cx_ins;
|
||||
|
@ -5432,13 +5434,13 @@ TraceRecorder::binary(LOpcode op)
|
|||
if (JSVAL_TAG(l) == JSVAL_BOOLEAN) {
|
||||
LIns* args[] = { a, cx_ins };
|
||||
a = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
|
||||
lnum = js_BooleanOrUndefinedToNumber(cx, JSVAL_TO_BOOLEAN(l));
|
||||
lnum = js_BooleanOrUndefinedToNumber(cx, JSVAL_TO_PSEUDO_BOOLEAN(l));
|
||||
leftIsNumber = true;
|
||||
}
|
||||
if (JSVAL_TAG(r) == JSVAL_BOOLEAN) {
|
||||
LIns* args[] = { b, cx_ins };
|
||||
b = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
|
||||
rnum = js_BooleanOrUndefinedToNumber(cx, JSVAL_TO_BOOLEAN(r));
|
||||
rnum = js_BooleanOrUndefinedToNumber(cx, JSVAL_TO_PSEUDO_BOOLEAN(r));
|
||||
rightIsNumber = true;
|
||||
}
|
||||
if (leftIsNumber && rightIsNumber) {
|
||||
|
@ -5735,13 +5737,10 @@ TraceRecorder::native_get(LIns* obj_ins, LIns* pobj_ins, JSScopeProperty* sprop,
|
|||
if (sprop->slot != SPROP_INVALID_SLOT)
|
||||
v_ins = stobj_get_slot(pobj_ins, sprop->slot, dslots_ins);
|
||||
else
|
||||
v_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
|
||||
v_ins = INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID));
|
||||
return true;
|
||||
}
|
||||
|
||||
// So box_jsval can emit no LIR_or at all to tag an object jsval.
|
||||
JS_STATIC_ASSERT(JSVAL_OBJECT == 0);
|
||||
|
||||
JS_REQUIRES_STACK void
|
||||
TraceRecorder::box_jsval(jsval v, LIns*& v_ins)
|
||||
{
|
||||
|
@ -6000,7 +5999,7 @@ TraceRecorder::record_EnterFrame()
|
|||
debug_only_v(
|
||||
js_Disassemble(cx, cx->fp->script, JS_TRUE, stdout);
|
||||
printf("----\n");)
|
||||
LIns* void_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
|
||||
LIns* void_ins = INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID));
|
||||
|
||||
jsval* vp = &fp->argv[fp->argc];
|
||||
jsval* vpstop = vp + ptrdiff_t(fp->fun->nargs) - ptrdiff_t(fp->argc);
|
||||
|
@ -6039,7 +6038,7 @@ TraceRecorder::record_LeaveFrame()
|
|||
JS_REQUIRES_STACK bool
|
||||
TraceRecorder::record_JSOP_PUSH()
|
||||
{
|
||||
stack(0, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID)));
|
||||
stack(0, INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6703,7 +6702,7 @@ success:
|
|||
break;
|
||||
}
|
||||
case FAIL_VOID:
|
||||
guard(false, lir->ins2i(LIR_eq, res_ins, JSVAL_TO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
|
||||
guard(false, lir->ins2i(LIR_eq, res_ins, JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
|
||||
break;
|
||||
case FAIL_COOKIE:
|
||||
guard(false, lir->ins2(LIR_eq, res_ins, INS_CONST(JSVAL_ERROR_COOKIE)), OOM_EXIT);
|
||||
|
@ -6762,7 +6761,7 @@ TraceRecorder::record_JSOP_TYPEOF()
|
|||
if (JSVAL_TAG(r) == JSVAL_BOOLEAN) {
|
||||
// We specialize identically for boolean and undefined. We must not have a hole here.
|
||||
// Pass the unboxed type here, since TypeOfBoolean knows how to handle it.
|
||||
JS_ASSERT(JSVAL_TO_BOOLEAN(r) <= 2);
|
||||
JS_ASSERT(r == JSVAL_TRUE || r == JSVAL_FALSE || r == JSVAL_VOID);
|
||||
type = lir->insCall(&js_TypeOfBoolean_ci, args);
|
||||
} else {
|
||||
JS_ASSERT(JSVAL_TAG(r) == JSVAL_OBJECT);
|
||||
|
@ -6776,7 +6775,7 @@ TraceRecorder::record_JSOP_TYPEOF()
|
|||
JS_REQUIRES_STACK bool
|
||||
TraceRecorder::record_JSOP_VOID()
|
||||
{
|
||||
stack(-1, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID)));
|
||||
stack(-1, INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -7137,7 +7136,7 @@ SetProperty_tn(JSContext* cx, JSObject* obj, JSString* idstr, jsval v)
|
|||
!OBJ_SET_PROPERTY(cx, obj, id, &v)) {
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
}
|
||||
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
return JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -7165,7 +7164,7 @@ SetElement_tn(JSContext* cx, JSObject* obj, int32 index, jsval v)
|
|||
|
||||
if (!js_Int32ToId(cx, index, &id) || !OBJ_SET_PROPERTY(cx, obj, id, &v))
|
||||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
|
||||
return JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID);
|
||||
}
|
||||
|
||||
JS_DEFINE_TRCINFO_1(SetProperty,
|
||||
|
@ -7562,7 +7561,7 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32& slot, LIns*& v_ins)
|
|||
/* Check for non-existent property reference, which results in undefined. */
|
||||
const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc];
|
||||
if (PCVAL_IS_NULL(pcval)) {
|
||||
v_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
|
||||
v_ins = INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID));
|
||||
JS_ASSERT(cs.ndefs == 1);
|
||||
stack(-cs.nuses, v_ins);
|
||||
slot = SPROP_INVALID_SLOT;
|
||||
|
@ -7653,7 +7652,7 @@ TraceRecorder::elem(jsval& oval, jsval& idx, jsval*& vp, LIns*& v_ins, LIns*& ad
|
|||
offsetof(JSRuntime, anyArrayProtoHasElement))),
|
||||
MISMATCH_EXIT);
|
||||
// Return undefined and indicate that we didn't actually read this (addr_ins).
|
||||
v_ins = lir->insImm(JSVAL_TO_BOOLEAN(JSVAL_VOID));
|
||||
v_ins = lir->insImm(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID));
|
||||
addr_ins = NULL;
|
||||
return true;
|
||||
}
|
||||
|
@ -7674,7 +7673,7 @@ TraceRecorder::elem(jsval& oval, jsval& idx, jsval*& vp, LIns*& v_ins, LIns*& ad
|
|||
if (JSVAL_TAG(*vp) == JSVAL_BOOLEAN) {
|
||||
// Optimize to guard for a hole only after untagging, so we know that
|
||||
// we have a boolean, to avoid an extra guard for non-boolean values.
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_HOLE))),
|
||||
guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_HOLE))),
|
||||
MISMATCH_EXIT);
|
||||
}
|
||||
return true;
|
||||
|
@ -8152,7 +8151,7 @@ TraceRecorder::record_JSOP_IN()
|
|||
ABORT_TRACE("string or integer expected");
|
||||
}
|
||||
|
||||
guard(false, lir->ins2i(LIR_eq, x, JSVAL_TO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
|
||||
guard(false, lir->ins2i(LIR_eq, x, JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
|
||||
x = lir->ins2i(LIR_eq, x, 1);
|
||||
|
||||
JSObject* obj2;
|
||||
|
@ -8762,7 +8761,7 @@ TraceRecorder::record_JSOP_CALLPROP()
|
|||
} else if (JSVAL_TAG(l) == JSVAL_BOOLEAN) {
|
||||
if (l == JSVAL_VOID)
|
||||
ABORT_TRACE("callprop on void");
|
||||
guard(false, lir->ins2i(LIR_eq, get(&l), JSVAL_TO_BOOLEAN(JSVAL_VOID)), MISMATCH_EXIT);
|
||||
guard(false, lir->ins2i(LIR_eq, get(&l), JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID)), MISMATCH_EXIT);
|
||||
i = JSProto_Boolean;
|
||||
debug_only(protoname = "Boolean.prototype";)
|
||||
} else {
|
||||
|
@ -8865,7 +8864,7 @@ TraceRecorder::record_JSOP_STOP()
|
|||
JS_ASSERT(OBJECT_TO_JSVAL(fp->thisp) == fp->argv[-1]);
|
||||
rval_ins = get(&fp->argv[-1]);
|
||||
} else {
|
||||
rval_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
|
||||
rval_ins = INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID));
|
||||
}
|
||||
clearFrameSlotsFromCache();
|
||||
return true;
|
||||
|
@ -8909,7 +8908,7 @@ TraceRecorder::record_JSOP_ENTERBLOCK()
|
|||
JSObject* obj;
|
||||
JS_GET_SCRIPT_OBJECT(script, GET_FULL_INDEX(0), obj);
|
||||
|
||||
LIns* void_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
|
||||
LIns* void_ins = INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID));
|
||||
for (int i = 0, n = OBJ_BLOCK_COUNT(cx, obj); i < n; i++)
|
||||
stack(i, void_ins);
|
||||
return true;
|
||||
|
@ -9272,7 +9271,7 @@ TraceRecorder::record_JSOP_NEWARRAY()
|
|||
JS_REQUIRES_STACK bool
|
||||
TraceRecorder::record_JSOP_HOLE()
|
||||
{
|
||||
stack(0, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_HOLE)));
|
||||
stack(0, INS_CONST(JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_HOLE)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -183,7 +183,7 @@
|
|||
# elif defined _MSC_VER
|
||||
# define JS_ALWAYS_INLINE __forceinline
|
||||
# elif defined __GNUC__
|
||||
# define JS_ALWAYS_INLINE __attribute__((always_inline))
|
||||
# define JS_ALWAYS_INLINE __attribute__((always_inline)) JS_INLINE
|
||||
# else
|
||||
# define JS_ALWAYS_INLINE JS_INLINE
|
||||
# endif
|
||||
|
|
|
@ -4257,6 +4257,21 @@ function testInterpreterReentery8() {
|
|||
}
|
||||
test(testInterpreterReentery8);
|
||||
|
||||
function testHolePushing() {
|
||||
var a = ["foobar", "baz"];
|
||||
for (var i = 0; i < 5; i++)
|
||||
a = [, "overwritten", "new"];
|
||||
var s = "[";
|
||||
for (i = 0; i < a.length; i++) {
|
||||
s += (i in a) ? a[i] : "<hole>";
|
||||
if (i != a.length - 1)
|
||||
s += ",";
|
||||
}
|
||||
return s + "], " + (0 in a);
|
||||
}
|
||||
testHolePushing.expected = "[<hole>,overwritten,new], false";
|
||||
test(testHolePushing);
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* _____ _ _ _____ ______ _____ _______ *
|
||||
|
|
|
@ -255,7 +255,8 @@ LookupGetterOrSetter(JSContext *cx, JSBool wantGetter, jsval *vp)
|
|||
{
|
||||
if(attrs & JSPROP_GETTER)
|
||||
{
|
||||
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(getter));
|
||||
JS_SET_RVAL(cx, vp,
|
||||
OBJECT_TO_JSVAL(reinterpret_cast<JSObject *>(getter)));
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +264,8 @@ LookupGetterOrSetter(JSContext *cx, JSBool wantGetter, jsval *vp)
|
|||
{
|
||||
if(attrs & JSPROP_SETTER)
|
||||
{
|
||||
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(setter));
|
||||
JS_SET_RVAL(cx, vp,
|
||||
OBJECT_TO_JSVAL(reinterpret_cast<JSObject *>(setter)));
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче