diff --git a/content/canvas/src/CustomQS_WebGL.h b/content/canvas/src/CustomQS_WebGL.h index 24252374e4b..09d27c57973 100644 --- a/content/canvas/src/CustomQS_WebGL.h +++ b/content/canvas/src/CustomQS_WebGL.h @@ -768,298 +768,3 @@ nsICanvasRenderingContextWebGL_VertexAttrib4fv(JSContext *cx, uintN argc, jsval { return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 4); } - -#ifdef JS_TRACER - -static inline jsval FASTCALL -helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj, - JSObject *arg, int nElements) -{ - XPC_QS_ASSERT_CONTEXT_OK(cx); - - nsICanvasRenderingContextWebGL *self; - xpc_qsSelfRef selfref; - xpc_qsArgValArray<3> vp(cx); - if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) { - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - js::AutoValueRooter obj_tvr(cx); - - nsIWebGLUniformLocation *location; - xpc_qsSelfRef location_selfref; - nsresult rv_convert_arg0 - = xpc_qsUnwrapThis(cx, locationobj, nsnull, &location, &location_selfref.ptr, &vp.array[1], nsnull); - if (NS_FAILED(rv_convert_arg0)) { - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - js::TypedArray *wa = 0; - - if (helper_isInt32Array(arg)) { - wa = js::TypedArray::fromJSObject(arg); - } else if (JS_IsArrayObject(cx, arg)) { - JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_INT32, arg); - if (!nobj) { - // XXX this will likely return a strange error message if it goes wrong - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - *obj_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj); - wa = js::TypedArray::fromJSObject(nobj); - } else { - xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNiv"); - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - nsresult rv; - - if (nElements == 1) { - rv = self->Uniform1iv_array(location, wa); - } else if (nElements == 2) { - rv = self->Uniform2iv_array(location, wa); - } else if (nElements == 3) { - rv = self->Uniform3iv_array(location, wa); - } else if (nElements == 4) { - rv = self->Uniform4iv_array(location, wa); - } - - if (NS_FAILED(rv)) { - xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformNiv"); - js_SetTraceableNativeFailed(cx); - } - - return JSVAL_VOID; -} - -static inline jsval FASTCALL -helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj, - JSObject *arg, int nElements) -{ - XPC_QS_ASSERT_CONTEXT_OK(cx); - - nsICanvasRenderingContextWebGL *self; - xpc_qsSelfRef selfref; - xpc_qsArgValArray<3> vp(cx); - if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) { - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - js::AutoValueRooter obj_tvr(cx); - - nsIWebGLUniformLocation *location; - xpc_qsSelfRef location_selfref; - nsresult rv_convert_arg0 - = xpc_qsUnwrapThis(cx, locationobj, nsnull, &location, &location_selfref.ptr, &vp.array[1], nsnull); - if (NS_FAILED(rv_convert_arg0)) { - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - js::TypedArray *wa = 0; - - if (helper_isFloat32Array(arg)) { - wa = js::TypedArray::fromJSObject(arg); - } else if (JS_IsArrayObject(cx, arg)) { - JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg); - if (!nobj) { - // XXX this will likely return a strange error message if it goes wrong - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - *obj_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj); - wa = js::TypedArray::fromJSObject(nobj); - } else { - xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNfv"); - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - nsresult rv; - - if (nElements == 1) { - rv = self->Uniform1fv_array(location, wa); - } else if (nElements == 2) { - rv = self->Uniform2fv_array(location, wa); - } else if (nElements == 3) { - rv = self->Uniform3fv_array(location, wa); - } else if (nElements == 4) { - rv = self->Uniform4fv_array(location, wa); - } - - if (NS_FAILED(rv)) { - xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformNfv"); - js_SetTraceableNativeFailed(cx); - } - - return JSVAL_VOID; -} - -static inline jsval FASTCALL -helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj, - JSBool transpose, JSObject *arg, int nElements) -{ - XPC_QS_ASSERT_CONTEXT_OK(cx); - - nsICanvasRenderingContextWebGL *self; - xpc_qsSelfRef selfref; - xpc_qsArgValArray<4> vp(cx); - if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) { - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - js::AutoValueRooter obj_tvr(cx); - - nsIWebGLUniformLocation *location; - xpc_qsSelfRef location_selfref; - nsresult rv_convert_arg0 - = xpc_qsUnwrapThis(cx, locationobj, nsnull, &location, &location_selfref.ptr, &vp.array[1], nsnull); - if (NS_FAILED(rv_convert_arg0)) { - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - js::TypedArray *wa = 0; - - if (helper_isFloat32Array(arg)) { - wa = js::TypedArray::fromJSObject(arg); - } else if (JS_IsArrayObject(cx, arg)) { - JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg); - if (!nobj) { - // XXX this will likely return a strange error message if it goes wrong - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - *obj_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj); - wa = js::TypedArray::fromJSObject(nobj); - } else { - xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv"); - js_SetTraceableNativeFailed(cx); - return JSVAL_VOID; - } - - nsresult rv; - if (nElements == 2) { - rv = self->UniformMatrix2fv_array(location, transpose, wa); - } else if (nElements == 3) { - rv = self->UniformMatrix3fv_array(location, transpose, wa); - } else if (nElements == 4) { - rv = self->UniformMatrix4fv_array(location, transpose, wa); - } - - if (NS_FAILED(rv)) { - xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv"); - js_SetTraceableNativeFailed(cx); - } - - return JSVAL_VOID; -} - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_Uniform1iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 1); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1iv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_Uniform2iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 2); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2iv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_Uniform3iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 3); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3iv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_Uniform4iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 4); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4iv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_Uniform1fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 1); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1fv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_Uniform2fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 2); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2fv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_Uniform3fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 3); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3fv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_Uniform4fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 4); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4fv, - (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 2); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix2fv, - (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 3); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix3fv, - (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -static jsval FASTCALL -nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg) -{ - return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 4); -} - -JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix4fv, - (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY))) - -#endif /* JS_TRACER */ diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index faccb2b706e..bccb3ae8faf 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -9119,7 +9119,6 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // If we have (or just created) a helper, pass the resolve flags // to the helper as its private data. // TODO: fix - JS_ASSERT(false && "Relying on dirty private = int details"); if (helper && !::JS_SetPrivate(cx, helper, FlagsToPrivate(flags))) { nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED); diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 7d66f26a0ba..20fba0c61ba 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -268,6 +268,12 @@ JSVAL_IS_UNDERLYING_TYPE_OF_PRIVATE(jsval v) return JSVAL_IS_UNDERLYING_TYPE_OF_PRIVATE_IMPL(l); } +static JS_ALWAYS_INLINE JSBool +JSVAL_MAY_BE_PRIVATE(jsval v) +{ + return JSVAL_IS_UNDERLYING_TYPE_OF_PRIVATE(v); +} + /* Lock and unlock the GC thing held by a jsval. */ #define JSVAL_LOCK(cx,v) (JSVAL_IS_GCTHING(v) \ ? JS_LockGCThing(cx, JSVAL_TO_GCTHING(v)) \ @@ -3031,6 +3037,7 @@ class Value * uses of public jsval members in jsapi.h/jspubtd.h. */ friend class PrimitiveValue; + friend jsdouble UnboxDoubleHelper(uint32 mask, uint32 payload); protected: /* Type masks */ diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 495522c487a..01978b900c0 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -353,8 +353,9 @@ JSObject::resizeDenseArrayElements(JSContext *cx, uint32 oldcap, uint32 newcap, setDenseArrayCapacity(newcap); if (initializeAllSlots) { - for (uint32 i = oldcap; i < newcap; i++) - setDenseArrayElement(i, JS_ARRAY_HOLE); + Value *base = addressOfDenseArrayElement(0); + for (Value *vp = base + oldcap, *end = base + newcap; vp < end; ++vp) + vp->setMagic(JS_ARRAY_HOLE); } return true; @@ -900,7 +901,7 @@ js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj) #ifdef JS_TRACER -static inline JSBool FASTCALL +static JS_ALWAYS_INLINE JSBool FASTCALL dense_grow(JSContext* cx, JSObject* obj, jsint i, const Value &v) { /* diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index ea0e55915c2..fc5128601c2 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -103,13 +103,29 @@ js_imod(int32 a, int32 b) } JS_DEFINE_CALLINFO_2(extern, INT32, js_imod, INT32, INT32, 1, ACC_NONE) +namespace js { + +jsdouble JS_ALWAYS_INLINE +UnboxDoubleHelper(uint32 mask, uint32 payload) +{ + if (mask == JSVAL_MASK32_INT32) { + return int32(payload); + } else { + Value v; + v.data.s.u.mask32 = mask; + v.data.s.payload.u32 = payload; + return v.asDouble(); + } +} + +} jsdouble FASTCALL -js_UnboxDouble(Value *v) +js_UnboxDouble(uint32 mask, uint32 payload) { - return v->asNumber(); + return UnboxDoubleHelper(mask, payload); } -JS_DEFINE_CALLINFO_1(extern, DOUBLE, js_UnboxDouble, VALUEPTR, 1, ACC_NONE) +JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_UnboxDouble, UINT32, UINT32, 1, ACC_NONE) int32 FASTCALL js_UnboxInt32(Value *v) @@ -259,7 +275,11 @@ HasProperty(JSContext* cx, JSObject* obj, jsid id) JSBool FASTCALL js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr) { - return HasProperty(cx, obj, ATOM_TO_JSID(idstr)); + jsid id; + if (!js_ValueToStringId(cx, StringTag(idstr), &id)) + return JS_NEITHER; + + return HasProperty(cx, obj, id); } JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedProperty, CONTEXT, OBJECT, STRING, 0, ACC_STORE_ANY) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index d879cb6bc38..b85ed790aa1 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -48,7 +48,6 @@ #include #include -#define __STDC_LIMIT_MACROS #include "jsstdint.h" #include "jstypes.h" diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 24be87108c7..1bbacf6bc73 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -877,7 +877,7 @@ js_NumberValueToCharBuffer(JSContext *cx, const Value &v, JSCharBuffer &cb) size_t cstrlen = strlen(cstr); JS_ASSERT(cstrlen < arrSize); size_t sizeBefore = cb.length(); - if (!cb.growBy(cstrlen)) + if (!cb.growByUninitialized(cstrlen)) return JS_FALSE; jschar *appendBegin = cb.begin() + sizeBefore; #ifdef DEBUG diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index 3d30105275c..b986f8cb785 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -162,10 +162,11 @@ typedef struct JSCompartment JSCompartment; * TODO: explain boxing strategy */ +#if defined(__cplusplus) || !defined(_MSC_VER) typedef enum JSValueMask16 -#if defined(_MSC_VER) +# if defined(_MSC_VER) : uint16 -#endif +# endif { JSVAL_MASK16_NULL = (uint16)0x0001, JSVAL_MASK16_UNDEFINED = (uint16)0x0002, @@ -188,10 +189,30 @@ typedef enum JSValueMask16 */ JSVAL_NANBOX_PATTERN = ((uint16)0xFFFF) } -#if defined(__GNUC__) +# if defined(__GNUC__) __attribute__((packed)) -#endif +# endif JSValueMask16; +#else /* defined(__cplusplus) || !defined(_MSC_VER) */ +// We need this C API for MSVC, because MSVC doesn't allow us to +// make a 16-bit enum in C. +typedef uint16 JSValueMask16; + +#define JSVAL_MASK16_NULL ((uint16)0x0001) +#define JSVAL_MASK16_UNDEFINED ((uint16)0x0002) +#define JSVAL_MASK16_INT32 ((uint16)0x0004) +#define JSVAL_MASK16_STRING ((uint16)0x0008) +#define JSVAL_MASK16_NONFUNOBJ ((uint16)0x0010) +#define JSVAL_MASK16_FUNOBJ ((uint16)0x0020) +#define JSVAL_MASK16_BOOLEAN ((uint16)0x0040) +#define JSVAL_MASK16_MAGIC ((uint16)0x0080) +#define JSVAL_MASK16_SINGLETON (JSVAL_MASK16_NULL | JSVAL_MASK16_UNDEFINED) +#define JSVAL_MASK16_OBJECT (JSVAL_MASK16_NONFUNOBJ | JSVAL_MASK16_FUNOBJ) +#define JSVAL_MASK16_OBJORNULL (JSVAL_MASK16_OBJECT | JSVAL_MASK16_NULL) +#define JSVAL_MASK16_GCTHING (JSVAL_MASK16_OBJECT | JSVAL_MASK16_STRING) +#define JSVAL_NANBOX_PATTERN ((uint16)0xFFFF) + +#endif /* defined(__cplusplus) || !defined(_MSC_VER) */ #define JSVAL_MASK32_CLEAR ((uint32)0xFFFF0000) @@ -1116,15 +1137,15 @@ static inline JSEqualityOp Jsvalify(EqualityOp f); /* Same type as HasI } /* namespace js */ typedef js::Class JSFunctionClassType; +extern "C" JS_FRIEND_DATA(JSFunctionClassType) js_FunctionClass; #else /* !defined(__cplusplus) */ typedef JSClass JSFunctionClassType; +extern JS_FRIEND_DATA(JSFunctionClassType) js_FunctionClass; #endif /* __cplusplus */ -extern JS_FRIEND_DATA(JSFunctionClassType) js_FunctionClass; - typedef struct JSPretendObject { void *_; diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp index 2abc98f4b17..8fef7e7a96c 100644 --- a/js/src/jsrecursion.cpp +++ b/js/src/jsrecursion.cpp @@ -731,17 +731,8 @@ TraceRecorder::slurpInt32Slot(LIns* addr_ins, ptrdiff_t offset, Value* vp, VMSid { LIns *mask_ins = lir->insLoad(LIR_ldi, addr_ins, offset + offsetof(jsval_layout, s.u.mask32), ACC_OTHER); - guard(false, - lir->insEqI_0(lir->ins2(LIR_ori, - lir->ins2(LIR_eqi, mask_ins, INS_CONST(JSVAL_MASK32_INT32)), - lir->ins2(LIR_ltui, mask_ins, INS_CONST(JSVAL_MASK32_CLEAR)))), - exit); - LIns* space = lir->insAlloc(sizeof(int32)); - LIns* args[] = { space, lir->ins2(LIR_addp, addr_ins, INS_CONST(offset)) }; - LIns* result = lir->insCall(&js_TryUnboxInt32_ci, args); - guard(false, lir->insEqI_0(result), exit); - LIns* int32_ins = lir->insLoad(LIR_ldi, space, 0, ACC_OTHER); - return int32_ins; + guard(true, lir->ins2(LIR_eqi, mask_ins, INS_CONST(JSVAL_MASK32_INT32)), exit); + return lir->insLoad(LIR_ldi, addr_ins, offset + offsetof(jsval_layout, s.payload), ACC_OTHER); } JS_REQUIRES_STACK LIns* @@ -749,13 +740,8 @@ TraceRecorder::slurpDoubleSlot(LIns* addr_ins, ptrdiff_t offset, Value* vp, VMSi { LIns *mask_ins = lir->insLoad(LIR_ldi, addr_ins, offset + offsetof(jsval_layout, s.u.mask32), ACC_OTHER); - guard(false, - lir->insEqI_0(lir->ins2(LIR_ori, - lir->ins2(LIR_eqi, mask_ins, INS_CONST(JSVAL_MASK32_INT32)), - lir->ins2(LIR_ltui, mask_ins, INS_CONST(JSVAL_MASK32_CLEAR)))), - exit); - LIns* args[] = { lir->ins2(LIR_addp, addr_ins, INS_CONST(offset)) }; - return lir->insCall(&js_UnboxDouble_ci, args); + guard(true, lir->ins2(LIR_ltui, mask_ins, INS_CONST(JSVAL_MASK32_CLEAR)), exit); + return lir->insLoad(LIR_ldd, addr_ins, offset + offsetof(jsval_layout, s.payload), ACC_OTHER); } JS_REQUIRES_STACK LIns* diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index d93995b7934..ab5b5e58204 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -1901,7 +1901,7 @@ ReplaceCallback(JSContext *cx, size_t count, void *p) return false; size_t growth = leftlen + replen; - if (!rdata.cb.growBy(growth)) + if (!rdata.cb.growByUninitialized(growth)) return false; jschar *chars = rdata.cb.begin() + rdata.index; diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 789fa78d247..10ab4b739ec 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -5844,7 +5844,7 @@ JS_REQUIRES_STACK MonitorResult TraceRecorder::recordLoopEdge(JSContext* cx, TraceRecorder* r, uintN& inlineCallCount) { #ifdef JS_THREADSAFE - if (cx->fp->scopeChain->getGlobal()->scope()->title.ownercx != cx) { + if (cx->fp->scopeChainObj()->getGlobal()->scope()->title.ownercx != cx) { AbortRecording(cx, "Global object not owned by this context"); return MONITOR_NOT_RECORDING; /* we stay away from shared global objects */ } @@ -8226,6 +8226,13 @@ TraceRecorder::d2i(LIns* f, bool resultCanBeImpreciseIfFractional) } if (f->isCall()) { const CallInfo* ci = f->callInfo(); + if (ci == &js_UnboxDouble_ci) { + LIns *boxed = lir->insAlloc(sizeof(Value)); + lir->insStore(fcallarg(f, 1), boxed, 0, ACC_OTHER); + lir->insStore(fcallarg(f, 0), boxed, sizeof(uint32), ACC_OTHER); + LIns* args[] = { boxed }; + return lir->insCall(&js_UnboxInt32_ci, args); + } if (ci == &js_StringToNumber_ci) { LIns* args[] = { fcallarg(f, 1), fcallarg(f, 0) }; return lir->insCall(&js_StringToInt32_ci, args); @@ -9350,23 +9357,35 @@ TraceRecorder::stobj_get_slot(LIns* obj_ins, unsigned slot, LIns*& dslots_ins) } JS_REQUIRES_STACK LIns* -TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VMSideExit *exit) +TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VMSideExit *exit, + bool force_double) { AccSet accSet = vaddr_ins == lirbuf->sp ? ACC_STACK : ACC_OTHER; LIns *mask_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + offsetof(jsval_layout, s.u.mask32), accSet); - if (v.isNumber()) { + if (v.isNumber() && force_double) { guard(false, lir->insEqI_0(lir->ins2(LIR_ori, lir->ins2(LIR_eqi, mask_ins, INS_CONST(JSVAL_MASK32_INT32)), lir->ins2(LIR_ltui, mask_ins, INS_CONST(JSVAL_MASK32_CLEAR)))), exit); - LIns* args[] = { lir->ins2(LIR_addp, vaddr_ins, INS_CONST(offset)) }; + LIns *val_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + offsetof(jsval_layout, s.payload), + accSet); + LIns* args[] = { val_ins, mask_ins }; return lir->insCall(&js_UnboxDouble_ci, args); } - LIns *val_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + offsetof(jsval_layout, s.payload), - accSet); + if (v.isInt32()) { + guard(true, lir->ins2(LIR_eqi, mask_ins, INS_CONST(JSVAL_MASK32_INT32)), exit); + return i2d(lir->insLoad(LIR_ldi, vaddr_ins, offset + offsetof(jsval_layout, s.payload), accSet)); + } + + if (v.isDouble()) { + guard(true, lir->ins2(LIR_ltui, mask_ins, INS_CONST(JSVAL_MASK32_CLEAR)), exit); + return lir->insLoad(LIR_ldd, vaddr_ins, offset + offsetof(jsval_layout, s.payload), accSet); + } + + LIns *val_ins = NULL; uint32 mask; if (v.isUndefined()) { mask = JSVAL_MASK32_UNDEFINED; @@ -9387,6 +9406,9 @@ TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VM } else { JS_NOT_REACHED("bad type"); } + if (!val_ins) + val_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + offsetof(jsval_layout, s.payload), + accSet); guard(true, lir->ins2(LIR_eqi, mask_ins, INS_CONST(mask)), exit); return val_ins; @@ -12374,7 +12396,13 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) LIns* res_ins; LIns* args[] = { NULL, idx_ins, obj_ins, cx_ins }; if (v.isNumber()) { - if (isPromoteInt(v_ins)) { + if (fcallinfo(v_ins) == &js_UnboxDouble_ci) { + LIns *boxed = lir->insAlloc(sizeof(Value)); + lir->insStore(fcallarg(v_ins, 1), boxed, 0, ACC_OTHER); + lir->insStore(fcallarg(v_ins, 0), boxed, sizeof(uint32), ACC_OTHER); + args[0] = boxed; + res_ins = lir->insCall(&js_Array_dense_setelem_ci, args); + } else if (isPromoteInt(v_ins)) { args[0] = demote(lir, v_ins); res_ins = lir->insCall(&js_Array_dense_setelem_int_ci, args); } else { @@ -13239,7 +13267,7 @@ TraceRecorder::denseArrayElement(Value& oval, Value& ival, Value*& vp, LIns*& v_ JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this. addr_ins = lir->ins2(LIR_addp, dslots_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 3)); - v_ins = unbox_value(*vp, addr_ins, 0, exit); + v_ins = unbox_value(*vp, addr_ins, 0, exit, true); /* Don't let the hole value escape. Turn it into an undefined. */ if (vp->isMagic()) { diff --git a/js/src/jstracer.h b/js/src/jstracer.h index e93a83c7c2e..bdec64b9cde 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1328,7 +1328,8 @@ class TraceRecorder int v_spindex); JS_REQUIRES_STACK nanojit::LIns* unbox_value(const Value &v, nanojit::LIns *vaddr_ins, - ptrdiff_t offset, VMSideExit *exit); + ptrdiff_t offset, VMSideExit *exit, + bool force_double=false); JS_REQUIRES_STACK nanojit::LIns* unbox_value_load(const Value &v, nanojit::LIns *vload_ins, VMSideExit *exit); JS_REQUIRES_STACK nanojit::LIns* unbox_int(const Value &v, nanojit::LIns *vaddr_ins, diff --git a/js/src/jsvector.h b/js/src/jsvector.h index c0a3a9eb8f3..156400c7113 100644 --- a/js/src/jsvector.h +++ b/js/src/jsvector.h @@ -190,6 +190,8 @@ class Vector : AllocPolicy bool growHeapStorageBy(size_t lengthInc); bool convertToHeapStorage(size_t lengthInc); + template inline bool growByImpl(size_t inc); + /* magic constants */ static const int sMaxInlineBytes = 1024; @@ -371,6 +373,9 @@ class Vector : AllocPolicy /* Call shrinkBy or growBy based on whether newSize > length(). */ bool resize(size_t newLength); + /* Leave new elements as uninitialized memory. */ + bool growByUninitialized(size_t incr); + void clear(); bool append(const T &t); @@ -546,15 +551,17 @@ Vector::shrinkBy(size_t incr) } template -inline bool -Vector::growBy(size_t incr) +template +JS_ALWAYS_INLINE bool +Vector::growByImpl(size_t incr) { ReentrancyGuard g(*this); if (usingInlineStorage()) { size_t freespace = sInlineCapacity - inlineLength(); if (incr <= freespace) { T *newend = inlineEnd() + incr; - Impl::initialize(inlineEnd(), newend); + if (InitNewElems) + Impl::initialize(inlineEnd(), newend); inlineLength() += incr; JS_ASSERT(usingInlineStorage()); return true; @@ -574,11 +581,26 @@ Vector::growBy(size_t incr) /* We are !usingInlineStorage(). Initialize new elements. */ JS_ASSERT(heapCapacity() - heapLength() >= incr); T *newend = heapEnd() + incr; - Impl::initialize(heapEnd(), newend); + if (InitNewElems) + Impl::initialize(heapEnd(), newend); heapEnd() = newend; return true; } +template +inline bool +Vector::growBy(size_t incr) +{ + return growByImpl(incr); +} + +template +inline bool +Vector::growByUninitialized(size_t incr) +{ + return growByImpl(incr); +} + template inline bool Vector::resize(size_t newLength) diff --git a/js/src/trace-test/tests/basic/bug569651.js b/js/src/trace-test/tests/basic/bug569651.js new file mode 100644 index 00000000000..58f9c136267 --- /dev/null +++ b/js/src/trace-test/tests/basic/bug569651.js @@ -0,0 +1,3 @@ +// don't crash or assert + ++Function("switch(\"\"){case 1:case 8:}"); \ No newline at end of file diff --git a/js/src/trace-test/tests/basic/bug572229.js b/js/src/trace-test/tests/basic/bug572229.js new file mode 100644 index 00000000000..c45cea0b6c1 --- /dev/null +++ b/js/src/trace-test/tests/basic/bug572229.js @@ -0,0 +1,12 @@ +// Don't crash + +function f(o, s) { + var k = s.substr(0, 1); + var c; + for (var i = 0; i < 10; ++i) { + c = k in o; + } + return c; +} + +assertEq(f({ a: 66 }, 'abc'), true); diff --git a/js/src/xpconnect/src/Makefile.in b/js/src/xpconnect/src/Makefile.in index 99977d462d4..da2fcb93a7a 100644 --- a/js/src/xpconnect/src/Makefile.in +++ b/js/src/xpconnect/src/Makefile.in @@ -159,7 +159,10 @@ DEFINES += \ $(addprefix -D,$(filter AVMPLUS%,$(CONFIG))) \ $(NULL) -ENABLE_TRACEABLE_FLAGS = --enable-traceables +# Disable traceable natives because (a) many of them return jsvals, which is +# hard to support now, and (b) we can call the basic versions from trace now +# anyway. +ENABLE_TRACEABLE_FLAGS = endif # ENABLE_JIT diff --git a/js/src/xpconnect/src/XPCDispConvert.cpp b/js/src/xpconnect/src/XPCDispConvert.cpp index 87b9464b1e0..726eb0de802 100644 --- a/js/src/xpconnect/src/XPCDispConvert.cpp +++ b/js/src/xpconnect/src/XPCDispConvert.cpp @@ -309,7 +309,7 @@ JSBool XPCDispConvert::JSToCOM(XPCCallContext& ccx, case VT_R8: { varDest->vt = VT_R8; - varDest->dblVal = *JSVAL_TO_DOUBLE(src); + varDest->dblVal = JSVAL_TO_DOUBLE(src); } break; case VT_EMPTY: diff --git a/js/src/xpconnect/src/XPCDispInterface.cpp b/js/src/xpconnect/src/XPCDispInterface.cpp index da4847f09f6..6bd80983806 100644 --- a/js/src/xpconnect/src/XPCDispInterface.cpp +++ b/js/src/xpconnect/src/XPCDispInterface.cpp @@ -366,7 +366,7 @@ JSBool XPCDispInterface::Member::GetValue(XPCCallContext& ccx, return JS_FALSE; // Store ourselves and our native interface within the JSObject - if(!JS_SetReservedSlot(ccx, funobj, 0, PRIVATE_TO_JSVAL(this))) + if(!JS_SetReservedSlot(ccx, funobj, 0, PRIVATE_TO_JSVAL((void *) this))) return JS_FALSE; if(!JS_SetReservedSlot(ccx, funobj, 1, PRIVATE_TO_JSVAL(iface))) diff --git a/js/src/xpconnect/src/XPCDispTearOff.cpp b/js/src/xpconnect/src/XPCDispTearOff.cpp index 4c0f30e5517..ad93a2ab702 100644 --- a/js/src/xpconnect/src/XPCDispTearOff.cpp +++ b/js/src/xpconnect/src/XPCDispTearOff.cpp @@ -386,7 +386,7 @@ STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid, goto pre_call_clean_up; } - sp = stackbase = args.getvp(); + sp = stackbase = Jsvalify(args.getvp()); // this is a function call, so push function and 'this' *sp++ = fval; diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index eb2a0702d33..f837c0fbcbe 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -2804,7 +2804,38 @@ JS_EXPORT_API(void) DumpJSObject(JSObject* obj) JS_EXPORT_API(void) DumpJSValue(jsval val) { - js::DumpValue(js::Valueify(val)); + printf("Dumping 0x%p.\n", (void *) val); + if(JSVAL_IS_NULL(val)) { + printf("Value is null\n"); + } + else if(JSVAL_IS_OBJECT(val) || JSVAL_IS_NULL(val)) { + printf("Value is an object\n"); + JSObject* obj = JSVAL_TO_OBJECT(val); + DumpJSObject(obj); + } + else if(JSVAL_IS_NUMBER(val)) { + printf("Value is a number: "); + if(JSVAL_IS_INT(val)) + printf("Integer %i\n", JSVAL_TO_INT(val)); + else if(JSVAL_IS_DOUBLE(val)) + printf("Floating-point value %f\n", JSVAL_TO_DOUBLE(val)); + } + else if(JSVAL_IS_STRING(val)) { + printf("Value is a string: "); + JSString* string = JSVAL_TO_STRING(val); + char* bytes = JS_GetStringBytes(string); + printf("<%s>\n", bytes); + } + else if(JSVAL_IS_BOOLEAN(val)) { + printf("Value is boolean: "); + printf(JSVAL_TO_BOOLEAN(val) ? "true" : "false"); + } + else if(JSVAL_IS_VOID(val)) { + printf("Value is undefined\n"); + } + else { + printf("No idea what this value is.\n"); + } } JS_END_EXTERN_C diff --git a/modules/plugin/base/src/nsJSNPRuntime.cpp b/modules/plugin/base/src/nsJSNPRuntime.cpp index 2f3348d7c60..cb98d48e9be 100644 --- a/modules/plugin/base/src/nsJSNPRuntime.cpp +++ b/modules/plugin/base/src/nsJSNPRuntime.cpp @@ -197,7 +197,7 @@ static JSClass sNPObjectJSWrapperClass = typedef struct NPObjectMemberPrivate { JSObject *npobjWrapper; jsval fieldValue; - jsval methodName; + NPIdentifier methodName; NPP npp; } NPObjectMemberPrivate; @@ -598,25 +598,23 @@ nsJSObjWrapper::NP_Invalidate(NPObject *npobj) } static JSBool -GetProperty(JSContext *cx, JSObject *obj, NPIdentifier identifier, jsval *rval) +GetProperty(JSContext *cx, JSObject *obj, NPIdentifier id, jsval *rval) { - jsval id = (jsval)identifier; - - if (JSVAL_IS_STRING(id)) { - JSString *str = JSVAL_TO_STRING(id); + if (NPIdentifierIsString(id)) { + JSString *str = NPIdentifierToString(id); return ::JS_GetUCProperty(cx, obj, ::JS_GetStringChars(str), ::JS_GetStringLength(str), rval); } - NS_ASSERTION(JSVAL_IS_INT(id), "id must be either string or int!\n"); + NS_ASSERTION(NPIdentifierIsInt(id), "id must be either string or int!\n"); - return ::JS_GetElement(cx, obj, JSVAL_TO_INT(id), rval); + return ::JS_GetElement(cx, obj, NPIdentifierToInt(id), rval); } // static bool -nsJSObjWrapper::NP_HasMethod(NPObject *npobj, NPIdentifier identifier) +nsJSObjWrapper::NP_HasMethod(NPObject *npobj, NPIdentifier id) { NPP npp = NPPStack::Peek(); JSContext *cx = GetJSContext(npp); @@ -639,7 +637,7 @@ nsJSObjWrapper::NP_HasMethod(NPObject *npobj, NPIdentifier identifier) AutoJSExceptionReporter reporter(cx); jsval v; - JSBool ok = GetProperty(cx, npjsobj->mJSObj, identifier, &v); + JSBool ok = GetProperty(cx, npjsobj->mJSObj, id, &v); return ok && !JSVAL_IS_PRIMITIVE(v) && ::JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(v)); @@ -672,7 +670,7 @@ doInvoke(NPObject *npobj, NPIdentifier method, const NPVariant *args, JSAutoRequest ar(cx); AutoJSExceptionReporter reporter(cx); - if ((jsval)method != JSVAL_VOID) { + if (method != NPIdentifier_VOID) { if (!GetProperty(cx, npjsobj->mJSObj, method, &fv) || ::JS_TypeOfValue(cx, fv) != JSTYPE_FUNCTION) { return PR_FALSE; @@ -742,7 +740,7 @@ nsJSObjWrapper::NP_Invoke(NPObject *npobj, NPIdentifier method, const NPVariant *args, uint32_t argCount, NPVariant *result) { - if ((jsval)method == JSVAL_VOID) { + if (method == NPIdentifier_VOID) { return PR_FALSE; } @@ -754,13 +752,13 @@ bool nsJSObjWrapper::NP_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result) { - return doInvoke(npobj, (NPIdentifier)JSVAL_VOID, args, argCount, PR_FALSE, + return doInvoke(npobj, NPIdentifier_VOID, args, argCount, PR_FALSE, result); } // static bool -nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier identifier) +nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier id) { NPP npp = NPPStack::Peek(); JSContext *cx = GetJSContext(npp); @@ -777,22 +775,21 @@ nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier identifier) } nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj; - jsval id = (jsval)identifier; JSBool found, ok = JS_FALSE; AutoCXPusher pusher(cx); JSAutoRequest ar(cx); AutoJSExceptionReporter reporter(cx); - if (JSVAL_IS_STRING(id)) { - JSString *str = JSVAL_TO_STRING(id); + if (NPIdentifierIsString(id)) { + JSString *str = NPIdentifierToString(id); ok = ::JS_HasUCProperty(cx, npjsobj->mJSObj, ::JS_GetStringChars(str), ::JS_GetStringLength(str), &found); } else { - NS_ASSERTION(JSVAL_IS_INT(id), "id must be either string or int!\n"); + NS_ASSERTION(NPIdentifierIsInt(id), "id must be either string or int!\n"); - ok = ::JS_HasElement(cx, npjsobj->mJSObj, JSVAL_TO_INT(id), &found); + ok = ::JS_HasElement(cx, npjsobj->mJSObj, NPIdentifierToInt(id), &found); } return ok && found; @@ -800,7 +797,7 @@ nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier identifier) // static bool -nsJSObjWrapper::NP_GetProperty(NPObject *npobj, NPIdentifier identifier, +nsJSObjWrapper::NP_GetProperty(NPObject *npobj, NPIdentifier id, NPVariant *result) { NPP npp = NPPStack::Peek(); @@ -824,13 +821,13 @@ nsJSObjWrapper::NP_GetProperty(NPObject *npobj, NPIdentifier identifier, AutoJSExceptionReporter reporter(cx); jsval v; - return (GetProperty(cx, npjsobj->mJSObj, identifier, &v) && + return (GetProperty(cx, npjsobj->mJSObj, id, &v) && JSValToNPVariant(npp, cx, v, result)); } // static bool -nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier identifier, +nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier id, const NPVariant *value) { NPP npp = NPPStack::Peek(); @@ -848,7 +845,6 @@ nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier identifier, } nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj; - jsval id = (jsval)identifier; JSBool ok = JS_FALSE; AutoCXPusher pusher(cx); @@ -858,15 +854,15 @@ nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier identifier, jsval v = NPVariantToJSVal(npp, cx, value); js::AutoValueRooter tvr(cx, js::Valueify(v)); - if (JSVAL_IS_STRING(id)) { - JSString *str = JSVAL_TO_STRING(id); + if (NPIdentifierIsString(id)) { + JSString *str = NPIdentifierToString(id); ok = ::JS_SetUCProperty(cx, npjsobj->mJSObj, ::JS_GetStringChars(str), ::JS_GetStringLength(str), &v); } else { - NS_ASSERTION(JSVAL_IS_INT(id), "id must be either string or int!\n"); + NS_ASSERTION(NPIdentifierIsInt(id), "id must be either string or int!\n"); - ok = ::JS_SetElement(cx, npjsobj->mJSObj, JSVAL_TO_INT(id), &v); + ok = ::JS_SetElement(cx, npjsobj->mJSObj, NPIdentifierToInt(id), &v); } // return ok == JS_TRUE to quiet down compiler warning, even if @@ -876,7 +872,7 @@ nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier identifier, // static bool -nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier identifier) +nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier id) { NPP npp = NPPStack::Peek(); JSContext *cx = GetJSContext(npp); @@ -893,7 +889,6 @@ nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier identifier) } nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj; - jsval id = (jsval)identifier; JSBool ok = JS_FALSE; AutoCXPusher pusher(cx); @@ -901,8 +896,8 @@ nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier identifier) AutoJSExceptionReporter reporter(cx); jsval deleted = JSVAL_FALSE; - if (JSVAL_IS_STRING(id)) { - JSString *str = JSVAL_TO_STRING(id); + if (NPIdentifierIsString(id)) { + JSString *str = NPIdentifierToString(id); ok = ::JS_DeleteUCProperty2(cx, npjsobj->mJSObj, ::JS_GetStringChars(str), ::JS_GetStringLength(str), &deleted); @@ -923,16 +918,16 @@ nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier identifier) } } } else { - NS_ASSERTION(JSVAL_IS_INT(id), "id must be either string or int!\n"); + NS_ASSERTION(NPIdentifierIsInt(id), "id must be either string or int!\n"); - ok = ::JS_DeleteElement2(cx, npjsobj->mJSObj, JSVAL_TO_INT(id), &deleted); + ok = ::JS_DeleteElement2(cx, npjsobj->mJSObj, NPIdentifierToInt(id), &deleted); if (ok && deleted) { // FIXME: See bug 425823, we shouldn't need to do this, and once // that bug is fixed we can remove this code. JSBool hasProp; - ok = ::JS_HasElement(cx, npjsobj->mJSObj, JSVAL_TO_INT(id), &hasProp); + ok = ::JS_HasElement(cx, npjsobj->mJSObj, NPIdentifierToInt(id), &hasProp); if (ok && hasProp) { // The property might have been deleted, but it got @@ -950,13 +945,13 @@ nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier identifier) //static bool -nsJSObjWrapper::NP_Enumerate(NPObject *npobj, NPIdentifier **identifier, +nsJSObjWrapper::NP_Enumerate(NPObject *npobj, NPIdentifier **idarray, uint32_t *count) { NPP npp = NPPStack::Peek(); JSContext *cx = GetJSContext(npp); - *identifier = 0; + *idarray = 0; *count = 0; if (!cx) { @@ -982,8 +977,8 @@ nsJSObjWrapper::NP_Enumerate(NPObject *npobj, NPIdentifier **identifier, } *count = ida->length; - *identifier = (NPIdentifier *)PR_Malloc(*count * sizeof(NPIdentifier)); - if (!*identifier) { + *idarray = (NPIdentifier *)PR_Malloc(*count * sizeof(NPIdentifier)); + if (!*idarray) { ThrowJSException(cx, "Memory allocation failed for NPIdentifier!"); ::JS_DestroyIdArray(cx, ida); @@ -995,26 +990,29 @@ nsJSObjWrapper::NP_Enumerate(NPObject *npobj, NPIdentifier **identifier, jsval v; if (!::JS_IdToValue(cx, ida->vector[i], &v)) { ::JS_DestroyIdArray(cx, ida); - PR_Free(*identifier); + PR_Free(*idarray); return PR_FALSE; } + NPIdentifier id; if (JSVAL_IS_STRING(v)) { JSString *str = JSVAL_TO_STRING(v); if (!JS_InternUCStringN(cx, ::JS_GetStringChars(str), ::JS_GetStringLength(str))) { ::JS_DestroyIdArray(cx, ida); - PR_Free(*identifier); + PR_Free(*idarray); return PR_FALSE; } + id = StringToNPIdentifier(str); } else { NS_ASSERTION(JSVAL_IS_INT(v), "The element in ida must be either string or int!\n"); + id = IntToNPIdentifier(JSVAL_TO_INT(v)); } - (*identifier)[i] = (NPIdentifier)v; + (*idarray)[i] = id; } ::JS_DestroyIdArray(cx, ida); @@ -1027,8 +1025,7 @@ bool nsJSObjWrapper::NP_Construct(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result) { - return doInvoke(npobj, (NPIdentifier)JSVAL_VOID, args, argCount, PR_TRUE, - result); + return doInvoke(npobj, NPIdentifier_VOID, args, argCount, PR_TRUE, result); } @@ -1205,7 +1202,8 @@ NPObjWrapper_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) PluginDestructionGuard pdg(LookupNPP(npobj)); - JSBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id); + NPIdentifier identifier = JSValToNPIdentifier(id); + JSBool hasProperty = npobj->_class->hasProperty(npobj, identifier); if (!ReportExceptionIfPending(cx)) return JS_FALSE; @@ -1214,7 +1212,7 @@ NPObjWrapper_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) // We must permit methods here since JS_DefineUCFunction() will add // the function as a property - JSBool hasMethod = npobj->_class->hasMethod(npobj, (NPIdentifier)id); + JSBool hasMethod = npobj->_class->hasMethod(npobj, identifier); if (!ReportExceptionIfPending(cx)) return JS_FALSE; @@ -1241,8 +1239,10 @@ NPObjWrapper_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) PluginDestructionGuard pdg(LookupNPP(npobj)); + NPIdentifier identifier = JSValToNPIdentifier(id); + if (!NPObjectIsOutOfProcessProxy(npobj)) { - JSBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id); + JSBool hasProperty = npobj->_class->hasProperty(npobj, identifier); if (!ReportExceptionIfPending(cx)) return JS_FALSE; @@ -1250,7 +1250,7 @@ NPObjWrapper_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_TRUE; } - if (!npobj->_class->removeProperty(npobj, (NPIdentifier)id)) + if (!npobj->_class->removeProperty(npobj, identifier)) *vp = JSVAL_FALSE; return ReportExceptionIfPending(cx); @@ -1280,8 +1280,10 @@ NPObjWrapper_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) PluginDestructionGuard pdg(npp); + NPIdentifier identifier = JSValToNPIdentifier(id); + if (!NPObjectIsOutOfProcessProxy(npobj)) { - JSBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id); + JSBool hasProperty = npobj->_class->hasProperty(npobj, identifier); if (!ReportExceptionIfPending(cx)) return JS_FALSE; @@ -1299,7 +1301,7 @@ NPObjWrapper_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_FALSE; } - JSBool ok = npobj->_class->setProperty(npobj, (NPIdentifier)id, &npv); + JSBool ok = npobj->_class->setProperty(npobj, identifier, &npv); _releasevariantvalue(&npv); // Release the variant if (!ReportExceptionIfPending(cx)) return JS_FALSE; @@ -1341,6 +1343,8 @@ NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) NPVariant npv; VOID_TO_NPVARIANT(npv); + NPIdentifier identifier = JSValToNPIdentifier(id); + #ifdef MOZ_IPC if (NPObjectIsOutOfProcessProxy(npobj)) { PluginScriptableObjectParent* actor = @@ -1350,7 +1354,7 @@ NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) if (!actor) return JS_FALSE; - JSBool success = actor->GetPropertyHelper((NPIdentifier)id, &hasProperty, + JSBool success = actor->GetPropertyHelper(identifier, &hasProperty, &hasMethod, &npv); if (!ReportExceptionIfPending(cx)) { if (success) @@ -1375,11 +1379,11 @@ NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) } #endif - hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id); + hasProperty = npobj->_class->hasProperty(npobj, identifier); if (!ReportExceptionIfPending(cx)) return JS_FALSE; - hasMethod = npobj->_class->hasMethod(npobj, (NPIdentifier)id); + hasMethod = npobj->_class->hasMethod(npobj, identifier); if (!ReportExceptionIfPending(cx)) return JS_FALSE; @@ -1388,7 +1392,7 @@ NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return CreateNPObjectMember(npp, cx, obj, npobj, id, nsnull, vp); if (hasProperty) { - if (npobj->_class->getProperty(npobj, (NPIdentifier)id, &npv)) + if (npobj->_class->getProperty(npobj, identifier, &npv)) *vp = NPVariantToJSVal(npp, cx, &npv); _releasevariantvalue(&npv); @@ -1488,10 +1492,10 @@ CallNPMethodInternal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, if (npobj->_class->invoke) { JSFunction *fun = (JSFunction *)::JS_GetPrivate(cx, funobj); - jsval method = STRING_TO_JSVAL(::JS_GetFunctionId(fun)); + JSString *name = ::JS_GetFunctionId(fun); + NPIdentifier id = StringToNPIdentifier(name); - ok = npobj->_class->invoke(npobj, (NPIdentifier)method, npargs, argc, - &v); + ok = npobj->_class->invoke(npobj, id, npargs, argc, &v); } else { ok = JS_FALSE; @@ -1610,7 +1614,8 @@ NPObjWrapper_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, enum_value = state->value; length = state->length; if (state->index != length) { - return ::JS_ValueToId(cx, (jsval)enum_value[state->index++], idp); + jsval val = NPIdentifierToJSVal(enum_value[state->index++]); + return ::JS_ValueToId(cx, val, idp); } // FALL THROUGH @@ -1643,7 +1648,9 @@ NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, PluginDestructionGuard pdg(LookupNPP(npobj)); - PRBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id); + NPIdentifier identifier = JSValToNPIdentifier(id); + + PRBool hasProperty = npobj->_class->hasProperty(npobj, identifier); if (!ReportExceptionIfPending(cx)) return JS_FALSE; @@ -1670,7 +1677,7 @@ NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, return JS_TRUE; } - PRBool hasMethod = npobj->_class->hasMethod(npobj, (NPIdentifier)id); + PRBool hasMethod = npobj->_class->hasMethod(npobj, identifier); if (!ReportExceptionIfPending(cx)) return JS_FALSE; @@ -2141,6 +2148,8 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj, ::JS_SetPrivate(cx, memobj, (void *)memberPrivate); + NPIdentifier identifier = JSValToNPIdentifier(id); + jsval fieldValue; NPVariant npv; NPBool hasProperty; @@ -2153,7 +2162,7 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj, else { VOID_TO_NPVARIANT(npv); - NPBool hasProperty = npobj->_class->getProperty(npobj, (NPIdentifier)id, + NPBool hasProperty = npobj->_class->getProperty(npobj, identifier, &npv); if (!ReportExceptionIfPending(cx)) { ::JS_RemoveValueRoot(cx, vp); @@ -2178,7 +2187,7 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj, memberPrivate->npobjWrapper = obj; memberPrivate->fieldValue = fieldValue; - memberPrivate->methodName = id; + memberPrivate->methodName = identifier; memberPrivate->npp = npp; ::JS_RemoveValueRoot(cx, vp); @@ -2277,9 +2286,10 @@ NPObjectMember_Call(JSContext *cx, JSObject *obj, } } + NPVariant npv; JSBool ok; - ok = npobj->_class->invoke(npobj, (NPIdentifier)memberPrivate->methodName, + ok = npobj->_class->invoke(npobj, memberPrivate->methodName, npargs, argc, &npv); // Release arguments. diff --git a/modules/plugin/base/src/nsNPAPIPlugin.cpp b/modules/plugin/base/src/nsNPAPIPlugin.cpp index 848fc16b72f..c85d2f3596d 100644 --- a/modules/plugin/base/src/nsNPAPIPlugin.cpp +++ b/modules/plugin/base/src/nsNPAPIPlugin.cpp @@ -690,7 +690,7 @@ doGetIdentifier(JSContext *cx, const NPUTF8* name) if (!str) return NULL; - return (NPIdentifier)STRING_TO_JSVAL(str); + return StringToNPIdentifier(str); } #if defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_WINCE) @@ -1353,25 +1353,23 @@ _getintidentifier(int32_t intid) if (!NS_IsMainThread()) { NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getstringidentifier called from the wrong thread\n")); } - return (NPIdentifier)INT_TO_JSVAL(intid); + return IntToNPIdentifier(intid); } NPUTF8* NP_CALLBACK -_utf8fromidentifier(NPIdentifier identifier) +_utf8fromidentifier(NPIdentifier id) { if (!NS_IsMainThread()) { NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_utf8fromidentifier called from the wrong thread\n")); } - if (!identifier) + if (!id) return NULL; - jsval v = (jsval)identifier; - - if (!JSVAL_IS_STRING(v)) { + if (!NPIdentifierIsString(id)) { return nsnull; } - JSString *str = JSVAL_TO_STRING(v); + JSString *str = NPIdentifierToString(id); return ToNewUTF8String(nsDependentString((PRUnichar *)::JS_GetStringChars(str), @@ -1379,29 +1377,27 @@ _utf8fromidentifier(NPIdentifier identifier) } int32_t NP_CALLBACK -_intfromidentifier(NPIdentifier identifier) +_intfromidentifier(NPIdentifier id) { if (!NS_IsMainThread()) { NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_intfromidentifier called from the wrong thread\n")); } - jsval v = (jsval)identifier; - if (!JSVAL_IS_INT(v)) { + if (!NPIdentifierIsInt(id)) { return PR_INT32_MIN; } - return JSVAL_TO_INT(v); + return NPIdentifierToInt(id); } bool NP_CALLBACK -_identifierisstring(NPIdentifier identifier) +_identifierisstring(NPIdentifier id) { if (!NS_IsMainThread()) { NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_identifierisstring called from the wrong thread\n")); } - jsval v = (jsval)identifier; - return JSVAL_IS_STRING(v); + return NPIdentifierIsString(id); } NPObject* NP_CALLBACK diff --git a/modules/plugin/base/src/nsNPAPIPlugin.h b/modules/plugin/base/src/nsNPAPIPlugin.h index ad375649869..3fb55122290 100644 --- a/modules/plugin/base/src/nsNPAPIPlugin.h +++ b/modules/plugin/base/src/nsNPAPIPlugin.h @@ -43,6 +43,8 @@ #include "npfunctions.h" #include "nsPluginHost.h" +#include "jsapi.h" + #include "mozilla/PluginLibrary.h" /* @@ -114,6 +116,129 @@ namespace mozilla { namespace plugins { namespace parent { +// On 32-bit platforms, sizeof(jsval) != sizeof(NPIdentifier), so we need to +// use an alternate encoding scheme. The following inline helpers provide an +// abstraction for setting and getting the values of NPIdentifiers that should +// always be used instead of casting an NPIdentifier to a jsval and using the +// jsapi. + +#if JS_BITS_PER_WORD == 64 + +JS_STATIC_ASSERT(sizeof(NPIdentifier) == sizeof(jsval)); + +static inline bool +NPIdentifierIsString(NPIdentifer id) +{ + return JSVAL_IS_STRING((jsval)id); +} + +static inline JSString * +NPIdentifierToString(NPIdentifer id) +{ + return JSVAL_TO_STRING((jsval)id); +} + +static inline NPIdentifier +StringToNPIdentifier(JSString *str) +{ + return (NPIdentifier)STRING_TO_JSVAL(str); +} + +static inline bool +NPIdentifierIsInt(NPIdentifer id) +{ + return JSVAL_IS_INT((jsval)id); +} + +static inline jsint +NPIdentifierToInt(NPIdentifer id) +{ + return JSVAL_TO_INT((jsval)id); +} + +static inline bool +IntToNPIdentifier(JSContext *, jsint i, NPIdentifier *pid) +{ + *pid = (NPIdentifier)INT_TO_JSVAL(i); + return true; +} + +static inline bool +NPIdentifierIsVoid(NPIdentifier id) +{ + return JSVAL_IS_VOID((NPIdentifier)id); +} + +static const NPIdentifier NPIdentifier_VOID = (NPIdentifier)JSVAL_VOID; + +#else /* JS_BITS_PER_WORD == 32 */ + +static inline bool +NPIdentifierIsString(NPIdentifier id) +{ + return ((size_t)id & 0x3) == 0; +} + +static inline JSString * +NPIdentifierToString(NPIdentifier id) +{ + NS_ASSERTION(NPIdentifierIsString(id), "id must be string"); + return (JSString *)id; +} + +static inline NPIdentifier +StringToNPIdentifier(JSString *str) +{ + NS_ASSERTION(((size_t)str & 3) == 0, "Strings are assumed to be at least 4-byte aligned"); + return (NPIdentifier)str; +} + +static inline bool +NPIdentifierIsInt(NPIdentifier id) +{ + return ((size_t)id & 1) != 0; +} + +static inline jsint +NPIdentifierToInt(NPIdentifier id) +{ + NS_ASSERTION(NPIdentifierIsInt(id), "id must be int"); + return (jsint)id >> 1; +} + +static inline NPIdentifier +IntToNPIdentifier(jsint i) +{ + NS_ASSERTION(i < (1 << 30) - 1, "integer id is too big, will be truncated"); + return (NPIdentifier)((i << 1) | 0x1); +} + +static inline bool +NPIdentifierIsVoid(NPIdentifier id) +{ + return (size_t)id == 0x2; +} + +static const NPIdentifier NPIdentifier_VOID = (NPIdentifier)0x2; + +#endif + +static inline jsval +NPIdentifierToJSVal(NPIdentifier id) +{ + if (NPIdentifierIsString(id)) + return STRING_TO_JSVAL(NPIdentifierToString(id)); + return INT_TO_JSVAL(NPIdentifierToInt(id)); +} + +static inline NPIdentifier +JSValToNPIdentifier(jsval val) +{ + if (JSVAL_IS_STRING(val)) + return StringToNPIdentifier(JSVAL_TO_STRING(val)); + return IntToNPIdentifier(JSVAL_TO_INT(val)); +} + NPObject* NP_CALLBACK _getwindowobject(NPP npp);