From 1da69179fa10fa3b05d3935bcb2b70671130da3e Mon Sep 17 00:00:00 2001 From: "mozilla@buildmonkey-right.mv.mozilla.com" Date: Fri, 11 Jun 2010 10:34:47 -0700 Subject: [PATCH 01/12] Write simpler code in JSObject::resizeDenseArrayElements so GCC does not do really really bad register allocation --- js/src/jsarray.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 495522c487a..072de2d538a 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; From eec97abca4adcf5dfa425784d99f216cb268f93d Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Fri, 11 Jun 2010 11:29:04 -0700 Subject: [PATCH 02/12] Make sure dense_grow gets inlined into the tracer functions that call it --- js/src/jsarray.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 072de2d538a..4660fe1d7c8 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -901,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) { /* From db5e1acb26569f5e380be6e921b79b9fd82481ca Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Fri, 11 Jun 2010 14:18:45 -0700 Subject: [PATCH 03/12] Avoid unnecessary initialization of js::Vector --- js/src/jscntxt.cpp | 1 - js/src/jsnum.cpp | 2 +- js/src/jsstr.cpp | 2 +- js/src/jsvector.h | 30 ++++++++++++++++++++++++++---- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index ddfdb84135d..274755bdd13 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/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/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) From e01cff89da549e0f7fec91a41611349666ac6fef Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Fri, 11 Jun 2010 18:09:58 -0700 Subject: [PATCH 04/12] Change NPAPI not to cast to from NPIdentifier and jsval. Fix silly JSObject::resizeDenseArrayElements bug introduced by earlier commit --- js/src/jsarray.cpp | 2 +- modules/plugin/base/src/nsJSNPRuntime.cpp | 134 ++++++++++++---------- modules/plugin/base/src/nsNPAPIPlugin.cpp | 26 ++--- modules/plugin/base/src/nsNPAPIPlugin.h | 125 ++++++++++++++++++++ 4 files changed, 209 insertions(+), 78 deletions(-) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 4660fe1d7c8..01978b900c0 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -354,7 +354,7 @@ JSObject::resizeDenseArrayElements(JSContext *cx, uint32 oldcap, uint32 newcap, if (initializeAllSlots) { Value *base = addressOfDenseArrayElement(0); - for (Value *vp = base + oldcap, *end = base + newcap; vp != end; ++vp) + for (Value *vp = base + oldcap, *end = base + newcap; vp < end; ++vp) vp->setMagic(JS_ARRAY_HOLE); } 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); From e645d90105bc0908798663ce66ef2587f3cf2ad6 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Mon, 14 Jun 2010 13:11:59 -0700 Subject: [PATCH 05/12] Build fixes for opt browser --- js/src/jstracer.cpp | 2 +- js/src/xpconnect/src/XPCDispTearOff.cpp | 2 +- js/src/xpconnect/src/nsXPConnect.cpp | 33 ++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 5db9a2dae02..10e337a7935 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 */ } 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 From 94e6c8a2cc55081d3fa8456c73e9a8140a119075 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Mon, 14 Jun 2010 14:24:30 -0700 Subject: [PATCH 06/12] Bug 571625: bring back box-after-unbox optimization for tracing with fatvals --- js/src/jsapi.h | 1 + js/src/jsbuiltins.cpp | 20 +++++++++++++++++--- js/src/jsrecursion.cpp | 4 +++- js/src/jstracer.cpp | 19 +++++++++++++++++-- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index fdbf46810c6..7d43927ccf2 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3029,6 +3029,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/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index ea0e55915c2..9aec5129afb 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -103,13 +103,27 @@ js_imod(int32 a, int32 b) } JS_DEFINE_CALLINFO_2(extern, INT32, js_imod, INT32, INT32, 1, ACC_NONE) +namespace js { +static 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) diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp index 2abc98f4b17..d9eda90a5cd 100644 --- a/js/src/jsrecursion.cpp +++ b/js/src/jsrecursion.cpp @@ -754,7 +754,9 @@ TraceRecorder::slurpDoubleSlot(LIns* addr_ins, ptrdiff_t offset, Value* vp, VMSi 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)) }; + LIns *val_ins = lir->insLoad(LIR_ldi, addr_ins, offset + offsetof(jsval_layout, s.payload), + ACC_OTHER); + LIns* args[] = { val_ins, mask_ins }; return lir->insCall(&js_UnboxDouble_ci, args); } diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 10e337a7935..b82b8f29fe7 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -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); @@ -9361,7 +9368,9 @@ TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VM 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); } @@ -12373,7 +12382,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 { From e54fb2ea802b186e2dde52137612b9c5862d9922 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Mon, 14 Jun 2010 14:46:31 -0700 Subject: [PATCH 07/12] Make UnboxDoubleHelper extern to match friend declaration --- js/src/jsbuiltins.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index 9aec5129afb..97638488f0a 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -104,7 +104,8 @@ js_imod(int32 a, int32 b) JS_DEFINE_CALLINFO_2(extern, INT32, js_imod, INT32, INT32, 1, ACC_NONE) namespace js { -static jsdouble JS_ALWAYS_INLINE + +jsdouble JS_ALWAYS_INLINE UnboxDoubleHelper(uint32 mask, uint32 payload) { if (mask == JSVAL_MASK32_INT32) { @@ -116,6 +117,7 @@ UnboxDoubleHelper(uint32 mask, uint32 payload) return v.asDouble(); } } + } jsdouble FASTCALL From f2f3967750f0d4e66114c0b2f8d616765b1449b3 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Mon, 14 Jun 2010 17:26:59 -0700 Subject: [PATCH 08/12] Bug 572029: fully specialize for unboxing most numbers --- js/src/jsrecursion.cpp | 24 ++++-------------------- js/src/jstracer.cpp | 23 ++++++++++++++++++----- js/src/jstracer.h | 3 ++- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp index d9eda90a5cd..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,15 +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 *val_ins = lir->insLoad(LIR_ldi, addr_ins, offset + offsetof(jsval_layout, s.payload), - ACC_OTHER); - LIns* args[] = { val_ins, mask_ins }; - 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/jstracer.cpp b/js/src/jstracer.cpp index b82b8f29fe7..c8edc76c560 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -9357,12 +9357,13 @@ 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)), @@ -9374,8 +9375,17 @@ TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VM 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; @@ -9396,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; @@ -13250,7 +13263,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 ee62b2ae9b5..6fec69fb35c 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, From d3526909268bb13eecdbe603a05fe0da948b5124 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Tue, 15 Jun 2010 15:43:41 -0700 Subject: [PATCH 09/12] Bug 572042: get tracing+fat values to build in the browser. As part of this I disabled the quickstub traceable natives. According to Andreas, we don't necessarily need them for good perf now that we can call the standard quickstub from trace. This build works on simple JS, but there are still bugs (e.g., Google Maps asserts). --- content/canvas/src/CustomQS_WebGL.h | 295 ---------------------- js/src/jsapi.h | 6 + js/src/jspubtd.h | 33 ++- js/src/xpconnect/src/Makefile.in | 5 +- js/src/xpconnect/src/XPCDispConvert.cpp | 2 +- js/src/xpconnect/src/XPCDispInterface.cpp | 2 +- 6 files changed, 39 insertions(+), 304 deletions(-) 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/js/src/jsapi.h b/js/src/jsapi.h index 7d43927ccf2..a9ec90ab37e 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)) \ 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/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))) From cf6624583883f06508792ec559d1b90da165d085 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Tue, 15 Jun 2010 16:00:16 -0700 Subject: [PATCH 10/12] Bug 572229: atomize strings passed to js_HasNamedProperty --- js/src/jsbuiltins.cpp | 6 +++++- js/src/trace-test/tests/basic/bug572229.js | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 js/src/trace-test/tests/basic/bug572229.js diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index 97638488f0a..fc5128601c2 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -275,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/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); From 29432cfcd1b4abeaaff433e779d17b3c631ebb9a Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Wed, 16 Jun 2010 11:22:14 -0700 Subject: [PATCH 11/12] Bug 572285: remove spurious assert --- dom/base/nsDOMClassInfo.cpp | 1 - 1 file changed, 1 deletion(-) 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); From cded156f8e48227202fd03029f20dffb83727152 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Wed, 16 Jun 2010 18:14:37 -0700 Subject: [PATCH 12/12] Bug 569651: add test case that formerly asserted, but is now WFM --- js/src/trace-test/tests/basic/bug569651.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 js/src/trace-test/tests/basic/bug569651.js 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