[JAEGER] Merge from Tracemonkey.
[JAEGER] Merge from Tracemonkey.
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -2412,21 +2412,17 @@ nsScriptSecurityManager::doGetObjectPrin
do {
// Note: jsClass is set before this loop, and also at the
// *end* of this loop.
// NOTE: These class and equality hook checks better match
// what IS_WRAPPER_CLASS() does in xpconnect!
- JSEqualityOp op =
- (jsClass->flags & JSCLASS_IS_EXTENDED) ?
- reinterpret_cast<const JSExtendedClass*>(jsClass)->equality :
- nsnull;
- if (op == sXPCWrappedNativeEqualityOps) {
+ if (jsClass->ext.equality == js::Valueify(sXPCWrappedNativeEqualityOps)) {
result = sXPConnect->GetPrincipal(aObj,
#ifdef DEBUG
aAllowShortCircuit
#else
PR_TRUE
#endif
);
if (result) {
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -5698,21 +5698,18 @@ CloneSimpleValues(JSContext* cx,
// Do we support FileList?
// Function objects don't get cloned.
if (JS_ObjectIsFunction(cx, obj)) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
// Security wrapped objects are not allowed either.
- JSClass* clasp = JS_GET_CLASS(cx, obj);
- if ((clasp->flags & JSCLASS_IS_EXTENDED) &&
- ((JSExtendedClass*)clasp)->wrappedObject) {
+ if (obj->getClass()->ext.wrappedObject)
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
- }
// See if this JSObject is backed by some C++ object. If it is then we assume
// that it is inappropriate to clone.
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
nsContentUtils::XPConnect()->
GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrapper));
if (wrapper) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -67,16 +67,18 @@
#include "nsLayoutUtils.h"
#include "nsComputedDOMStyle.h"
#if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK2)
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#endif
+#include "jsobj.h"
+
static PRBool IsUniversalXPConnectCapable()
{
PRBool hasCap = PR_FALSE;
nsresult rv = nsContentUtils::GetSecurityManager()->
IsCapabilityEnabled("UniversalXPConnect", &hasCap);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
return hasCap;
}
@@ -1342,24 +1344,20 @@ nsDOMWindowUtils::GetParent()
// first argument must be an object
if(JSVAL_IS_PRIMITIVE(argv[0]))
return NS_ERROR_XPC_BAD_CONVERT_JS;
JSObject *parent = JS_GetParent(cx, JSVAL_TO_OBJECT(argv[0]));
*rval = OBJECT_TO_JSVAL(parent);
- // Outerize if necessary. Embrace the ugliness!
+ // Outerize if necessary.
if (parent) {
- JSClass* clasp = JS_GET_CLASS(cx, parent);
- if (clasp->flags & JSCLASS_IS_EXTENDED) {
- JSExtendedClass* xclasp = reinterpret_cast<JSExtendedClass*>(clasp);
- if (JSObjectOp outerize = xclasp->outerObject)
- *rval = OBJECT_TO_JSVAL(outerize(cx, parent));
- }
+ if (JSObjectOp outerize = parent->getClass()->ext.outerObject)
+ *rval = OBJECT_TO_JSVAL(outerize(cx, parent));
}
cc->SetReturnValueWasSet(PR_TRUE);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetOuterWindowID(PRUint64 *aWindowID)
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -898,16 +898,30 @@ PrintWinCodebase(nsGlobalWindow *win)
void
DumpString(const nsAString &str)
{
printf("%s\n", NS_ConvertUTF16toUTF8(str).get());
}
#endif
+static void
+MaybeGC(JSContext *cx)
+{
+ size_t bytes = cx->runtime->gcBytes;
+ size_t lastBytes = cx->runtime->gcLastBytes;
+ if ((bytes > 8192 && bytes > lastBytes * 16)
+#ifdef DEBUG
+ || cx->runtime->gcZeal > 0
+#endif
+ ) {
+ JS_GC(cx);
+ }
+}
+
static already_AddRefed<nsIPrompt>
GetPromptFromContext(nsJSContext* ctx)
{
nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(ctx->GetGlobalObject()));
NS_ENSURE_TRUE(win, nsnull);
nsIDocShell *docShell = win->GetDocShell();
NS_ENSURE_TRUE(docShell, nsnull);
@@ -936,17 +950,17 @@ nsJSContext::DOMOperationCallback(JSCont
// XXX Save the operation callback time so we can restore it after the GC,
// because GCing can cause JS to run on our context, causing our
// ScriptEvaluated to be called, and clearing our operation callback time.
// See bug 302333.
PRTime callbackTime = ctx->mOperationCallbackTime;
PRTime modalStateTime = ctx->mModalStateTime;
- JS_MaybeGC(cx);
+ MaybeGC(cx);
// Now restore the callback time and count, in case they got reset.
ctx->mOperationCallbackTime = callbackTime;
ctx->mModalStateTime = modalStateTime;
// Check to see if we are running OOM
nsCOMPtr<nsIMemory> mem;
NS_GetMemoryManager(getter_AddRefs(mem));
@@ -3524,22 +3538,22 @@ nsJSContext::ScriptEvaluated(PRBool aTer
}
delete start;
}
mNumEvaluations++;
#ifdef JS_GC_ZEAL
if (mContext->runtime->gcZeal >= 2) {
- JS_MaybeGC(mContext);
+ MaybeGC(mContext);
} else
#endif
if (mNumEvaluations > 20) {
mNumEvaluations = 0;
- JS_MaybeGC(mContext);
+ MaybeGC(mContext);
}
if (aTerminated) {
mOperationCallbackTime = 0;
mModalStateTime = 0;
}
}
--- a/js/ipc/ObjectWrapperParent.cpp
+++ b/js/ipc/ObjectWrapperParent.cpp
@@ -164,46 +164,42 @@ with_error(JSContext* cx,
RType rval,
const char* error = NULL)
{
if (!JS_IsExceptionPending(cx))
JS_ReportError(cx, error ? error : "Unspecified CPOW error");
return rval;
}
-const JSExtendedClass ObjectWrapperParent::sCPOW_JSClass = {
- // JSClass (JSExtendedClass.base) initialization
- { "CrossProcessObjectWrapper",
- JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_IS_EXTENDED |
+const js::Class ObjectWrapperParent::sCPOW_JSClass = {
+ "CrossProcessObjectWrapper",
+ JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE |
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(sNumSlots),
- ObjectWrapperParent::CPOW_AddProperty,
- ObjectWrapperParent::CPOW_DelProperty,
- ObjectWrapperParent::CPOW_GetProperty,
- ObjectWrapperParent::CPOW_SetProperty,
+ js::Valueify(ObjectWrapperParent::CPOW_AddProperty),
+ js::Valueify(ObjectWrapperParent::CPOW_DelProperty),
+ js::Valueify(ObjectWrapperParent::CPOW_GetProperty),
+ js::Valueify(ObjectWrapperParent::CPOW_SetProperty),
(JSEnumerateOp) ObjectWrapperParent::CPOW_NewEnumerate,
- (JSResolveOp) ObjectWrapperParent::CPOW_NewResolve,
- ObjectWrapperParent::CPOW_Convert,
+ (JSResolveOp) ObjectWrapperParent::CPOW_NewResolve,
+ js::Valueify(ObjectWrapperParent::CPOW_Convert),
ObjectWrapperParent::CPOW_Finalize,
- nsnull, // getObjectOps
+ nsnull, // reserved1
nsnull, // checkAccess
- ObjectWrapperParent::CPOW_Call,
- ObjectWrapperParent::CPOW_Construct,
+ js::Valueify(ObjectWrapperParent::CPOW_Call),
+ js::Valueify(ObjectWrapperParent::CPOW_Construct),
nsnull, // xdrObject
- ObjectWrapperParent::CPOW_HasInstance,
+ js::Valueify(ObjectWrapperParent::CPOW_HasInstance),
nsnull, // mark
- nsnull, // reserveSlots
- },
-
- // JSExtendedClass initialization
- ObjectWrapperParent::CPOW_Equality,
- nsnull, // outerObject
- nsnull, // innerObject
- nsnull, // iterator
- nsnull, // wrappedObject
- JSCLASS_NO_RESERVED_MEMBERS
+ {
+ js::Valueify(ObjectWrapperParent::CPOW_Equality),
+ nsnull, // outerObject
+ nsnull, // innerObject
+ nsnull, // iteratorObject
+ nsnull, // wrappedObject
+ }
};
void
ObjectWrapperParent::ActorDestroy(ActorDestroyReason)
{
if (mObj) {
mObj->setPrivate(NULL);
mObj = NULL;
@@ -215,28 +211,28 @@ ObjectWrapperParent::Manager()
{
PContextWrapperParent* pcwp = PObjectWrapperParent::Manager();
return static_cast<ContextWrapperParent*>(pcwp);
}
JSObject*
ObjectWrapperParent::GetJSObject(JSContext* cx) const
{
- JSClass* clasp = const_cast<JSClass*>(&ObjectWrapperParent::sCPOW_JSClass.base);
- if (!mObj && (mObj = JS_NewObject(cx, clasp, NULL, NULL))) {
+ js::Class *clasp = const_cast<js::Class *>(&ObjectWrapperParent::sCPOW_JSClass);
+ if (!mObj && (mObj = JS_NewObject(cx, js::Jsvalify(clasp), NULL, NULL))) {
JS_SetPrivate(cx, mObj, (void*)this);
JS_SetReservedSlot(cx, mObj, sFlagsSlot, JSVAL_ZERO);
}
return mObj;
}
static ObjectWrapperParent*
Unwrap(JSContext* cx, JSObject* obj)
{
- while (obj->getJSClass() != &ObjectWrapperParent::sCPOW_JSClass.base)
+ while (obj->getClass() != &ObjectWrapperParent::sCPOW_JSClass)
if (!(obj = obj->getProto()))
return NULL;
ObjectWrapperParent* self =
static_cast<ObjectWrapperParent*>(JS_GetPrivate(cx, obj));
NS_ASSERTION(!self || self->GetJSObject(cx) == obj,
"Wrapper and wrapped object disagree?");
--- a/js/ipc/ObjectWrapperParent.h
+++ b/js/ipc/ObjectWrapperParent.h
@@ -38,16 +38,17 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_jsipc_ObjectWrapperParent_h__
#define mozilla_jsipc_ObjectWrapperParent_h__
#include "mozilla/jsipc/PObjectWrapperParent.h"
#include "jsapi.h"
+#include "jsvalue.h"
#include "nsAutoJSValHolder.h"
namespace mozilla {
namespace jsipc {
class ContextWrapperParent;
class OperationChecker {
@@ -70,17 +71,17 @@ public:
jsval GetJSVal(JSContext* cx) const {
return OBJECT_TO_JSVAL(GetJSObject(cx));
}
void CheckOperation(JSContext* cx,
OperationStatus* status);
- static const JSExtendedClass sCPOW_JSClass;
+ static const js::Class sCPOW_JSClass;
protected:
void ActorDestroy(ActorDestroyReason why);
ContextWrapperParent* Manager();
private:
--- a/js/jsd/jsd_val.c
+++ b/js/jsd/jsd_val.c
@@ -37,30 +37,17 @@
/*
* JavaScript Debugging support - Value and Property support
*/
#include "jsd.h"
#include "jsapi.h"
#include "jspubtd.h"
-
-/*
- * Lifted with slight modification from jsobj.h
- */
-
-#define OBJ_TO_OUTER_OBJECT(cx, obj) \
-do { \
- JSClass *clasp_ = JS_GetClass(cx, obj); \
- if (clasp_->flags & JSCLASS_IS_EXTENDED) { \
- JSExtendedClass *xclasp_ = (JSExtendedClass*) clasp_; \
- if (xclasp_->outerObject) \
- obj = xclasp_->outerObject(cx, obj); \
- } \
-} while(0)
+#include "jsprvtd.h"
#ifdef DEBUG
void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval)
{
JS_ASSERT(jsdval);
JS_ASSERT(jsdval->nref > 0);
if(!JS_CLIST_IS_EMPTY(&jsdval->props))
{
@@ -309,18 +296,17 @@ jsd_DropValue(JSDContext* jsdc, JSDValue
jsval
jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
{
JSObject* obj;
JSContext* cx;
jsval val = jsdval->val;
if (!JSVAL_IS_PRIMITIVE(val)) {
cx = JSD_GetDefaultJSContext(jsdc);
- obj = JSVAL_TO_OBJECT(val);
- OBJ_TO_OUTER_OBJECT(cx, obj);
+ obj = js_ObjectToOuterObject(cx, JSVAL_TO_OBJECT(val));
if (!obj)
{
JS_ClearPendingException(cx);
val = JSVAL_NULL;
}
else
val = OBJECT_TO_JSVAL(obj);
}
--- a/js/src/jsapi-tests/testExtendedEq.cpp
+++ b/js/src/jsapi-tests/testExtendedEq.cpp
@@ -1,42 +1,56 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99:
*
* This tests user-specified (via JSExtendedClass) equality operations on
* trace.
*/
#include "tests.h"
+#include "jsobj.h"
static JSBool
my_Equality(JSContext *cx, JSObject *obj, const jsval *, JSBool *bp)
{
*bp = JS_TRUE;
return JS_TRUE;
}
-JSExtendedClass TestExtendedEq_JSClass = {
- { "TestExtendedEq",
- JSCLASS_IS_EXTENDED,
- JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
- JS_EnumerateStub, JS_ResolveStub, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
- },
- // JSExtendedClass initialization
- my_Equality,
- NULL, NULL, NULL, NULL, JSCLASS_NO_RESERVED_MEMBERS
+js::Class TestExtendedEq_JSClass = {
+ "TestExtendedEq",
+ 0,
+ js::PropertyStub, /* addProperty */
+ js::PropertyStub, /* delProperty */
+ js::PropertyStub, /* getProperty */
+ js::PropertyStub, /* setProperty */
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ NULL, /* convert */
+ NULL, /* finalize */
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ NULL, /* mark */
+ {
+ js::Valueify(my_Equality),
+ NULL, /* outerObject */
+ NULL, /* innerObject */
+ NULL, /* iteratorObject */
+ NULL, /* wrappedObject */
+ }
};
BEGIN_TEST(testExtendedEq_bug530489)
{
JSClass *clasp = (JSClass *) &TestExtendedEq_JSClass;
- JSObject *global = JS_GetGlobalObject(cx);
CHECK(JS_InitClass(cx, global, global, clasp, NULL, 0, NULL, NULL, NULL, NULL));
CHECK(JS_DefineObject(cx, global, "obj1", clasp, NULL, 0));
CHECK(JS_DefineObject(cx, global, "obj2", clasp, NULL, 0));
jsval v;
EVAL("(function() { var r; for (var i = 0; i < 10; ++i) r = obj1 == obj2; return r; })()", &v);
CHECK_SAME(v, JSVAL_TRUE);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1337,21 +1337,20 @@ JS_InitStandardClasses(JSContext *cx, JS
#if JS_HAS_GENERATORS
js_InitIteratorClasses(cx, obj) &&
#endif
js_InitDateClass(cx, obj) &&
js_InitProxyClass(cx, obj);
}
#define CLASP(name) (&js_##name##Class)
-#define XCLASP(name) (&js_##name##Class.base)
+#define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type])
#define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
#define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
#define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
-#define EAGER_ATOM_AND_XCLASP(name) EAGER_CLASS_ATOM(name), XCLASP(name)
#define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
typedef struct JSStdName {
JSObjectOp init;
size_t atomOffset; /* offset of atom pointer in JSAtomState */
const char *name; /* null if atom is pre-pinned, else name */
Class *clasp;
} JSStdName;
@@ -1387,18 +1386,18 @@ static JSStdName standard_class_atoms[]
{js_InitDateClass, EAGER_ATOM_AND_CLASP(Date)},
{js_InitMathClass, EAGER_ATOM_AND_CLASP(Math)},
{js_InitNumberClass, EAGER_ATOM_AND_CLASP(Number)},
{js_InitStringClass, EAGER_ATOM_AND_CLASP(String)},
{js_InitExceptionClasses, EAGER_ATOM_AND_CLASP(Error)},
{js_InitRegExpClass, EAGER_ATOM_AND_CLASP(RegExp)},
#if JS_HAS_XML_SUPPORT
{js_InitXMLClass, EAGER_ATOM_AND_CLASP(XML)},
- {js_InitNamespaceClass, EAGER_ATOM_AND_XCLASP(Namespace)},
- {js_InitQNameClass, EAGER_ATOM_AND_XCLASP(QName)},
+ {js_InitNamespaceClass, EAGER_ATOM_AND_CLASP(Namespace)},
+ {js_InitQNameClass, EAGER_ATOM_AND_CLASP(QName)},
#endif
#if JS_HAS_GENERATORS
{js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(StopIteration)},
#endif
{js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)},
{js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::jsclass},
{NULL, 0, NULL, NULL}
};
@@ -1443,31 +1442,32 @@ static JSStdName standard_class_names[]
#if JS_HAS_XML_SUPPORT
{js_InitAnyNameClass, EAGER_ATOM_AND_CLASP(AnyName)},
{js_InitAttributeNameClass, EAGER_ATOM_AND_CLASP(AttributeName)},
{js_InitXMLClass, LAZY_ATOM(XMLList), CLASP(XML)},
{js_InitXMLClass, LAZY_ATOM(isXMLName), CLASP(XML)},
#endif
#if JS_HAS_GENERATORS
- {js_InitIteratorClasses, EAGER_ATOM_AND_XCLASP(Iterator)},
- {js_InitIteratorClasses, EAGER_ATOM_AND_XCLASP(Generator)},
+ {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Iterator)},
+ {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Generator)},
#endif
/* Typed Arrays */
{js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::jsclass},
- {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int8Array), &TypedArray::fastClasses[TypedArray::TYPE_INT8]},
- {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8Array), &TypedArray::fastClasses[TypedArray::TYPE_UINT8]},
- {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int16Array), &TypedArray::fastClasses[TypedArray::TYPE_INT16]},
- {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint16Array), &TypedArray::fastClasses[TypedArray::TYPE_UINT16]},
- {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int32Array), &TypedArray::fastClasses[TypedArray::TYPE_INT32]},
- {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint32Array), &TypedArray::fastClasses[TypedArray::TYPE_UINT32]},
- {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float32Array), &TypedArray::fastClasses[TypedArray::TYPE_FLOAT32]},
- {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float64Array), &TypedArray::fastClasses[TypedArray::TYPE_FLOAT64]},
- {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8ClampedArray), &TypedArray::fastClasses[TypedArray::TYPE_UINT8_CLAMPED]},
+ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int8Array), TYPED_ARRAY_CLASP(TYPE_INT8)},
+ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8Array), TYPED_ARRAY_CLASP(TYPE_UINT8)},
+ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int16Array), TYPED_ARRAY_CLASP(TYPE_INT16)},
+ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint16Array), TYPED_ARRAY_CLASP(TYPE_UINT16)},
+ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int32Array), TYPED_ARRAY_CLASP(TYPE_INT32)},
+ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint32Array), TYPED_ARRAY_CLASP(TYPE_UINT32)},
+ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float32Array), TYPED_ARRAY_CLASP(TYPE_FLOAT32)},
+ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float64Array), TYPED_ARRAY_CLASP(TYPE_FLOAT64)},
+ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8ClampedArray),
+ TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED)},
{js_InitProxyClass, EAGER_ATOM_AND_CLASP(Proxy)},
{NULL, 0, NULL, NULL}
};
static JSStdName object_prototype_names[] = {
/* Object.prototype properties (global delegates to Object.prototype). */
@@ -1854,17 +1854,17 @@ JS_PUBLIC_API(void)
JS_free(JSContext *cx, void *p)
{
return cx->free(p);
}
JS_PUBLIC_API(void)
JS_updateMallocCounter(JSContext *cx, size_t nbytes)
{
- cx->runtime->updateMallocCounter(nbytes);
+ return cx->updateMallocCounter(nbytes);
}
JS_PUBLIC_API(char *)
JS_strdup(JSContext *cx, const char *s)
{
size_t n;
void *p;
@@ -2450,26 +2450,75 @@ JS_GC(JSContext *cx)
JS_PUBLIC_API(void)
JS_MaybeGC(JSContext *cx)
{
JSRuntime *rt;
uint32 bytes, lastBytes;
rt = cx->runtime;
+#ifdef JS_GC_ZEAL
+ if (rt->gcZeal > 0) {
+ JS_GC(cx);
+ return;
+ }
+#endif
+
bytes = rt->gcBytes;
lastBytes = rt->gcLastBytes;
- if (rt->gcIsNeeded ||
-#ifdef JS_GC_ZEAL
- rt->gcZeal > 0 ||
-#endif
- (bytes > 8192 && bytes > lastBytes * 16) ||
- bytes >= rt->gcTriggerBytes ||
- rt->overQuota()) {
+ /*
+ * We run the GC if we used all available free GC cells and had to
+ * allocate extra 1/3 of GC arenas since the last run of GC, or if
+ * we have malloc'd more bytes through JS_malloc than we were told
+ * to allocate by JS_NewRuntime.
+ *
+ * The reason for
+ * bytes > 4/3 lastBytes
+ * condition is the following. Bug 312238 changed bytes and lastBytes
+ * to mean the total amount of memory that the GC uses now and right
+ * after the last GC.
+ *
+ * Before the bug the variables meant the size of allocated GC things
+ * now and right after the last GC. That size did not include the
+ * memory taken by free GC cells and the condition was
+ * bytes > 3/2 lastBytes.
+ * That is, we run the GC if we have half again as many bytes of
+ * GC-things as the last time we GC'd. To be compatible we need to
+ * express that condition through the new meaning of bytes and
+ * lastBytes.
+ *
+ * We write the original condition as
+ * B*(1-F) > 3/2 Bl*(1-Fl)
+ * where B is the total memory size allocated by GC and F is the free
+ * cell density currently and Sl and Fl are the size and the density
+ * right after GC. The density by definition is memory taken by free
+ * cells divided by total amount of memory. In other words, B and Bl
+ * are bytes and lastBytes with the new meaning and B*(1-F) and
+ * Bl*(1-Fl) are bytes and lastBytes with the original meaning.
+ *
+ * Our task is to exclude F and Fl from the last statement. According
+ * to the stats from bug 331966 comment 23, Fl is about 10-25% for a
+ * typical run of the browser. It means that the original condition
+ * implied that we did not run GC unless we exhausted the pool of
+ * free cells. Indeed if we still have free cells, then B == Bl since
+ * we did not yet allocated any new arenas and the condition means
+ * 1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F
+ * That implies 3/2 Fl > 1/2 or Fl > 1/3. That cannot be fulfilled
+ * for the state described by the stats. So we can write the original
+ * condition as:
+ * F == 0 && B > 3/2 Bl(1-Fl)
+ * Again using the stats we see that Fl is about 11% when the browser
+ * starts up and when we are far from hitting rt->gcMaxBytes. With
+ * this F we have
+ * F == 0 && B > 3/2 Bl(1-0.11)
+ * or approximately F == 0 && B > 4/3 Bl.
+ */
+ if ((bytes > 8192 && bytes > lastBytes + lastBytes / 3) ||
+ rt->isGCMallocLimitReached()) {
JS_GC(cx);
}
}
JS_PUBLIC_API(JSGCCallback)
JS_SetGCCallback(JSContext *cx, JSGCCallback cb)
{
CHECK_REQUEST(cx);
@@ -2580,17 +2629,17 @@ JS_NewExternalString(JSContext *cx, jsch
{
CHECK_REQUEST(cx);
JS_ASSERT(uintN(type) < JS_EXTERNAL_STRING_LIMIT);
JSString *str = js_NewGCExternalString(cx, uintN(type));
if (!str)
return NULL;
str->initFlat(chars, length);
- cx->runtime->updateMallocCounter((length + 1) * sizeof(jschar));
+ cx->updateMallocCounter((length + 1) * sizeof(jschar));
return str;
}
JS_PUBLIC_API(intN)
JS_GetExternalStringGCType(JSRuntime *rt, JSString *str)
{
/*
* No need to test this in js_GetExternalStringGCType, which asserts its
@@ -3702,18 +3751,22 @@ JS_DeleteProperty(JSContext *cx, JSObjec
}
JS_PUBLIC_API(void)
JS_ClearScope(JSContext *cx, JSObject *obj)
{
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
- if (obj->map->ops->clear)
- obj->map->ops->clear(cx, obj);
+ JSFinalizeOp clearOp = obj->getOps()->clear;
+ if (clearOp)
+ clearOp(cx, obj);
+
+ if (obj->isNative())
+ js_ClearNative(cx, obj);
/* Clear cached class objects on the global object. */
if (obj->getClass()->flags & JSCLASS_IS_GLOBAL) {
int key;
for (key = JSProto_Null; key < JSProto_LIMIT * 3; key++)
JS_SetReservedSlot(cx, obj, key, JSVAL_VOID);
}
@@ -3776,20 +3829,31 @@ prop_iter_trace(JSTracer *trc, JSObject
MarkIdRange(trc, ida->length, ida->vector, "prop iter");
}
}
static Class prop_iter_class = {
"PropertyIterator",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
JSCLASS_MARK_IS_TRACE,
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, prop_iter_finalize,
- NULL, NULL, NULL, NULL,
- NULL, NULL, JS_CLASS_TRACE(prop_iter_trace), NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ prop_iter_finalize,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ JS_CLASS_TRACE(prop_iter_trace)
};
JS_PUBLIC_API(JSObject *)
JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
{
JSObject *iterobj;
JSScope *scope;
void *pdata;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1601,16 +1601,17 @@ JS_SetScriptStackQuota(JSContext *cx, si
#define JS_DEFAULT_SCRIPT_STACK_QUOTA ((size_t) 0x2000000)
/************************************************************************/
/*
* Classes, objects, and properties.
*/
+typedef void (*JSClassInternal)();
/* For detailed comments on the function pointer types, see jspubtd.h. */
struct JSClass {
const char *name;
uint32 flags;
/* Mandatory non-null function pointer members. */
JSPropertyOp addProperty;
@@ -1618,38 +1619,26 @@ struct JSClass {
JSPropertyOp getProperty;
JSPropertyOp setProperty;
JSEnumerateOp enumerate;
JSResolveOp resolve;
JSConvertOp convert;
JSFinalizeOp finalize;
/* Optionally non-null members start here. */
- JSGetObjectOps getObjectOps;
+ JSClassInternal reserved0;
JSCheckAccessOp checkAccess;
JSNative call;
JSNative construct;
JSXDRObjectOp xdrObject;
JSHasInstanceOp hasInstance;
JSMarkOp mark;
- void (*reserved0)(void);
-};
-
-struct JSExtendedClass {
- JSClass base;
- JSEqualityOp equality;
- JSObjectOp outerObject;
- JSObjectOp innerObject;
- JSIteratorOp iteratorObject;
- JSObjectOp wrappedObject; /* NB: infallible, null
- returns are treated as
- the original object */
- void (*reserved0)(void);
- void (*reserved1)(void);
- void (*reserved2)(void);
+
+ JSClassInternal reserved1;
+ void *reserved[19];
};
#define JSCLASS_HAS_PRIVATE (1<<0) /* objects have private slot */
#define JSCLASS_NEW_ENUMERATE (1<<1) /* has JSNewEnumerateOp hook */
#define JSCLASS_NEW_RESOLVE (1<<2) /* has JSNewResolveOp hook */
#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) /* private is (nsISupports *) */
/* (1<<4) was JSCLASS_SHARE_ALL_PROPERTIES, now obsolete. See bug 527805. */
#define JSCLASS_NEW_RESOLVE_GETS_START (1<<5) /* JSNewResolveOp gets starting
@@ -1672,25 +1661,23 @@ struct JSExtendedClass {
<< JSCLASS_RESERVED_SLOTS_SHIFT)
#define JSCLASS_RESERVED_SLOTS(clasp) (((clasp)->flags \
>> JSCLASS_RESERVED_SLOTS_SHIFT) \
& JSCLASS_RESERVED_SLOTS_MASK)
#define JSCLASS_HIGH_FLAGS_SHIFT (JSCLASS_RESERVED_SLOTS_SHIFT + \
JSCLASS_RESERVED_SLOTS_WIDTH)
-/* True if JSClass is really a JSExtendedClass. */
-#define JSCLASS_IS_EXTENDED (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0))
+#define JSCLASS_INTERNAL_FLAG1 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0))
#define JSCLASS_IS_ANONYMOUS (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1))
#define JSCLASS_IS_GLOBAL (1<<(JSCLASS_HIGH_FLAGS_SHIFT+2))
/* Indicates that JSClass.mark is a tracer with JSTraceOp type. */
#define JSCLASS_MARK_IS_TRACE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
-
-#define JSCLASS_LAST_API_FLAG_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT+3)
+#define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
/*
* ECMA-262 requires that most constructors used internally create objects
* with "the original Foo.prototype value" as their [[Prototype]] (__proto__)
* member initial value. The "original ... value" verbiage is there because
* in ECMA-262, global properties naming class objects are read/write and
* deleteable, for the most part.
*
@@ -1710,18 +1697,18 @@ struct JSExtendedClass {
#define JSCLASS_CACHED_PROTO_MASK JS_BITMASK(JSCLASS_CACHED_PROTO_WIDTH)
#define JSCLASS_HAS_CACHED_PROTO(key) ((key) << JSCLASS_CACHED_PROTO_SHIFT)
#define JSCLASS_CACHED_PROTO_KEY(clasp) ((JSProtoKey) \
(((clasp)->flags \
>> JSCLASS_CACHED_PROTO_SHIFT) \
& JSCLASS_CACHED_PROTO_MASK))
/* Initializer for unused members of statically initialized JSClass structs. */
-#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,0
-#define JSCLASS_NO_RESERVED_MEMBERS 0,0,0
+#define JSCLASS_NO_INTERNAL_MEMBERS 0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
+#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,JSCLASS_NO_INTERNAL_MEMBERS
struct JSIdArray {
jsint length;
jsid vector[1]; /* actually, length jsid words */
};
extern JS_PUBLIC_API(void)
JS_DestroyIdArray(JSContext *cx, JSIdArray *ida);
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -979,17 +979,16 @@ array_finalize(JSContext *cx, JSObject *
{
obj->freeDenseArrayElements(cx);
}
static void
array_trace(JSTracer *trc, JSObject *obj)
{
JS_ASSERT(obj->isDenseArray());
- obj->traceProtoAndParent(trc);
if (!obj->dslots)
return;
size_t holes = 0;
uint32 capacity = obj->getDenseArrayCapacity();
for (uint32 i = 0; i < capacity; i++) {
Value v = obj->getDenseArrayElement(i);
@@ -1000,59 +999,63 @@ array_trace(JSTracer *trc, JSObject *obj
}
if (IS_GC_MARKING_TRACER(trc) && holes > MIN_SPARSE_INDEX && holes > capacity / 4 * 3) {
/* This might fail, in which case we don't slowify it. */
static_cast<GCMarker *>(trc)->arraysToSlowify.append(obj);
}
}
-extern JSObjectOps js_ArrayObjectOps;
-
-static const JSObjectMap SharedArrayMap(&js_ArrayObjectOps, JSObjectMap::SHAPELESS);
-
-JSObjectOps js_ArrayObjectOps = {
- &SharedArrayMap,
- array_lookupProperty,
- array_defineProperty,
- array_getProperty,
- array_setProperty,
- array_getAttributes,
- array_setAttributes,
- array_deleteProperty,
- js_Enumerate,
- array_typeOf,
- array_trace,
- NULL, /* thisObject */
- NULL /* clear */
-};
-
-static JSObjectOps *
-array_getObjectOps(JSContext *cx, Class *clasp)
-{
- return &js_ArrayObjectOps;
-}
-
Class js_ArrayClass = {
"Array",
+ Class::NON_NATIVE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::DENSE_ARRAY_FIXED_RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, js_TryValueOf, array_finalize,
- array_getObjectOps, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ js_TryValueOf,
+ array_finalize,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ NULL, /* mark */
+ JS_NULL_CLASS_EXT,
+ {
+ array_lookupProperty,
+ array_defineProperty,
+ array_getProperty,
+ array_setProperty,
+ array_getAttributes,
+ array_setAttributes,
+ array_deleteProperty,
+ NULL, /* enumerate */
+ array_typeOf,
+ array_trace,
+ NULL, /* thisObject */
+ NULL, /* clear */
+ }
};
Class js_SlowArrayClass = {
"Array",
- JSCLASS_HAS_PRIVATE |
- JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
- slowarray_addProperty, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, js_TryValueOf, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
+ slowarray_addProperty,
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ js_TryValueOf
};
/*
* Convert an array object from fast-and-dense to slow-and-flexible.
*/
JSBool
JSObject::makeDenseArraySlow(JSContext *cx)
{
@@ -1068,17 +1071,17 @@ JSObject::makeDenseArraySlow(JSContext *
if (arrayProto->getClass() == &js_ObjectClass) {
/* obj is Array.prototype. */
emptyShape = js_GenerateShape(cx, false);
} else {
/* arrayProto is Array.prototype. */
JS_ASSERT(arrayProto->getClass() == &js_SlowArrayClass);
emptyShape = arrayProto->scope()->emptyScope->shape;
}
- JSScope *scope = JSScope::create(cx, &js_ObjectOps, &js_SlowArrayClass, obj, emptyShape);
+ JSScope *scope = JSScope::create(cx, &js_SlowArrayClass, obj, emptyShape);
if (!scope)
return JS_FALSE;
uint32 capacity = obj->getDenseArrayCapacity();
/* For a brief moment the object has NULL dslots until we slowify it during construction. */
if (obj->dslots)
obj->dslots[-1].setPrivateUint32(JS_INITIAL_NSLOTS + capacity);
@@ -2987,17 +2990,17 @@ js_NewEmptyArray(JSContext* cx, JSObject
JS_ASSERT(proto->isArray());
JSObject* obj = js_NewGCObject(cx);
if (!obj)
return NULL;
/* Initialize all fields of JSObject. */
- obj->map = const_cast<JSObjectMap *>(&SharedArrayMap);
+ obj->map = const_cast<JSObjectMap *>(&JSObjectMap::sharedNonNative);
obj->init(&js_ArrayClass, proto, proto->getParent(), NullValue());
obj->setArrayLength(len);
obj->setDenseArrayCapacity(0);
return obj;
}
#ifdef JS_TRACER
JS_DEFINE_CALLINFO_3(extern, OBJECT, js_NewEmptyArray, CONTEXT, OBJECT, INT32, 0,
nanojit::ACCSET_STORE_ANY)
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -51,25 +51,28 @@
#include "jslock.h"
#include "jsnum.h"
#include "jsobj.h"
#include "jsstr.h"
#include "jsvector.h"
#include "jsobjinlines.h"
-
using namespace js;
Class js_BooleanClass = {
"Boolean",
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub
};
#if JS_HAS_TOSOURCE
#include "jsprf.h"
static JSBool
bool_toSource(JSContext *cx, uintN argc, Value *vp)
{
--- a/js/src/jsbuiltins.cpp
+++ b/js/src/jsbuiltins.cpp
@@ -251,17 +251,17 @@ js_AddAtomProperty(JSContext* cx, JSObje
JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddAtomProperty, CONTEXT, OBJECT, SCOPEPROP,
0, ACCSET_STORE_ANY)
static JSBool
HasProperty(JSContext* cx, JSObject* obj, jsid id)
{
// Check that we know how the lookup op will behave.
for (JSObject* pobj = obj; pobj; pobj = pobj->getProto()) {
- if (pobj->map->ops->lookupProperty != js_LookupProperty)
+ if (pobj->getOps()->lookupProperty)
return JS_NEITHER;
Class* clasp = pobj->getClass();
if (clasp->resolve != JS_ResolveStub && clasp != &js_StringClass)
return JS_NEITHER;
}
JSObject* obj2;
JSProperty* prop;
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -742,16 +742,17 @@ js_PurgeThreads(JSContext *cx)
* The following is potentially suboptimal as it also zeros the
* caches in data, but the code simplicity wins here.
*/
thread->data.gcFreeLists.purge();
DestroyThread(thread);
e.removeFront();
} else {
thread->data.purge(cx);
+ thread->gcThreadMallocBytes = JS_GC_THREAD_MALLOC_LIMIT;
}
}
#else
cx->runtime->threadData.purge(cx);
#endif
}
/*
@@ -1905,46 +1906,53 @@ js_InvokeOperationCallback(JSContext *cx
* Reset the callback flag first, then yield. If another thread is racing
* us here we will accumulate another callback request which will be
* serviced at the next opportunity.
*/
JS_ATOMIC_CLEAR_MASK(&JS_THREAD_DATA(cx)->interruptFlags,
JSThreadData::INTERRUPT_OPERATION_CALLBACK);
/*
- * Ideally this should never be hit. The embedding should call JS_MaybeGC()
- * to schedule preemptive GCs.
+ * Unless we are going to run the GC, we automatically yield the current
+ * context every time the operation callback is hit since we might be
+ * called as a result of an impending GC, which would deadlock if we do
+ * not yield. Operation callbacks are supposed to happen rarely (seconds,
+ * not milliseconds) so it is acceptable to yield at every callback.
*/
JSRuntime *rt = cx->runtime;
- if (rt->gcIsNeeded || rt->overQuota()) {
- JS_GC(cx);
- /* If we are still over quota after the GC, report an error. */
- if (rt->overQuota()) {
+ if (rt->gcIsNeeded) {
+ js_GC(cx, GC_NORMAL);
+
+ /*
+ * On trace we can exceed the GC quota, see comments in NewGCArena. So
+ * we check the quota and report OOM here when we are off trace.
+ */
+ bool delayedOutOfMemory;
+ JS_LOCK_GC(rt);
+ delayedOutOfMemory = (rt->gcBytes > rt->gcMaxBytes);
+ JS_UNLOCK_GC(rt);
+ if (delayedOutOfMemory) {
js_ReportOutOfMemory(cx);
return false;
}
}
+#ifdef JS_THREADSAFE
+ else {
+ JS_YieldRequest(cx);
+ }
+#endif
- /*
- * Automatically yield the current context every time the operation callback
- * is hit since we might be called as a result of an impending GC, which
- * would deadlock if we do not yield. Operation callbacks are supposed to
- * happen rarely (seconds, not milliseconds) so it is acceptable to yield at
- * every callback.
- */
-#ifdef JS_THREADSAFE
- JS_YieldRequest(cx);
-#endif
+ JSOperationCallback cb = cx->operationCallback;
/*
* Important: Additional callbacks can occur inside the callback handler
* if it re-enters the JS engine. The embedding must ensure that the
* callback is disconnected before attempting such re-entry.
*/
- JSOperationCallback cb = cx->operationCallback;
+
return !cb || cb(cx);
}
JSBool
js_HandleExecutionInterrupt(JSContext *cx)
{
JSBool result = JS_TRUE;
if (JS_THREAD_DATA(cx)->interruptFlags & JSThreadData::INTERRUPT_OPERATION_CALLBACK)
@@ -2172,16 +2180,57 @@ JSContext::containingSegment(const JSSta
if (f == target)
return css;
}
}
return NULL;
}
+void
+JSContext::checkMallocGCPressure(void *p)
+{
+ if (!p) {
+ js_ReportOutOfMemory(this);
+ return;
+ }
+
+#ifdef JS_THREADSAFE
+ JS_ASSERT(thread);
+ JS_ASSERT(thread->gcThreadMallocBytes <= 0);
+ ptrdiff_t n = JS_GC_THREAD_MALLOC_LIMIT - thread->gcThreadMallocBytes;
+ thread->gcThreadMallocBytes = JS_GC_THREAD_MALLOC_LIMIT;
+
+ AutoLockGC lock(runtime);
+ runtime->gcMallocBytes -= n;
+
+ /*
+ * Trigger the GC on memory pressure but only if we are inside a request
+ * and not inside a GC.
+ */
+ if (runtime->isGCMallocLimitReached() && requestDepth != 0)
+#endif
+ {
+ if (!runtime->gcRunning) {
+ JS_ASSERT(runtime->isGCMallocLimitReached());
+ runtime->gcMallocBytes = -1;
+
+ /*
+ * Empty the GC free lists to trigger a last-ditch GC when any GC
+ * thing is allocated later on this thread. This makes unnecessary
+ * to check for the memory pressure on the fast path of the GC
+ * allocator. We cannot touch the free lists on other threads as
+ * their manipulation is not thread-safe.
+ */
+ JS_THREAD_DATA(this)->gcFreeLists.purge();
+ js_TriggerGC(this, true);
+ }
+ }
+}
+
bool
JSContext::isConstructing()
{
#ifdef JS_TRACER
if (JS_ON_TRACE(this)) {
JS_ASSERT(bailExit);
return *bailExit->pc == JSOP_NEW;
}
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1012,16 +1012,23 @@ struct JSThreadData {
volatile jsword interruptFlags;
JSGCFreeLists gcFreeLists;
/* Keeper of the contiguous stack used by all contexts in this thread. */
js::StackSpace stackSpace;
/*
+ * Flag indicating that we are waiving any soft limits on the GC heap
+ * because we want allocations to be infallible (except when we hit
+ * a hard quota).
+ */
+ bool waiveGCQuota;
+
+ /*
* The GSN cache is per thread since even multi-cx-per-thread embeddings
* do not interleave js_GetSrcNote calls.
*/
JSGSNCache gsnCache;
/* Property cache for faster call/get/set invocation. */
js::PropertyCache propertyCache;
@@ -1101,16 +1108,22 @@ struct JSThread {
/* Opaque thread-id, from NSPR's PR_GetCurrentThread(). */
void *id;
/* Indicates that the thread is waiting in ClaimTitle from jslock.cpp. */
JSTitle *titleToShare;
/*
+ * Thread-local version of JSRuntime.gcMallocBytes to avoid taking
+ * locks on each JS_malloc.
+ */
+ ptrdiff_t gcThreadMallocBytes;
+
+ /*
* This thread is inside js_GC, either waiting until it can start GC, or
* waiting for GC to finish on another thread. This thread holds no locks;
* other threads may steal titles from it.
*
* Protected by rt->gcLock.
*/
bool gcWaiting;
@@ -1118,16 +1131,23 @@ struct JSThread {
* The context running the requests.
*/
JSContext *requestContext;
/* Factored out of JSThread for !JS_THREADSAFE embedding in JSRuntime. */
JSThreadData data;
};
+/*
+ * Only when JSThread::gcThreadMallocBytes exhausts the following limit we
+ * update JSRuntime::gcMallocBytes.
+ * .
+ */
+const size_t JS_GC_THREAD_MALLOC_LIMIT = 1 << 19;
+
#define JS_THREAD_DATA(cx) (&(cx)->thread->data)
extern JSThread *
js_CurrentThread(JSRuntime *rt);
/*
* The function takes the GC lock and does not release in successful return.
* On error (out of memory) the function releases the lock but delegates
@@ -1282,19 +1302,16 @@ struct JSCompartment {
bool wrap(JSContext *cx, js::PropertyOp *op);
bool wrap(JSContext *cx, js::PropertyDescriptor *desc);
bool wrap(JSContext *cx, js::AutoIdVector &props);
bool wrapException(JSContext *cx);
void sweep(JSContext *cx);
};
-extern JS_FRIEND_API(void)
-js_TriggerAllOperationCallbacks(JSRuntime *rt, JSBool gcLocked);
-
struct JSRuntime {
/* Default compartment. */
JSCompartment *defaultCompartment;
/* List of compartments (protected by the GC lock). */
js::Vector<JSCompartment *, 0, js::SystemAllocPolicy> compartments;
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
@@ -1368,17 +1385,17 @@ struct JSRuntime {
#endif
JSGCCallback gcCallback;
/*
* Malloc counter to measure memory pressure for GC scheduling. It runs
* from gcMaxMallocBytes down to zero.
*/
- volatile ptrdiff_t gcMallocBytes;
+ ptrdiff_t gcMallocBytes;
#ifdef JS_THREADSAFE
JSBackgroundThread gcHelperThread;
#endif
js::GCChunkAllocator *gcChunkAllocator;
void setCustomGCChunkAllocator(js::GCChunkAllocator *allocator) {
@@ -1653,57 +1670,29 @@ struct JSRuntime {
JSWrapObjectCallback wrapObjectCallback;
JSRuntime();
~JSRuntime();
bool init(uint32 maxbytes);
- inline void triggerGC(bool gcLocked) {
- if (!gcIsNeeded) {
- gcIsNeeded = true;
- js_TriggerAllOperationCallbacks(this, gcLocked);
- }
- }
-
void setGCTriggerFactor(uint32 factor);
void setGCLastBytes(size_t lastBytes);
- bool gcQuotaReached() {
- return gcBytes >= gcMaxBytes;
- }
-
- void updateMallocCounter(size_t bytes) {
- /* We tolerate races and lost counts here. */
- if ((gcMallocBytes -= bytes) <= 0)
- triggerGC(false);
- }
-
- bool mallocQuotaReached() {
- return gcMallocBytes <= 0;
- }
-
- bool overQuota() {
- return gcQuotaReached() || mallocQuotaReached();
- }
-
- void* malloc(size_t bytes) { updateMallocCounter(bytes); return ::js_malloc(bytes); }
-
- void* calloc(size_t bytes) { updateMallocCounter(bytes); return ::js_calloc(bytes); }
-
- void* realloc(void* p, size_t bytes) {
- void* q = ::js_realloc(p, bytes);
- if (p != q)
- updateMallocCounter(bytes);
- return q;
- }
+ void* malloc(size_t bytes) { return ::js_malloc(bytes); }
+
+ void* calloc(size_t bytes) { return ::js_calloc(bytes); }
+
+ void* realloc(void* p, size_t bytes) { return ::js_realloc(p, bytes); }
void free(void* p) { ::js_free(p); }
+ bool isGCMallocLimitReached() const { return gcMallocBytes <= 0; }
+
void resetGCMallocBytes() { gcMallocBytes = ptrdiff_t(gcMaxMallocBytes); }
void setGCMaxMallocBytes(size_t value) {
/*
* For compatibility treat any value that exceeds PTRDIFF_T_MAX to
* mean that value.
*/
gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
@@ -1788,19 +1777,16 @@ struct JSRegExpStatics {
JSRegExpStatics(JSContext *cx) : cx(cx), parens(cx) {}
bool copy(const JSRegExpStatics& other);
void clearRoots();
void clear();
};
-extern JS_FRIEND_API(void)
-js_ReportOutOfMemory(JSContext *cx);
-
struct JSContext
{
explicit JSContext(JSRuntime *rt);
/* JSRuntime contextList linkage. */
JSCList link;
/* Runtime version control identifier. */
@@ -2077,39 +2063,86 @@ struct JSContext
#ifdef JS_THREADSAFE
/*
* The sweep task for this context.
*/
js::BackgroundSweepTask *gcSweepTask;
#endif
- inline void *reportIfOutOfMemory(void *p) {
- if (!p)
- js_ReportOutOfMemory(this);
- return p;
+ ptrdiff_t &getMallocCounter() {
+#ifdef JS_THREADSAFE
+ return thread->gcThreadMallocBytes;
+#else
+ return runtime->gcMallocBytes;
+#endif
+ }
+
+ /*
+ * Call this after allocating memory held by GC things, to update memory
+ * pressure counters or report the OOM error if necessary.
+ */
+ inline void updateMallocCounter(void *p, size_t nbytes) {
+ JS_ASSERT(ptrdiff_t(nbytes) >= 0);
+ ptrdiff_t &counter = getMallocCounter();
+ counter -= ptrdiff_t(nbytes);
+ if (!p || counter <= 0)
+ checkMallocGCPressure(p);
+ }
+
+ /*
+ * Call this after successfully allocating memory held by GC things, to
+ * update memory pressure counters.
+ */
+ inline void updateMallocCounter(size_t nbytes) {
+ JS_ASSERT(ptrdiff_t(nbytes) >= 0);
+ ptrdiff_t &counter = getMallocCounter();
+ counter -= ptrdiff_t(nbytes);
+ if (counter <= 0) {
+ /*
+ * Use 1 as an arbitrary non-null pointer indicating successful
+ * allocation.
+ */
+ checkMallocGCPressure(reinterpret_cast<void *>(jsuword(1)));
+ }
}
inline void* malloc(size_t bytes) {
JS_ASSERT(bytes != 0);
- return reportIfOutOfMemory(runtime->malloc(bytes));
+ void *p = runtime->malloc(bytes);
+ updateMallocCounter(p, bytes);
+ return p;
}
inline void* mallocNoReport(size_t bytes) {
JS_ASSERT(bytes != 0);
- return runtime->malloc(bytes);
+ void *p = runtime->malloc(bytes);
+ if (!p)
+ return NULL;
+ updateMallocCounter(bytes);
+ return p;
}
inline void* calloc(size_t bytes) {
JS_ASSERT(bytes != 0);
- return reportIfOutOfMemory(runtime->calloc(bytes));
+ void *p = runtime->calloc(bytes);
+ updateMallocCounter(p, bytes);
+ return p;
}
inline void* realloc(void* p, size_t bytes) {
- return reportIfOutOfMemory(runtime->realloc(p, bytes));
+ void *orig = p;
+ p = runtime->realloc(p, bytes);
+
+ /*
+ * For compatibility we do not account for realloc that increases
+ * previously allocated memory.
+ */
+ updateMallocCounter(p, orig ? 0 : bytes);
+ return p;
}
inline void free(void* p) {
#ifdef JS_THREADSAFE
if (gcSweepTask) {
gcSweepTask->freeLater(p);
return;
}
@@ -2166,16 +2199,26 @@ struct JSContext
#ifdef DEBUG
void assertValidStackDepth(uintN depth) {
JS_ASSERT(0 <= regs->sp - fp->base());
JS_ASSERT(depth <= uintptr_t(regs->sp - fp->base()));
}
#else
void assertValidStackDepth(uintN /*depth*/) {}
#endif
+
+private:
+
+ /*
+ * The allocation code calls the function to indicate either OOM failure
+ * when p is null or that a memory pressure counter has reached some
+ * threshold when p is not null. The function takes the pointer and not
+ * a boolean flag to minimize the amount of code in its inlined callers.
+ */
+ JS_FRIEND_API(void) checkMallocGCPressure(void *p);
};
JS_ALWAYS_INLINE JSObject *
JSStackFrame::varobj(js::CallStackSegment *css) const
{
JS_ASSERT(css->contains(this));
return fun ? callobj : css->getInitialVarObj();
}
@@ -2924,16 +2967,19 @@ js_ReportErrorNumberVA(JSContext *cx, ui
extern JSBool
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
void *userRef, const uintN errorNumber,
char **message, JSErrorReport *reportp,
bool charArgs, va_list ap);
#endif
+extern void
+js_ReportOutOfMemory(JSContext *cx);
+
/*
* Report that cx->scriptStackQuota is exhausted.
*/
void
js_ReportOutOfScriptQuota(JSContext *cx);
extern void
js_ReportOverRecursed(JSContext *cx);
@@ -3025,16 +3071,25 @@ extern JSErrorFormatString js_ErrorForma
* is to be terminated.
*/
extern JSBool
js_InvokeOperationCallback(JSContext *cx);
extern JSBool
js_HandleExecutionInterrupt(JSContext *cx);
+
+#ifndef JS_THREADSAFE
+# define js_TriggerAllOperationCallbacks(rt, gcLocked) \
+ js_TriggerAllOperationCallbacks (rt)
+#endif
+
+void
+js_TriggerAllOperationCallbacks(JSRuntime *rt, JSBool gcLocked);
+
extern JSStackFrame *
js_GetScriptedCaller(JSContext *cx, JSStackFrame *fp);
extern jsbytecode*
js_GetCurrentBytecodePC(JSContext* cx);
extern bool
js_CurrentPCIsInImacro(JSContext *cx);
@@ -3060,17 +3115,17 @@ LeaveTrace(JSContext *cx)
if (JS_ON_TRACE(cx))
DeepBail(cx);
#endif
}
static JS_INLINE void
LeaveTraceIfGlobalObject(JSContext *cx, JSObject *obj)
{
- if (obj->fslots[JSSLOT_PARENT].isNull())
+ if (!obj->parent)
LeaveTrace(cx);
}
static JS_INLINE JSBool
CanLeaveTrace(JSContext *cx)
{
JS_ASSERT(JS_ON_TRACE(cx));
#ifdef JS_TRACER
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -480,19 +480,23 @@ msFromTime(jsdouble t)
/*
* Other Support routines and definitions
*/
Class js_DateClass = {
js_Date_str,
JSCLASS_HAS_RESERVED_SLOTS(JSObject::DATE_FIXED_RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub
};
/* for use by date_parse */
static const char* wtb[] = {
"am", "pm",
"monday", "tuesday", "wednesday", "thursday", "friday",
"saturday", "sunday",
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -83,20 +83,31 @@ exn_enumerate(JSContext *cx, JSObject *o
static JSBool
exn_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
JSObject **objp);
Class js_ErrorClass = {
js_Error_str,
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_MARK_IS_TRACE |
JSCLASS_HAS_CACHED_PROTO(JSProto_Error),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- exn_enumerate, (JSResolveOp)exn_resolve, ConvertStub, exn_finalize,
- NULL, NULL, NULL, Exception,
- NULL, NULL, JS_CLASS_TRACE(exn_trace), NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ exn_enumerate,
+ (JSResolveOp)exn_resolve,
+ ConvertStub,
+ exn_finalize,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ Exception, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ JS_CLASS_TRACE(exn_trace)
};
typedef struct JSStackTraceElem {
JSString *funName;
size_t argc;
const char *filename;
uintN ulineno;
} JSStackTraceElem;
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -683,40 +683,51 @@ args_or_call_trace(JSTracer *trc, JSObje
* in a JSStackFrame with their corresponding property values in the frame's
* arguments object.
*/
Class js_ArgumentsClass = {
"Arguments",
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::ARGS_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
- PropertyStub, args_delProperty,
- PropertyStub, PropertyStub,
- args_enumerate, (JSResolveOp) args_resolve,
- ConvertStub, NULL,
- NULL, NULL,
- NULL, NULL,
- NULL, NULL,
- JS_CLASS_TRACE(args_or_call_trace), NULL
+ PropertyStub, /* addProperty */
+ args_delProperty,
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ args_enumerate,
+ (JSResolveOp) args_resolve,
+ ConvertStub,
+ NULL, /* finalize */
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ JS_CLASS_TRACE(args_or_call_trace)
};
const uint32 JSSLOT_CALLEE = JSSLOT_PRIVATE + 1;
const uint32 JSSLOT_CALL_ARGUMENTS = JSSLOT_PRIVATE + 2;
const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS = 2;
/*
* A Declarative Environment object stores its active JSStackFrame pointer in
* its private slot, just as Call and Arguments objects do.
*/
Class js_DeclEnvClass = {
js_Object_str,
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub
};
static JSBool
CheckForEscapingClosure(JSContext *cx, JSObject *obj, Value *vp)
{
JS_ASSERT(obj->getClass() == &js_CallClass ||
obj->getClass() == &js_DeclEnvClass);
@@ -1264,24 +1275,31 @@ call_resolve(JSContext *cx, JSObject *ob
return JS_TRUE;
}
JS_PUBLIC_DATA(Class) js_CallClass = {
"Call",
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(CALL_CLASS_FIXED_RESERVED_SLOTS) |
JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS | JSCLASS_MARK_IS_TRACE,
- PropertyStub, PropertyStub,
- PropertyStub, PropertyStub,
- call_enumerate, (JSResolveOp)call_resolve,
- NULL, NULL,
- NULL, NULL,
- NULL, NULL,
- NULL, NULL,
- JS_CLASS_TRACE(args_or_call_trace), NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ call_enumerate,
+ (JSResolveOp)call_resolve,
+ NULL, /* convert */
+ NULL, /* finalize */
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ JS_CLASS_TRACE(args_or_call_trace)
};
bool
JSStackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
{
if (!fun) {
*vp = argv ? argv[-2] : UndefinedValue();
return true;
@@ -1907,24 +1925,31 @@ JSFunction::countInterpretedReservedSlot
* does not bloat every instance, only those on which reserved slots are set,
* and those on which ad-hoc properties are defined.
*/
JS_PUBLIC_DATA(Class) js_FunctionClass = {
js_Function_str,
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::FUN_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
- PropertyStub, PropertyStub,
- PropertyStub, PropertyStub,
- fun_enumerate, (JSResolveOp)fun_resolve,
- ConvertStub, fun_finalize,
- NULL, NULL,
- NULL, NULL,
- js_XDRFunctionObject, fun_hasInstance,
- JS_CLASS_TRACE(fun_trace), NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ fun_enumerate,
+ (JSResolveOp)fun_resolve,
+ ConvertStub,
+ fun_finalize,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ js_XDRFunctionObject,
+ fun_hasInstance,
+ JS_CLASS_TRACE(fun_trace)
};
namespace js {
JSString *
fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent)
{
if (!obj->isFunction()) {
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -632,29 +632,39 @@ ReleaseGCChunk(JSRuntime *rt, jsuword ch
METER(rt->gcStats.nchunks--);
rt->gcChunkAllocator->free(p);
}
static JSGCArena *
NewGCArena(JSContext *cx)
{
JSRuntime *rt = cx->runtime;
+ if (!JS_THREAD_DATA(cx)->waiveGCQuota && rt->gcBytes >= rt->gcMaxBytes) {
+ /*
+ * FIXME bug 524051 We cannot run a last-ditch GC on trace for now, so
+ * just pretend we are out of memory which will throw us off trace and
+ * we will re-try this code path from the interpreter.
+ */
+ if (!JS_ON_TRACE(cx))
+ return NULL;
+ js_TriggerGC(cx, true);
+ }
size_t nchunks = rt->gcChunks.length();
+
JSGCChunkInfo *ci;
for (;; ++rt->gcChunkCursor) {
if (rt->gcChunkCursor == nchunks) {
ci = NULL;
break;
}
ci = rt->gcChunks[rt->gcChunkCursor];
if (ci->numFreeArenas != 0)
break;
}
-
if (!ci) {
if (!rt->gcChunks.reserve(nchunks + 1))
return NULL;
void *chunkptr = GetGCChunk(rt);
if (!chunkptr)
return NULL;
ci = JSGCChunkInfo::fromChunk(reinterpret_cast<jsuword>(chunkptr));
ci->init(rt);
@@ -1688,55 +1698,107 @@ JSGCFreeLists::purge()
void
JSGCFreeLists::moveTo(JSGCFreeLists *another)
{
*another = *this;
PodArrayZero(finalizables);
JS_ASSERT(isEmpty());
}
+static inline bool
+IsGCThresholdReached(JSRuntime *rt)
+{
+#ifdef JS_GC_ZEAL
+ if (rt->gcZeal >= 1)
+ return true;
+#endif
+
+ /*
+ * Since the initial value of the gcLastBytes parameter is not equal to
+ * zero (see the js_InitGC function) the return value is false when
+ * the gcBytes value is close to zero at the JS engine start.
+ */
+ return rt->isGCMallocLimitReached() || rt->gcBytes >= rt->gcTriggerBytes;
+}
+
+static void
+LastDitchGC(JSContext *cx)
+{
+ JS_ASSERT(!JS_ON_TRACE(cx));
+
+ /* The last ditch GC preserves weak roots and all atoms. */
+ AutoPreserveWeakRoots save(cx);
+ AutoKeepAtoms keep(cx->runtime);
+
+ /*
+ * Keep rt->gcLock across the call into the GC so we don't starve and
+ * lose to racing threads who deplete the heap just after the GC has
+ * replenished it (or has synchronized with a racing GC that collected a
+ * bunch of garbage). This unfair scheduling can happen on certain
+ * operating systems. For the gory details, see bug 162779.
+ */
+ js_GC(cx, GC_LOCK_HELD);
+}
+
static JSGCThing *
RefillFinalizableFreeList(JSContext *cx, unsigned thingKind)
{
JS_ASSERT(!JS_THREAD_DATA(cx)->gcFreeLists.finalizables[thingKind]);
JSRuntime *rt = cx->runtime;
JSGCArenaList *arenaList;
JSGCArena *a;
{
AutoLockGC lock(rt);
JS_ASSERT(!rt->gcRunning);
if (rt->gcRunning) {
METER(rt->gcStats.finalfail++);
return NULL;
}
+ bool canGC = !JS_ON_TRACE(cx) && !JS_THREAD_DATA(cx)->waiveGCQuota;
+ bool doGC = canGC && IsGCThresholdReached(rt);
arenaList = &rt->gcArenaList[thingKind];
- while ((a = arenaList->cursor) != NULL) {
- JSGCArenaInfo *ainfo = a->getInfo();
- arenaList->cursor = ainfo->prev;
- JSGCThing *freeList = ainfo->freeList;
- if (freeList) {
- ainfo->freeList = NULL;
- return freeList;
+ for (;;) {
+ if (doGC) {
+ LastDitchGC(cx);
+ METER(cx->runtime->gcStats.arenaStats[thingKind].retry++);
+ canGC = false;
+
+ /*
+ * The JSGC_END callback can legitimately allocate new GC
+ * things and populate the free list. If that happens, just
+ * return that list head.
+ */
+ JSGCThing *freeList = JS_THREAD_DATA(cx)->gcFreeLists.finalizables[thingKind];
+ if (freeList)
+ return freeList;
}
+
+ while ((a = arenaList->cursor) != NULL) {
+ JSGCArenaInfo *ainfo = a->getInfo();
+ arenaList->cursor = ainfo->prev;
+ JSGCThing *freeList = ainfo->freeList;
+ if (freeList) {
+ ainfo->freeList = NULL;
+ return freeList;
+ }
+ }
+
+ a = NewGCArena(cx);
+ if (a)
+ break;
+ if (!canGC) {
+ METER(cx->runtime->gcStats.arenaStats[thingKind].fail++);
+ return NULL;
+ }
+ doGC = true;
}
/*
- * If we have to allocate a new arena, check whether are bumping
- * against our GC heap quota. If so, request a GC to happen soon.
- */
- if (rt->gcQuotaReached())
- cx->runtime->triggerGC(true);
-
- a = NewGCArena(cx);
- if (!a)
- return NULL;
-
- /*
* Do only minimal initialization of the arena inside the GC lock. We
* can do the rest outside the lock because no other threads will see
* the arena until the GC is run.
*/
JSGCArenaInfo *ainfo = a->getInfo();
ainfo->list = arenaList;
ainfo->prev = arenaList->head;
ainfo->freeList = NULL;
@@ -1850,17 +1912,22 @@ JS_PUBLIC_API(void)
JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind)
{
switch (kind) {
case JSTRACE_OBJECT: {
/* If obj has no map, it must be a newborn. */
JSObject *obj = (JSObject *) thing;
if (!obj->map)
break;
- obj->map->ops->trace(trc, obj);
+ if (JSObject *proto = obj->getProto())
+ JS_CALL_OBJECT_TRACER(trc, proto, "proto");
+ if (JSObject *parent = obj->getParent())
+ JS_CALL_OBJECT_TRACER(trc, parent, "parent");
+ JSTraceOp op = obj->getOps()->trace;
+ (op ? op : js_TraceObject)(trc, obj);
break;
}
case JSTRACE_STRING: {
JSString *str = (JSString *) thing;
if (str->isDependent())
JS_CALL_STRING_TRACER(trc, str->dependentBase(), "base");
else if (str->isRope()) {
@@ -2453,16 +2520,36 @@ js_TraceRuntime(JSTracer *trc)
JS_CALL_OBJECT_TRACER(trc, fun, "FunctionCountMap key");
}
}
}
#endif
}
void
+js_TriggerGC(JSContext *cx, JSBool gcLocked)
+{
+ JSRuntime *rt = cx->runtime;
+
+#ifdef JS_THREADSAFE
+ JS_ASSERT(cx->requestDepth > 0);
+#endif
+ JS_ASSERT(!rt->gcRunning);
+ if (rt->gcIsNeeded)
+ return;
+
+ /*
+ * Trigger the GC when it is safe to call an operation callback on any
+ * thread.
+ */
+ rt->gcIsNeeded = JS_TRUE;
+ js_TriggerAllOperationCallbacks(rt, gcLocked);
+}
+
+void
js_DestroyScriptsToGC(JSContext *cx, JSThreadData *data)
{
JSScript **listp, *script;
for (size_t i = 0; i != JS_ARRAY_LENGTH(data->scriptsToGC); ++i) {
listp = &data->scriptsToGC[i];
while ((script = *listp) != NULL) {
*listp = script->u.nextToGC;
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -160,16 +160,26 @@ js_TraceStackFrame(JSTracer *trc, JSStac
extern JS_REQUIRES_STACK void
js_TraceRuntime(JSTracer *trc);
extern JS_REQUIRES_STACK JS_FRIEND_API(void)
js_TraceContext(JSTracer *trc, JSContext *acx);
/*
+ * Schedule the GC call at a later safe point.
+ */
+#ifndef JS_THREADSAFE
+# define js_TriggerGC(cx, gcLocked) js_TriggerGC (cx)
+#endif
+
+extern void
+js_TriggerGC(JSContext *cx, JSBool gcLocked);
+
+/*
* Kinds of js_GC invocation.
*/
typedef enum JSGCInvocationKind {
/* Normal invocation. */
GC_NORMAL = 0,
/*
* Called from js_DestroyContext for last JSContext in a JSRuntime, when
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -310,19 +310,23 @@ ComputeThisFromArgv(JSContext *cx, Value
#if JS_HAS_NO_SUCH_METHOD
const uint32 JSSLOT_FOUND_FUNCTION = JSSLOT_PRIVATE;
const uint32 JSSLOT_SAVED_ID = JSSLOT_PRIVATE + 1;
Class js_NoSuchMethodClass = {
"NoSuchMethod",
JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS,
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
};
/*
* When JSOP_CALLPROP or JSOP_CALLELEM does not find the method property of
* the base object, we search for the __noSuchMethod__ method in the base.
* If it exists, we store the method and the property's id into an object of
* NoSuchMethod class and store this object into the callee's stack slot.
* Later, js_Invoke will recognise such an object and transfer control to
@@ -658,17 +662,17 @@ DoSlowCall(JSContext *cx, uintN argc, Va
JSStackFrame *fp = cx->fp;
JSObject *obj = fp->getThisObject(cx);
if (!obj)
return false;
JS_ASSERT(ObjectValue(*obj) == fp->thisv);
JSObject *callee = &JS_CALLEE(cx, vp).toObject();
Class *clasp = callee->getClass();
- JS_ASSERT(!(clasp->flags & CLASS_CALL_IS_FAST));
+ JS_ASSERT(!(clasp->flags & Class::CALL_IS_FAST));
if (!clasp->call) {
js_ReportIsNotFunction(cx, &vp[0], 0);
return JS_FALSE;
}
AutoValueRooter rval(cx);
JSBool ok = clasp->call(cx, obj, argc, JS_ARGV(cx, vp), rval.addr());
if (ok)
JS_SET_RVAL(cx, vp, rval.value());
@@ -760,17 +764,17 @@ Invoke(JSContext *cx, const InvokeArgsGu
/* Try a call or construct native object op. */
if (flags & JSINVOKE_CONSTRUCT) {
if (!vp[1].isObjectOrNull()) {
if (!js_PrimitiveToObject(cx, &vp[1]))
return false;
}
return InvokeCommon(cx, NULL, NULL, DoConstruct, args, flags);
}
- CallOp callOp = (clasp->flags & CLASS_CALL_IS_FAST) ? (CallOp) clasp->call : DoSlowCall;
+ CallOp callOp = (clasp->flags & Class::CALL_IS_FAST) ? (CallOp) clasp->call : DoSlowCall;
return InvokeCommon(cx, NULL, NULL, callOp, args, flags);
}
extern JS_REQUIRES_STACK JS_FRIEND_API(bool)
InvokeFriendAPI(JSContext *cx, const InvokeArgsGuard &args, uintN flags)
{
return Invoke(cx, args, flags);
}
@@ -910,17 +914,17 @@ Execute(JSContext *cx, JSObject *chain,
if (!innerizedChain)
return false;
fp->scopeChain = innerizedChain;
initialVarObj = (cx->options & JSOPTION_VAROBJFIX)
? chain->getGlobal()
: chain;
}
- JS_ASSERT(initialVarObj->map->ops->defineProperty == js_DefineProperty);
+ JS_ASSERT(!initialVarObj->getOps()->defineProperty);
fp->script = script;
fp->imacpc = NULL;
fp->rval.setUndefined();
fp->blockChain = NULL;
/* Initialize regs. */
regs.pc = script->code;
@@ -1149,17 +1153,17 @@ TypeOfValue(JSContext *cx, const Value &
return JSTYPE_NUMBER;
if (v.isString())
return JSTYPE_STRING;
if (v.isNull())
return JSTYPE_OBJECT;
if (v.isUndefined())
return JSTYPE_VOID;
if (v.isObject())
- return v.toObject().map->ops->typeOf(cx, &v.toObject());
+ return v.toObject().typeOf(cx);
JS_ASSERT(v.isBoolean());
return JSTYPE_BOOLEAN;
}
bool
InstanceOfSlow(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
{
JS_ASSERT(!obj || obj->getClass() != clasp);
@@ -2060,31 +2064,31 @@ JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH ==
/*
* Inline fast paths for iteration. js_IteratorMore and js_IteratorNext handle
* all cases, but we inline the most frequently taken paths here.
*/
static inline bool
IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval)
{
- if (iterobj->getClass() == &js_IteratorClass.base) {
+ if (iterobj->getClass() == &js_IteratorClass) {
NativeIterator *ni = (NativeIterator *) iterobj->getPrivate();
*cond = (ni->props_cursor < ni->props_end);
} else {
if (!js_IteratorMore(cx, iterobj, rval))
return false;
*cond = rval->isTrue();
}
return true;
}
static inline bool
IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
{
- if (iterobj->getClass() == &js_IteratorClass.base) {
+ if (iterobj->getClass() == &js_IteratorClass) {
NativeIterator *ni = (NativeIterator *) iterobj->getPrivate();
JS_ASSERT(ni->props_cursor < ni->props_end);
if (ni->isKeyIter()) {
jsid id = *ni->currentKey();
if (JSID_IS_ATOM(id)) {
rval->setString(JSID_TO_STRING(id));
ni->incKeyCursor();
return true;
@@ -3330,30 +3334,28 @@ END_CASE(JSOP_BITAND)
if ((lval.isObject() && lval.toObject().isXML()) || \
(rval.isObject() && rval.toObject().isXML())) { \
if (!js_TestXMLEquality(cx, lval, rval, &cond)) \
goto error; \
cond = cond OP JS_TRUE; \
} else
#define EXTENDED_EQUALITY_OP(OP) \
- if (((clasp = l->getClass())->flags & JSCLASS_IS_EXTENDED) && \
- ((ExtendedClass *)clasp)->equality) { \
- if (!((ExtendedClass *)clasp)->equality(cx, l, &rval, &cond)) \
+ if (EqualityOp eq = l->getClass()->ext.equality) { \
+ if (!eq(cx, l, &rval, &cond)) \
goto error; \
cond = cond OP JS_TRUE; \
} else
#else
#define XML_EQUALITY_OP(OP) /* nothing */
#define EXTENDED_EQUALITY_OP(OP) /* nothing */
#endif
#define EQUALITY_OP(OP, IFNAN) \
JS_BEGIN_MACRO \
- Class *clasp; \
JSBool cond; \
Value rval = regs.sp[-1]; \
Value lval = regs.sp[-2]; \
XML_EQUALITY_OP(OP) \
if (SameType(lval, rval)) { \
if (lval.isString()) { \
JSString *l = lval.toString(), *r = rval.toString(); \
cond = js_EqualStrings(l, r) OP JS_TRUE; \
@@ -4130,17 +4132,17 @@ BEGIN_CASE(JSOP_GETXPROP)
NATIVE_GET(cx, obj, obj2, sprop,
fp->imacpc ? JSGET_NO_METHOD_BARRIER : JSGET_METHOD_BARRIER,
&rval);
}
break;
}
jsid id = ATOM_TO_JSID(atom);
- if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)
+ if (JS_LIKELY(!aobj->getOps()->getProperty)
? !js_GetPropertyHelper(cx, obj, id,
(fp->imacpc ||
regs.pc[JSOP_GETPROP_LENGTH + i] == JSOP_IFEQ)
? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
: JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER,
&rval)
: !obj->getProperty(cx, id, &rval)) {
goto error;
@@ -4234,26 +4236,26 @@ BEGIN_CASE(JSOP_CALLPROP)
* PropertyCache::test.
*/
jsid id;
id = ATOM_TO_JSID(atom);
PUSH_NULL();
if (lval.isObject()) {
if (!js_GetMethod(cx, &objv.toObject(), id,
- JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)
+ JS_LIKELY(!aobj->getOps()->getProperty)
? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
: JSGET_NO_METHOD_BARRIER,
&rval)) {
goto error;
}
regs.sp[-1] = objv;
regs.sp[-2] = rval;
} else {
- JS_ASSERT(objv.toObject().map->ops->getProperty == js_GetProperty);
+ JS_ASSERT(!objv.toObject().getOps()->getProperty);
if (!js_GetPropertyHelper(cx, &objv.toObject(), id,
JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER,
&rval)) {
goto error;
}
regs.sp[-1] = lval;
regs.sp[-2] = rval;
}
@@ -4470,17 +4472,17 @@ BEGIN_CASE(JSOP_SETMETHOD)
}
if (sprop)
break;
}
if (!atom)
LOAD_ATOM(0, atom);
jsid id = ATOM_TO_JSID(atom);
- if (entry && JS_LIKELY(obj->map->ops->setProperty == js_SetProperty)) {
+ if (entry && JS_LIKELY(!obj->getOps()->setProperty)) {
uintN defineHow;
if (op == JSOP_SETMETHOD)
defineHow = JSDNP_CACHE_RESULT | JSDNP_SET_METHOD;
else if (op == JSOP_SETNAME)
defineHow = JSDNP_CACHE_RESULT | JSDNP_UNQUALIFIED;
else
defineHow = JSDNP_CACHE_RESULT;
if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval))
@@ -5483,17 +5485,17 @@ BEGIN_CASE(JSOP_DEFVAR)
JSAtom *atom = atoms[index];
/*
* index is relative to atoms at this point but for global var
* code below we need the absolute value.
*/
index += atoms - script->atomMap.vector;
JSObject *obj = fp->varobj(cx);
- JS_ASSERT(obj->map->ops->defineProperty == js_DefineProperty);
+ JS_ASSERT(!obj->getOps()->defineProperty);
uintN attrs = JSPROP_ENUMERATE;
if (!(fp->flags & JSFRAME_EVAL))
attrs |= JSPROP_PERMANENT;
if (op == JSOP_DEFCONST)
attrs |= JSPROP_READONLY;
/* Lookup id in order to check for redeclaration problems. */
jsid id = ATOM_TO_JSID(atom);
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -80,29 +80,41 @@
#include "jsstrinlines.h"
using namespace js;
static void iterator_finalize(JSContext *cx, JSObject *obj);
static void iterator_trace(JSTracer *trc, JSObject *obj);
static JSObject *iterator_iterator(JSContext *cx, JSObject *obj, JSBool keysonly);
-ExtendedClass js_IteratorClass = {
- { "Iterator",
- JSCLASS_HAS_PRIVATE |
- JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator) |
- JSCLASS_MARK_IS_TRACE |
- JSCLASS_IS_EXTENDED,
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, iterator_finalize,
- NULL, NULL, NULL, NULL,
- NULL, NULL, JS_CLASS_TRACE(iterator_trace), NULL },
- NULL, NULL, NULL, iterator_iterator,
- NULL,
- JSCLASS_NO_RESERVED_MEMBERS
+Class js_IteratorClass = {
+ "Iterator",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator) | JSCLASS_MARK_IS_TRACE,
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ iterator_finalize,
+ NULL, /* reserved */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ JS_CLASS_TRACE(iterator_trace),
+ {
+ NULL, /* equality */
+ NULL, /* outerObject */
+ NULL, /* innerObject */
+ iterator_iterator,
+ NULL /* wrappedObject */
+ }
};
void
NativeIterator::mark(JSTracer *trc)
{
if (isKeyIter())
MarkIdRange(trc, beginKey(), endKey(), "props");
else
@@ -113,17 +125,17 @@ NativeIterator::mark(JSTracer *trc)
/*
* Shared code to close iterator's state either through an explicit call or
* when GC detects that the iterator is no longer reachable.
*/
static void
iterator_finalize(JSContext *cx, JSObject *obj)
{
- JS_ASSERT(obj->getClass() == &js_IteratorClass.base);
+ JS_ASSERT(obj->getClass() == &js_IteratorClass);
/* Avoid double work if the iterator was closed by JSOP_ENDITER. */
NativeIterator *ni = obj->getNativeIterator();
if (ni) {
cx->free(ni);
obj->setNativeIterator(NULL);
}
}
@@ -303,17 +315,17 @@ Snapshot(JSContext *cx, JSObject *obj, u
IdSet ht(cx);
if (!ht.init(32))
return NULL;
JSObject *pobj = obj;
do {
Class *clasp = pobj->getClass();
if (pobj->isNative() &&
- pobj->map->ops->enumerate == js_Enumerate &&
+ !pobj->getOps()->enumerate &&
!(clasp->flags & JSCLASS_NEW_ENUMERATE)) {
if (!clasp->enumerate(cx, pobj))
return false;
if (!EnumerateNativeProperties<EnumPolicy>(cx, obj, pobj, flags, ht, props))
return false;
} else if (pobj->isDenseArray()) {
if (!EnumerateDenseArrayProperties<EnumPolicy>(cx, obj, pobj, flags, ht, props))
return false;
@@ -444,21 +456,21 @@ NewIteratorObject(JSContext *cx, uintN f
* are not stillborn, with the exception of "NoSuchMethod" internal
* helper objects) expect it to have a non-null map pointer, so we
* share an empty Enumerator scope in the runtime.
*/
JSObject *obj = js_NewGCObject(cx);
if (!obj)
return false;
obj->map = cx->runtime->emptyEnumeratorScope->hold();
- obj->init(&js_IteratorClass.base, NULL, NULL, NullValue());
+ obj->init(&js_IteratorClass, NULL, NULL, NullValue());
return obj;
}
- return NewBuiltinClassInstance(cx, &js_IteratorClass.base);
+ return NewBuiltinClassInstance(cx, &js_IteratorClass);
}
NativeIterator *
NativeIterator::allocateKeyIterator(JSContext *cx, uint32 slength, const AutoIdVector &props)
{
size_t plength = props.length();
NativeIterator *ni = (NativeIterator *)
cx->malloc(sizeof(NativeIterator) + plength * sizeof(jsid) + slength * sizeof(uint32));
@@ -605,17 +617,17 @@ GetIterator(JSContext *cx, JSObject *obj
* The iterator object for JSITER_ENUMERATE never escapes, so we
* don't care for the proper parent/proto to be set. This also
* allows us to re-use a previous iterator object that was freed
* by JSOP_ENDITER.
*/
JSObject *pobj = obj;
do {
if (!pobj->isNative() ||
- obj->map->ops->enumerate != js_Enumerate ||
+ obj->getOps()->enumerate ||
pobj->getClass()->enumerate != JS_EnumerateStub) {
shapes.clear();
goto miss;
}
uint32 shape = pobj->shape();
key = (key + (key << 16)) ^ shape;
if (!shapes.append(shape))
return false;
@@ -693,17 +705,17 @@ js_ThrowStopIteration(JSContext *cx)
}
static JSBool
iterator_next(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj;
obj = ComputeThisFromVp(cx, vp);
- if (!InstanceOf(cx, obj, &js_IteratorClass.base, vp + 2))
+ if (!InstanceOf(cx, obj, &js_IteratorClass, vp + 2))
return false;
if (!js_IteratorMore(cx, obj, vp))
return false;
if (!vp->toBoolean()) {
js_ThrowStopIteration(cx);
return false;
}
@@ -755,45 +767,41 @@ js_ValueToIterator(JSContext *cx, uintN
obj = js_ValueToNonNullObject(cx, *vp);
if (!obj)
return false;
}
}
AutoObjectRooter tvr(cx, obj);
- Class *clasp = obj->getClass();
- ExtendedClass *xclasp;
- if ((clasp->flags & JSCLASS_IS_EXTENDED) &&
- (xclasp = (ExtendedClass *) clasp)->iteratorObject) {
- /* Enumerate Iterator.prototype directly. */
- if (clasp != &js_IteratorClass.base || obj->getNativeIterator()) {
- JSObject *iterobj = xclasp->iteratorObject(cx, obj, !(flags & JSITER_FOREACH));
- if (!iterobj)
- return false;
- vp->setObject(*iterobj);
- return true;
- }
+ /* Enumerate Iterator.prototype directly. */
+ JSIteratorOp op = obj->getClass()->ext.iteratorObject;
+ if (op && (obj->getClass() != &js_IteratorClass || obj->getNativeIterator())) {
+ JSObject *iterobj = op(cx, obj, !(flags & JSITER_FOREACH));
+ if (!iterobj)
+ return false;
+ vp->setObject(*iterobj);
+ return true;
}
return GetIterator(cx, obj, flags, vp);
}
#if JS_HAS_GENERATORS
static JS_REQUIRES_STACK JSBool
CloseGenerator(JSContext *cx, JSObject *genobj);
#endif
JS_FRIEND_API(JSBool)
js_CloseIterator(JSContext *cx, JSObject *obj)
{
cx->iterValue.setMagic(JS_NO_ITER_VALUE);
Class *clasp = obj->getClass();
- if (clasp == &js_IteratorClass.base) {
+ if (clasp == &js_IteratorClass) {
/* Remove enumerators from the active list, which is a stack. */
NativeIterator *ni = obj->getNativeIterator();
if (ni->flags & JSITER_ENUMERATE) {
JS_ASSERT(cx->enumerators == obj);
cx->enumerators = ni->next;
}
/* Cache the iterator object if possible. */
@@ -803,17 +811,17 @@ js_CloseIterator(JSContext *cx, JSObject
ni->props_cursor = ni->props_array;
ni->next = *hp;
*hp = obj;
} else {
iterator_finalize(cx, obj);
}
}
#if JS_HAS_GENERATORS
- else if (clasp == &js_GeneratorClass.base) {
+ else if (clasp == &js_GeneratorClass) {
return CloseGenerator(cx, obj);
}
#endif
return JS_TRUE;
}
/*
* Suppress enumeration of deleted properties. We maintain a list of all active
@@ -888,17 +896,17 @@ js_SuppressDeletedProperty(JSContext *cx
}
return true;
}
JSBool
js_IteratorMore(JSContext *cx, JSObject *iterobj, Value *rval)
{
/* Fast path for native iterators */
- if (iterobj->getClass() == &js_IteratorClass.base) {
+ if (iterobj->getClass() == &js_IteratorClass) {
/*
* Implement next directly as all the methods of native iterator are
* read-only and permanent.
*/
NativeIterator *ni = iterobj->getNativeIterator();
rval->setBoolean(ni->props_cursor < ni->props_end);
return true;
}
@@ -932,17 +940,17 @@ js_IteratorMore(JSContext *cx, JSObject
rval->setBoolean(true);
return true;
}
JSBool
js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
{
/* Fast path for native iterators */
- if (iterobj->getClass() == &js_IteratorClass.base) {
+ if (iterobj->getClass() == &js_IteratorClass) {
/*
* Implement next directly as all the methods of the native iterator are
* read-only and permanent.
*/
NativeIterator *ni = iterobj->getNativeIterator();
JS_ASSERT(ni->props_cursor < ni->props_end);
if (ni->isKeyIter()) {
*rval = IdToValue(*ni->currentKey());
@@ -981,24 +989,30 @@ stopiter_hasInstance(JSContext *cx, JSOb
{
*bp = js_ValueIsStopIteration(*v);
return JS_TRUE;
}
Class js_StopIterationClass = {
js_StopIteration_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration),
- PropertyStub, PropertyStub,
- PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub,
- ConvertStub, NULL,
- NULL, NULL,
- NULL, NULL,
- NULL, stopiter_hasInstance,
- NULL, NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ NULL, /* finalize */
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ stopiter_hasInstance
};
#if JS_HAS_GENERATORS
static void
generator_finalize(JSContext *cx, JSObject *obj)
{
JSGenerator *gen = (JSGenerator *) obj->getPrivate();
@@ -1031,44 +1045,56 @@ generator_trace(JSTracer *trc, JSObject
JSStackFrame *fp = gen->getFloatingFrame();
JS_ASSERT(gen->getLiveFrame() == fp);
MarkValueRange(trc, gen->floatingStack, fp->argEnd(), "generator slots");
js_TraceStackFrame(trc, fp);
MarkValueRange(trc, fp->slots(), gen->savedRegs.sp, "generator slots");
}
-ExtendedClass js_GeneratorClass = {
- { js_Generator_str,
- JSCLASS_HAS_PRIVATE |
- JSCLASS_HAS_CACHED_PROTO(JSProto_Generator) |
- JSCLASS_IS_ANONYMOUS |
- JSCLASS_MARK_IS_TRACE |
- JSCLASS_IS_EXTENDED,
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, generator_finalize,
- NULL, NULL, NULL, NULL,
- NULL, NULL, JS_CLASS_TRACE(generator_trace), NULL },
- NULL, NULL, NULL, iterator_iterator,
- NULL,
- JSCLASS_NO_RESERVED_MEMBERS
+Class js_GeneratorClass = {
+ js_Generator_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Generator) |
+ JSCLASS_IS_ANONYMOUS | JSCLASS_MARK_IS_TRACE,
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ generator_finalize,
+ NULL, /* reserved */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ JS_CLASS_TRACE(generator_trace),
+ {
+ NULL, /* equality */
+ NULL, /* outerObject */
+ NULL, /* innerObject */
+ iterator_iterator,
+ NULL, /* wrappedObject */
+ }
};
/*
* Called from the JSOP_GENERATOR case in the interpreter, with fp referring
* to the frame by which the generator function was activated. Create a new
* JSGenerator object, which contains its own JSStackFrame that we populate
* from *fp. We know that upon return, the JSOP_GENERATOR opcode will return
* from the activation in fp, so we can steal away fp->callobj and fp->argsobj
* if they are non-null.
*/
JS_REQUIRES_STACK JSObject *
js_NewGenerator(JSContext *cx)
{
- JSObject *obj = NewBuiltinClassInstance(cx, &js_GeneratorClass.base);
+ JSObject *obj = NewBuiltinClassInstance(cx, &js_GeneratorClass);
if (!obj)
return NULL;
/* Load and compute stack slot counts. */
JSStackFrame *fp = cx->fp;
uintN argc = fp->argc;
uintN nargs = JS_MAX(argc, fp->fun->nargs);
uintN vplen = 2 + nargs;
@@ -1300,17 +1326,17 @@ SendToGenerator(JSContext *cx, JSGenerat
* Propagate the condition to the caller.
*/
return JS_FALSE;
}
static JS_REQUIRES_STACK JSBool
CloseGenerator(JSContext *cx, JSObject *obj)
{
- JS_ASSERT(obj->getClass() == &js_GeneratorClass.base);
+ JS_ASSERT(obj->getClass() == &js_GeneratorClass);
JSGenerator *gen = (JSGenerator *) obj->getPrivate();
if (!gen) {
/* Generator prototype object. */
return JS_TRUE;
}
if (gen->state == JSGEN_CLOSED)
@@ -1324,17 +1350,17 @@ CloseGenerator(JSContext *cx, JSObject *
*/
static JSBool
generator_op(JSContext *cx, JSGeneratorOp op, Value *vp, uintN argc)
{
JSObject *obj;
LeaveTrace(cx);
obj = ComputeThisFromVp(cx, vp);
- if (!InstanceOf(cx, obj, &js_GeneratorClass.base, vp + 2))
+ if (!InstanceOf(cx, obj, &js_GeneratorClass, vp + 2))
return JS_FALSE;
JSGenerator *gen = (JSGenerator *) obj->getPrivate();
if (!gen) {
/* This happens when obj is the generator prototype. See bug 352885. */
goto closed_generator;
}
@@ -1419,24 +1445,24 @@ js_InitIteratorClasses(JSContext *cx, JS
JSObject *proto, *stop;
/* Idempotency required: we initialize several things, possibly lazily. */
if (!js_GetClassObject(cx, obj, JSProto_StopIteration, &stop))
return NULL;
if (stop)
return stop;
- proto = js_InitClass(cx, obj, NULL, &js_IteratorClass.base, Iterator, 2,
+ proto = js_InitClass(cx, obj, NULL, &js_IteratorClass, Iterator, 2,
NULL, iterator_methods, NULL, NULL);
if (!proto)
return NULL;
#if JS_HAS_GENERATORS
/* Initialize the generator internals if configured. */
- if (!js_InitClass(cx, obj, NULL, &js_GeneratorClass.base, NULL, 0,
+ if (!js_InitClass(cx, obj, NULL, &js_GeneratorClass, NULL, 0,
NULL, generator_methods, NULL, NULL)) {
return NULL;
}
#endif
return js_InitClass(cx, obj, NULL, &js_StopIterationClass, NULL, 0,
NULL, NULL, NULL, NULL);
}
--- a/js/src/jsiter.h
+++ b/js/src/jsiter.h
@@ -244,19 +244,19 @@ js_LiveFrameIfGenerator(JSStackFrame *fp
{
if (fp->flags & JSFRAME_GENERATOR)
return js_FloatingFrameToGenerator(fp)->getLiveFrame();
return fp;
}
#endif
-extern js::ExtendedClass js_GeneratorClass;
-extern js::ExtendedClass js_IteratorClass;
-extern js::Class js_StopIterationClass;
+extern js::Class js_GeneratorClass;
+extern js::Class js_IteratorClass;
+extern js::Class js_StopIterationClass;
static inline bool
js_ValueIsStopIteration(const js::Value &v)
{
return v.isObject() && v.toObject().getClass() == &js_StopIterationClass;
}
extern JSObject *
--- a/js/src/jslock.h
+++ b/js/src/jslock.h
@@ -145,19 +145,17 @@ struct JSTitle {
#define JS_UNLOCK(cx, tl) js_Unlock(cx, tl)
#define JS_LOCK_RUNTIME(rt) js_LockRuntime(rt)
#define JS_UNLOCK_RUNTIME(rt) js_UnlockRuntime(rt)
/*
* NB: The JS_LOCK_OBJ and JS_UNLOCK_OBJ macros work *only* on native objects
* (objects for which obj->isNative() returns true). All uses of these macros in
- * the engine are predicated on obj->isNative or equivalent checks. These uses
- * are for optimizations above the JSObjectOps layer, under which object locks
- * normally hide.
+ * the engine are predicated on obj->isNative or equivalent checks.
*/
#define CX_OWNS_SCOPE_TITLE(cx,scope) ((scope)->title.ownercx == (cx))
#define JS_LOCK_OBJ(cx,obj) \
JS_BEGIN_MACRO \
JSObject *obj_ = (obj); \
if (!CX_OWNS_SCOPE_TITLE(cx, obj_->scope())) { \
js_LockObj(cx, obj_); \
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -92,19 +92,23 @@ static JSConstDoubleSpec math_constants[
{M_SQRT2, "SQRT2", 0, {0,0,0}},
{M_SQRT1_2, "SQRT1_2", 0, {0,0,0}},
{0,0,0,{0,0,0}}
};
Class js_MathClass = {
js_Math_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_Math),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub
};
static JSBool
math_abs(JSContext *cx, uintN argc, Value *vp)
{
jsdouble x, z;
if (argc == 0) {
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -277,19 +277,23 @@ static JSFunctionSpec number_functions[]
JS_TN(js_parseFloat_str, num_parseFloat, 1,0, &num_parseFloat_trcinfo),
JS_TN(js_parseInt_str, num_parseInt, 2,0, &num_parseInt_trcinfo),
JS_FS_END
};
Class js_NumberClass = {
js_Number_str,
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Number),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub
};
static JSBool
Number(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
{
if (argc != 0) {
if (!ValueToNumber(cx, &argv[0]))
return JS_FALSE;
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -97,40 +97,37 @@
#include "jsatominlines.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "jsautooplen.h"
using namespace js;
-JS_FRIEND_DATA(JSObjectOps) js_ObjectOps = {
- NULL,
- js_LookupProperty,
- js_DefineProperty,
- js_GetProperty,
- js_SetProperty,
- js_GetAttributes,
- js_SetAttributes,
- js_DeleteProperty,
- js_Enumerate,
- js_TypeOf,
- js_TraceObject,
- NULL, /* thisObject */
- js_Clear
-};
+JS_FRIEND_DATA(const JSObjectMap) JSObjectMap::sharedNonNative(JSObjectMap::SHAPELESS);
Class js_ObjectClass = {
js_Object_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub
};
+JS_FRIEND_API(JSObject *)
+js_ObjectToOuterObject(JSContext *cx, JSObject *obj)
+{
+ OBJ_TO_OUTER_OBJECT(cx, obj);
+ return obj;
+}
+
#if JS_HAS_OBJ_PROTO_PROP
static JSBool
obj_getProto(JSContext *cx, JSObject *obj, jsid id, Value *vp);
static JSBool
obj_setProto(JSContext *cx, JSObject *obj, jsid id, Value *vp);
@@ -912,40 +909,31 @@ js_CheckPrincipalsAccess(JSContext *cx,
}
}
return JS_TRUE;
}
JSObject *
js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller)
{
- Class *clasp;
- JSExtendedClass *xclasp;
JSObject *inner;
if (!scopeobj)
goto bad;
OBJ_TO_INNER_OBJECT(cx, scopeobj);
if (!scopeobj)
return NULL;
+ /* XXX This is an awful gross hack. */
inner = scopeobj;
-
- /* XXX This is an awful gross hack. */
while (scopeobj) {
- clasp = scopeobj->getClass();
- if (clasp->flags & JSCLASS_IS_EXTENDED) {
- xclasp = (JSExtendedClass*)clasp;
- if (xclasp->innerObject &&
- xclasp->innerObject(cx, scopeobj) != scopeobj) {
- goto bad;
- }
- }
-
+ JSObjectOp op = scopeobj->getClass()->ext.innerObject;
+ if (op && op(cx, scopeobj) != scopeobj)
+ goto bad;
scopeobj = scopeobj->getParent();
}
return inner;
bad:
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_INDIRECT_CALL, caller);
@@ -1362,17 +1350,17 @@ obj_unwatch(JSContext *cx, uintN argc, V
*/
/* Proposed ECMA 15.2.4.5. */
static JSBool
obj_hasOwnProperty(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
return obj &&
- js_HasOwnPropertyHelper(cx, obj->map->ops->lookupProperty, argc, vp);
+ js_HasOwnPropertyHelper(cx, obj->getOps()->lookupProperty, argc, vp);
}
JSBool
js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, uintN argc,
Value *vp)
{
jsid id;
if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), &id))
@@ -1401,32 +1389,28 @@ js_HasOwnPropertyHelper(JSContext *cx, J
return JS_TRUE;
}
JSBool
js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
JSObject **objp, JSProperty **propp)
{
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING);
- if (!lookup(cx, obj, id, objp, propp))
+ if (!(lookup ? lookup : js_LookupProperty)(cx, obj, id, objp, propp))
return false;
if (!*propp)
return true;
if (*objp == obj)
return true;
- JSExtendedClass *xclasp;
- JSObject *outer;
Class *clasp = (*objp)->getClass();
- if (!(clasp->flags & JSCLASS_IS_EXTENDED) ||
- !(xclasp = (JSExtendedClass *) clasp)->outerObject) {
- outer = NULL;
- } else {
- outer = xclasp->outerObject(cx, *objp);
+ JSObject *outer = NULL;
+ if (JSObjectOp op = (*objp)->getClass()->ext.outerObject) {
+ outer = op(cx, *objp);
if (!outer)
return false;
}
if (outer != *objp) {
if ((*objp)->isNative() && obj->getClass() == clasp) {
/*
* The combination of JSPROP_SHARED and JSPROP_PERMANENT in a
@@ -1702,17 +1686,17 @@ js_GetOwnPropertyDescriptor(JSContext *c
{
if (obj->isProxy()) {
if (!JSProxy::getOwnPropertyDescriptor(cx, obj, id, vp))
return false;
}
JSObject *pobj;
JSProperty *prop;
- if (!js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &pobj, &prop))
+ if (!js_HasOwnProperty(cx, obj->getOps()->lookupProperty, obj, id, &pobj, &prop))
return false;
if (!prop) {
vp->setUndefined();
return true;
}
Value roots[] = { UndefinedValue(), UndefinedValue(), UndefinedValue() };
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots);
@@ -1978,32 +1962,32 @@ Reject(JSContext *cx, JSObject *obj, JSP
static JSBool
DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc,
bool throwError, bool *rval)
{
/* 8.12.9 step 1. */
JSProperty *current;
JSObject *obj2;
- JS_ASSERT(obj->map->ops->lookupProperty == js_LookupProperty);
- if (!js_HasOwnProperty(cx, js_LookupProperty, obj, desc.id, &obj2, ¤t))
+ JS_ASSERT(!obj->getOps()->lookupProperty);
+ if (!js_HasOwnProperty(cx, NULL, obj, desc.id, &obj2, ¤t))
return JS_FALSE;
- JS_ASSERT(obj->map->ops->defineProperty == js_DefineProperty);
+ JS_ASSERT(!obj->getOps()->defineProperty);
/* 8.12.9 steps 2-4. */
JSScope *scope = obj->scope();
if (!current) {
if (scope->sealed())
return Reject(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
*rval = true;
if (desc.isGenericDescriptor() || desc.isDataDescriptor()) {
- JS_ASSERT(obj->map->ops->defineProperty == js_DefineProperty);
+ JS_ASSERT(!obj->getOps()->defineProperty);
return js_DefineProperty(cx, obj, desc.id, &desc.value,
PropertyStub, PropertyStub, desc.attrs);
}
JS_ASSERT(desc.isAccessorDescriptor());
/*
* Getters and setters are just like watchpoints from an access
@@ -2298,17 +2282,17 @@ DefinePropertyOnArray(JSContext *cx, JSO
static JSBool
DefineProperty(JSContext *cx, JSObject *obj, const PropDesc &desc, bool throwError,
bool *rval)
{
if (obj->isArray())
return DefinePropertyOnArray(cx, obj, desc, throwError, rval);
- if (obj->map->ops->lookupProperty != js_LookupProperty) {
+ if (obj->getOps()->lookupProperty) {
if (obj->isProxy())
return JSProxy::defineProperty(cx, obj, desc.id, desc.pd);
return Reject(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
}
return DefinePropertyOnObject(cx, obj, desc, throwError, rval);
}
@@ -2579,18 +2563,17 @@ js_Object(JSContext *cx, JSObject *obj,
}
#ifdef JS_TRACER
JSObject*
js_NewObjectWithClassProto(JSContext *cx, Class *clasp, JSObject *proto,
const Value &privateSlotValue)
{
- JS_ASSERT(!clasp->getObjectOps);
- JS_ASSERT(proto->map->ops == &js_ObjectOps);
+ JS_ASSERT(clasp->isNative());
JSObject* obj = js_NewGCObject(cx);
if (!obj)
return NULL;
obj->initSharingEmptyScope(clasp, proto, proto->getParent(), privateSlotValue);
return obj;
}
@@ -2861,45 +2844,49 @@ with_TypeOf(JSContext *cx, JSObject *obj
}
static JSObject *
with_ThisObject(JSContext *cx, JSObject *obj)
{
return obj->getWithThis();
}
-JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = {
- NULL,
- with_LookupProperty,
- js_DefineProperty,
- with_GetProperty,
- with_SetProperty,
- with_GetAttributes,
- with_SetAttributes,
- with_DeleteProperty,
- with_Enumerate,
- with_TypeOf,
- js_TraceObject,
- with_ThisObject,
- js_Clear
-};
-
-static JSObjectOps *
-with_getObjectOps(JSContext *cx, Class *clasp)
-{
- return &js_WithObjectOps;
-}
-
Class js_WithClass = {
"With",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS,
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- with_getObjectOps,
- 0,0,0,0,0,0,0
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ NULL, /* finalize */
+ NULL, /* reserved */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ NULL, /* mark */
+ JS_NULL_CLASS_EXT,
+ {
+ with_LookupProperty,
+ NULL, /* defineProperty */
+ with_GetProperty,
+ with_SetProperty,
+ with_GetAttributes,
+ with_SetAttributes,
+ with_DeleteProperty,
+ with_Enumerate,
+ with_TypeOf,
+ NULL, /* trace */
+ with_ThisObject,
+ NULL, /* clear */
+ }
};
JS_REQUIRES_STACK JSObject *
js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
{
JSObject *obj;
obj = js_NewGCObject(cx);
@@ -3236,19 +3223,23 @@ js_XDRBlockObject(JSXDRState *xdr, JSObj
return true;
}
#endif
Class js_BlockClass = {
"Block",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_IS_ANONYMOUS,
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub
};
JSObject *
js_InitObjectClass(JSContext *cx, JSObject *obj)
{
JSObject *proto = js_InitClass(cx, obj, NULL, &js_ObjectClass, js_Object, 1,
object_props, object_methods, NULL, object_static_methods);
if (!proto)
@@ -4467,17 +4458,17 @@ js_FindPropertyHelper(JSContext *cx, jsi
/* Scan entries on the scope chain that we can cache across. */
entry = JS_NO_PROP_CACHE_FILL;
obj = scopeChain;
parent = obj->getParent();
for (scopeIndex = 0;
parent
? js_IsCacheableNonGlobalScope(obj)
- : obj->map->ops->lookupProperty == js_LookupProperty;
+ : !obj->getOps()->lookupProperty;
++scopeIndex) {
protoIndex =
js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
&pobj, &prop);
if (protoIndex < 0)
return NULL;
if (prop) {
@@ -4848,26 +4839,29 @@ js_GetProperty(JSContext *cx, JSObject *
return js_GetPropertyHelper(cx, obj, id, JSGET_METHOD_BARRIER, vp);
}
JSBool
js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, Value *vp)
{
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
- if (obj->map->ops == &js_ObjectOps ||
- obj->map->ops->getProperty == js_GetProperty) {
+ PropertyIdOp op = obj->getOps()->getProperty;
+ if (!op) {
+#if JS_HAS_XML_SUPPORT
+ JS_ASSERT(!obj->isXML());
+#endif
return js_GetPropertyHelper(cx, obj, id, getHow, vp);
}
JS_ASSERT_IF(getHow & JSGET_CACHE_RESULT, obj->isDenseArray());
#if JS_HAS_XML_SUPPORT
if (obj->isXML())
return js_GetXMLMethod(cx, obj, id, vp);
#endif
- return obj->getProperty(cx, id, vp);
+ return op(cx, obj, id, vp);
}
JS_FRIEND_API(bool)
js_CheckUndeclaredVarAssignment(JSContext *cx, JSString *propname)
{
JSStackFrame *const fp = js_GetTopStackFrame(cx);
if (!fp)
return true;
@@ -5377,17 +5371,17 @@ DefaultValue(JSContext *cx, JSObject *ob
return JS_FALSE;
}
*vp = v;
return JS_TRUE;
}
} /* namespace js */
-JSBool
+JS_FRIEND_API(JSBool)
js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, Value *statep, jsid *idp)
{
/* If the class has a custom JSCLASS_NEW_ENUMERATE hook, call it. */
Class *clasp = obj->getClass();
JSEnumerateOp enumerate = clasp->enumerate;
if (clasp->flags & JSCLASS_NEW_ENUMERATE) {
JS_ASSERT(enumerate != JS_EnumerateStub);
return ((NewEnumerateOp) enumerate)(cx, obj, enum_op, statep, idp);
@@ -5931,18 +5925,16 @@ js_TraceObject(JSTracer *trc, JSObject *
else if (IS_GC_MARKING_TRACER(trc))
(void) clasp->mark(cx, obj, trc);
}
if (clasp->flags & JSCLASS_IS_GLOBAL) {
JSCompartment *compartment = obj->getCompartment(cx);
compartment->marked = true;
}
- obj->traceProtoAndParent(trc);
-
/*
* An unmutated object that shares a prototype object's scope. We can't
* tell how many slots are in use in obj by looking at its scope, so we
* use obj->numSlots().
*
* NB: In case clasp->mark mutates something, leave this code here --
* don't move it up and unify it with the |if (!traceScope)| section
* above.
@@ -5955,17 +5947,17 @@ js_TraceObject(JSTracer *trc, JSObject *
for (uint32 i = JSSLOT_START(clasp); i != nslots; ++i) {
const Value &v = obj->getSlot(i);
JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
MarkValueRaw(trc, v);
}
}
void
-js_Clear(JSContext *cx, JSObject *obj)
+js_ClearNative(JSContext *cx, JSObject *obj)
{
JSScope *scope;
uint32 i, n;
/*
* Clear our scope and the property cache of all obj's properties only if
* obj owns the scope (i.e., not if obj is sharing another object's scope).
* NB: we do not clear any reserved slots lying below JSSLOT_FREE(clasp).
@@ -6044,22 +6036,19 @@ js_SetReservedSlot(JSContext *cx, JSObje
GC_POKE(cx, JS_NULL);
JS_UNLOCK_SCOPE(cx, scope);
return true;
}
JSObject *
JSObject::wrappedObject(JSContext *cx) const
{
- Class *clasp = getClass();
- if (clasp->flags & JSCLASS_IS_EXTENDED) {
- if (JSObjectOp wrappedObject = reinterpret_cast<JSExtendedClass *>(clasp)->wrappedObject) {
- if (JSObject *obj = wrappedObject(cx, const_cast<JSObject *>(this)))
- return obj;
- }
+ if (JSObjectOp op = getClass()->ext.wrappedObject) {
+ if (JSObject *obj = op(cx, const_cast<JSObject *>(this)))
+ return obj;
}
return const_cast<JSObject *>(this);
}
JSObject *
JSObject::getGlobal()
{
JSObject *obj = this;
@@ -6085,17 +6074,17 @@ JSObject::getCompartment(JSContext *cx)
Class *clasp = obj->getClass();
if (!(clasp->flags & JSCLASS_IS_GLOBAL)) {
// The magic AnyName object is runtime-wide.
if (clasp == &js_AnyNameClass)
return cx->runtime->defaultCompartment;
// The magic function namespace object is runtime-wide.
- if (clasp == &js_NamespaceClass.base &&
+ if (clasp == &js_NamespaceClass &&
obj->getNameURI() == ATOM_TO_JSVAL(cx->runtime->atomState.lazy.functionNamespaceURIAtom)) {
return cx->runtime->defaultCompartment;
}
// Compile-time Function, Block, and RegExp objects are not parented.
if (clasp == &js_FunctionClass || clasp == &js_BlockClass || clasp == &js_RegExpClass) {
// This is a bogus answer, but it'll do for now.
return cx->runtime->defaultCompartment;
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -165,112 +165,99 @@ struct PropDesc {
bool hasEnumerable : 1;
bool hasConfigurable : 1;
};
namespace js {
typedef Vector<PropDesc, 1> PropDescArray;
-/*
- * Flag and type-safe cast helper to denote that Class::call is a fast native.
- */
-const uint32 CLASS_CALL_IS_FAST = uint32(1) << (JSCLASS_LAST_API_FLAG_SHIFT + 1);
-
-inline Native CastCallOpAsNative(CallOp op)
-{
- return reinterpret_cast<Native>(op);
-}
-
} /* namespace js */
-/* For detailed comments on these function pointer types, see jsprvtd.h. */
-struct JSObjectOps {
- /*
- * Custom shared object map for non-native objects. For native objects
- * this should be null indicating, that JSObject.map is an instance of
- * JSScope.
- */
- const JSObjectMap *objectMap;
-
- /* Mandatory non-null function pointer members. */
- JSLookupPropOp lookupProperty;
- js::DefinePropOp defineProperty;
- js::PropertyIdOp getProperty;
- js::PropertyIdOp setProperty;
- JSAttributesOp getAttributes;
- JSAttributesOp setAttributes;
- js::PropertyIdOp deleteProperty;
- js::NewEnumerateOp enumerate;
- JSTypeOfOp typeOf;
- JSTraceOp trace;
+struct JSObjectMap {
+ static JS_FRIEND_DATA(const JSObjectMap) sharedNonNative;
- /* Optionally non-null members start here. */
- JSObjectOp thisObject;
- JSFinalizeOp clear;
-
- bool inline isNative() const;
-};
-
-extern JS_FRIEND_DATA(JSObjectOps) js_ObjectOps;
-extern JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps;
-
-/*
- * Test whether the ops is native. FIXME bug 492938: consider how it would
- * affect the performance to do just the !objectMap check.
- */
-inline bool
-JSObjectOps::isNative() const
-{
- return JS_LIKELY(this == &js_ObjectOps) || !objectMap;
-}
-
-struct JSObjectMap {
- const JSObjectOps * const ops; /* high level object operation vtable */
uint32 shape; /* shape identifier */
- explicit JSObjectMap(const JSObjectOps *ops, uint32 shape) : ops(ops), shape(shape) {}
+ explicit JSObjectMap(uint32 shape) : shape(shape) {}
enum { INVALID_SHAPE = 0x8fffffff, SHAPELESS = 0xffffffff };
-private:
+ bool isNative() const { return this != &sharedNonNative; }
+
+ private:
/* No copy or assignment semantics. */
JSObjectMap(JSObjectMap &);
void operator=(JSObjectMap &);
};
+/*
+ * Unlike js_DefineNativeProperty, propp must be non-null. On success, and if
+ * id was found, return true with *objp non-null and locked, and with a held
+ * property stored in *propp. If successful but id was not found, return true
+ * with both *objp and *propp null. Therefore all callers who receive a
+ * non-null *propp must later call (*objp)->dropProperty(cx, *propp).
+ */
+extern JS_FRIEND_API(JSBool)
+js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp);
+
+extern JSBool
+js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value,
+ js::PropertyOp getter, js::PropertyOp setter, uintN attrs);
+
+extern JSBool
+js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
+
+extern JSBool
+js_SetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
+
+extern JSBool
+js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+
+extern JSBool
+js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+
+extern JSBool
+js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ js::Value *statep, jsid *idp);
+
+extern JSType
+js_TypeOf(JSContext *cx, JSObject *obj);
+
struct NativeIterator;
-const uint32 JS_INITIAL_NSLOTS = 4;
-
-const uint32 JSSLOT_PARENT = 0;
+const uint32 JS_INITIAL_NSLOTS = 3;
/*
* The first available slot to store generic value. For JSCLASS_HAS_PRIVATE
* classes the slot stores a pointer to private data stuffed in a Value.
* Such pointer is stored as is without an overhead of PRIVATE_TO_JSVAL
* tagging and should be accessed using the (get|set)Private methods of
* JSObject.
*/
-const uint32 JSSLOT_PRIVATE = 1;
+const uint32 JSSLOT_PRIVATE = 0;
struct JSFunction;
/*
* JSObject struct, with members sized to fit in 32 bytes on 32-bit targets,
* 64 bytes on 64-bit systems. The JSFunction struct is an extension of this
* struct allocated from a larger GC size-class.
*
- * An object is a delegate if it is on another object's prototype (linked by
- * JSSLOT_PROTO) or scope (JSSLOT_PARENT) chain, and therefore the delegate
- * might be asked implicitly to get or set a property on behalf of another
- * object. Delegates may be accessed directly too, as may any object, but only
- * those objects linked after the head of any prototype or scope chain are
- * flagged as delegates. This definition helps to optimize shape-based property
- * cache invalidation (see Purge{Scope,Proto}Chain in jsobj.cpp).
+ * An object is a delegate if it is on another object's prototype (the proto
+ * field) or scope chain (the parent field), and therefore the delegate might
+ * be asked implicitly to get or set a property on behalf of another object.
+ * Delegates may be accessed directly too, as may any object, but only those
+ * objects linked after the head of any prototype or scope chain are flagged
+ * as delegates. This definition helps to optimize shape-based property cache
+ * invalidation (see Purge{Scope,Proto}Chain in jsobj.cpp).
*
* The meaning of the system object bit is defined by the API client. It is
* set in JS_NewSystemObject and is queried by JS_IsSystemObject (jsdbgapi.h),
* but it has no intrinsic meaning to SpiderMonkey. Further, JSFILENAME_SYSTEM
* and JS_FlagScriptFilenamePrefix (also exported via jsdbgapi.h) are intended
* to be complementary to this bit, but it is up to the API client to implement
* any such association.
*
@@ -287,40 +274,40 @@ struct JSObject {
* manipulates JSObjects, which requires peeking under any encapsulation.
*/
friend class js::TraceRecorder;
JSObjectMap *map; /* property map, see jsscope.h */
js::Class *clasp; /* class pointer */
jsuword flags; /* see above */
JSObject *proto; /* object's prototype */
+ JSObject *parent; /* object's parent */
js::Value *dslots; /* dynamically allocated slots */
-#if JS_BITS_PER_WORD == 32
- // TODO: this is needed to pad out fslots. alternatively, clasp could be
- // merged with flags and the padding removed, but I think the upcoming
- // removal of JSScope will change this all anyway so I will leave this
- // here for now.
- uint32 padding;
-#endif
js::Value fslots[JS_INITIAL_NSLOTS]; /* small number of fixed slots */
- bool isNative() const { return map->ops->isNative(); }
+ bool isNative() const {
+ return map->isNative();
+ }
js::Class *getClass() const {
return clasp;
}
JSClass *getJSClass() const {
return Jsvalify(clasp);
}
bool hasClass(const js::Class *c) const {
return c == clasp;
}
+ const js::ObjectOps *getOps() const {
+ return &getClass()->ops;
+ }
+
inline JSScope *scope() const;
inline uint32 shape() const;
bool isDelegate() const {
return (flags & jsuword(1)) != jsuword(0);
}
void setDelegate() {
@@ -410,37 +397,30 @@ struct JSObject {
for (JSObject *obj = newProto; obj; obj = obj->getProto())
JS_ASSERT(obj != this);
#endif
setDelegateNullSafe(newProto);
proto = newProto;
}
JSObject *getParent() const {
- return fslots[JSSLOT_PARENT].toObjectOrNull();
+ return parent;
}
void clearParent() {
- fslots[JSSLOT_PARENT].setNull();
+ parent = NULL;
}
void setParent(JSObject *newParent) {
#ifdef DEBUG
for (JSObject *obj = newParent; obj; obj = obj->getParent())
JS_ASSERT(obj != this);
#endif
setDelegateNullSafe(newParent);
- fslots[JSSLOT_PARENT].setObjectOrNull(newParent);
- }
-
- void traceProtoAndParent(JSTracer *trc) const {
- if (JSObject *proto = getProto())
- JS_CALL_OBJECT_TRACER(trc, proto, "__proto__");
- if (JSObject *parent = getParent())
- JS_CALL_OBJECT_TRACER(trc, parent, "parent");
+ parent = newParent;
}
JSObject *getGlobal();
void *getPrivate() const {
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
void *priv = fslots[JSSLOT_PRIVATE].toPrivate();
return priv;
@@ -681,63 +661,72 @@ struct JSObject {
JSObject *parent,
const js::Value &privateSlotValue);
inline bool hasSlotsArray() const { return !!dslots; }
/* This method can only be called when hasSlotsArray() returns true. */
inline void freeSlotsArray(JSContext *cx);
- JSBool lookupProperty(JSContext *cx, jsid id,
- JSObject **objp, JSProperty **propp) {
- return map->ops->lookupProperty(cx, this, id, objp, propp);
+ JSBool lookupProperty(JSContext *cx, jsid id, JSObject **objp, JSProperty **propp) {
+ JSLookupPropOp op = getOps()->lookupProperty;
+ return (op ? op : js_LookupProperty)(cx, this, id, objp, propp);
}
JSBool defineProperty(JSContext *cx, jsid id, const js::Value &value,
js::PropertyOp getter = js::PropertyStub,
js::PropertyOp setter = js::PropertyStub,
uintN attrs = JSPROP_ENUMERATE) {
- return map->ops->defineProperty(cx, this, id, &value, getter, setter, attrs);
+ js::DefinePropOp op = getOps()->defineProperty;
+ return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs);
}
JSBool getProperty(JSContext *cx, jsid id, js::Value *vp) {
- return map->ops->getProperty(cx, this, id, vp);
+ js::PropertyIdOp op = getOps()->getProperty;
+ return (op ? op : js_GetProperty)(cx, this, id, vp);
}
JSBool setProperty(JSContext *cx, jsid id, js::Value *vp) {
- return map->ops->setProperty(cx, this, id, vp);
+ js::PropertyIdOp op = getOps()->setProperty;
+ return (op ? op : js_SetProperty)(cx, this, id, vp);
}
JSBool getAttributes(JSContext *cx, jsid id, uintN *attrsp) {
- return map->ops->getAttributes(cx, this, id, attrsp);
+ JSAttributesOp op = getOps()->getAttributes;
+ return (op ? op : js_GetAttributes)(cx, this, id, attrsp);
}
JSBool setAttributes(JSContext *cx, jsid id, uintN *attrsp) {
- return map->ops->setAttributes(cx, this, id, attrsp);
+ JSAttributesOp op = getOps()->setAttributes;
+ return (op ? op : js_SetAttributes)(cx, this, id, attrsp);
}
JSBool deleteProperty(JSContext *cx, jsid id, js::Value *rval) {
- return map->ops->deleteProperty(cx, this, id, rval);
+ js::PropertyIdOp op = getOps()->deleteProperty;
+ return (op ? op : js_DeleteProperty)(cx, this, id, rval);
}
- JSBool enumerate(JSContext *cx, JSIterateOp op, js::Value *statep,
- jsid *idp) {
- return map->ops->enumerate(cx, this, op, statep, idp);
+ JSBool enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp) {
+ js::NewEnumerateOp op = getOps()->enumerate;
+ return (op ? op : js_Enumerate)(cx, this, iterop, statep, idp);
}
JSType typeOf(JSContext *cx) {
- return map->ops->typeOf(cx, this);
+ JSTypeOfOp op = getOps()->typeOf;
+ return (op ? op : js_TypeOf)(cx, this);
}
JSObject *wrappedObject(JSContext *cx) const;
/* These four are time-optimized to avoid stub calls. */
JSObject *thisObject(JSContext *cx) {
- return map->ops->thisObject ? map->ops->thisObject(cx, this) : this;
+ JSObjectOp op = getOps()->thisObject;
+ return op ? op(cx, this) : this;
}
+
static bool thisObject(JSContext *cx, const js::Value &v, js::Value *vp);
inline void dropProperty(JSContext *cx, JSProperty *prop);
JS_FRIEND_API(JSCompartment *) getCompartment(JSContext *cx);
void swap(JSObject *obj);
@@ -808,37 +797,29 @@ JS_STATIC_ASSERT(sizeof(JSObject) % JS_G
#define CX_THREAD_IS_RUNNING_GC(cx) \
THREAD_IS_RUNNING_GC((cx)->runtime, (cx)->thread)
#endif /* JS_THREADSAFE */
inline void
OBJ_TO_INNER_OBJECT(JSContext *cx, JSObject *&obj)
{
- js::Class *clasp = obj->getClass();
- if (clasp->flags & JSCLASS_IS_EXTENDED) {
- js::ExtendedClass *xclasp = (js::ExtendedClass *) clasp;
- if (xclasp->innerObject)
- obj = xclasp->innerObject(cx, obj);
- }
+ if (JSObjectOp op = obj->getClass()->ext.innerObject)
+ obj = op(cx, obj);
}
/*
* The following function has been copied to jsd/jsd_val.c. If making changes to
* OBJ_TO_OUTER_OBJECT, please update jsd/jsd_val.c as well.
*/
inline void
OBJ_TO_OUTER_OBJECT(JSContext *cx, JSObject *&obj)
{
- js::Class *clasp = obj->getClass();
- if (clasp->flags & JSCLASS_IS_EXTENDED) {
- js::ExtendedClass *xclasp = (js::ExtendedClass *) clasp;
- if (xclasp->outerObject)
- obj = xclasp->outerObject(cx, obj);
- }
+ if (JSObjectOp op = obj->getClass()->ext.outerObject)
+ obj = op(cx, obj);
}
class JSValueArray {
public:
jsval *array;
size_t length;
JSValueArray(jsval *v, size_t c) : array(v), length(c) {}
@@ -1070,24 +1051,22 @@ js_CheckForStringIndex(jsid id);
* js_PurgeScopeChain does nothing if obj is not itself a prototype or parent
* scope, else it reshapes the scope and prototype chains it links. It calls
* js_PurgeScopeChainHelper, which asserts that obj is flagged as a delegate
* (i.e., obj has ever been on a prototype or parent chain).
*/
extern void
js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id);
-#ifdef __cplusplus /* Aargh, libgjs, bug 492720. */
-static JS_INLINE void
+inline void
js_PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
{
if (obj->isDelegate())
js_PurgeScopeChainHelper(cx, obj, id);
}
-#endif
/*
* Find or create a property named by id in obj's scope, with the given getter
* and setter, slot, attributes, and other members.
*/
extern JSScopeProperty *
js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
js::PropertyOp getter, js::PropertyOp setter, uint32 slot,
@@ -1099,20 +1078,16 @@ js_AddNativeProperty(JSContext *cx, JSOb
* or identical property.
*/
extern JSScopeProperty *
js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
JSScopeProperty *sprop, uintN attrs, uintN mask,
js::PropertyOp getter, js::PropertyOp setter);
extern JSBool
-js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value,
- js::PropertyOp getter, js::PropertyOp setter, uintN attrs);
-
-extern JSBool
js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id,
const js::Value &descriptor, JSBool *bp);
/*
* Flags for the defineHow parameter of js_DefineNativeProperty.
*/
const uintN JSDNP_CACHE_RESULT = 1; /* an interpreter call from JSOP_INITPROP */
const uintN JSDNP_DONT_PURGE = 2; /* suppress js_PurgeScopeChain */
@@ -1132,54 +1107,43 @@ const uintN JSDNP_UNQUALIFIED = 8; /* U
*/
extern JSBool
js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value &value,
js::PropertyOp getter, js::PropertyOp setter, uintN attrs,
uintN flags, intN shortid, JSProperty **propp,
uintN defineHow = 0);
/*
- * Unlike js_DefineNativeProperty, propp must be non-null. On success, and if
- * id was found, return true with *objp non-null and locked, and with a held
- * property stored in *propp. If successful but id was not found, return true
- * with both *objp and *propp null. Therefore all callers who receive a
- * non-null *propp must later call (*objp)->dropProperty(cx, *propp).
- */
-extern JS_FRIEND_API(JSBool)
-js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
- JSProperty **propp);
-
-/*
* Specialized subroutine that allows caller to preset JSRESOLVE_* flags and
* returns the index along the prototype chain in which *propp was found, or
* the last index if not found, or -1 on error.
*/
extern int
js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
JSObject **objp, JSProperty **propp);
/*
* We cache name lookup results only for the global object or for native
* non-global objects without prototype or with prototype that never mutates,
* see bug 462734 and bug 487039.
*/
-static inline bool
+inline bool
js_IsCacheableNonGlobalScope(JSObject *obj)
{
extern JS_FRIEND_DATA(js::Class) js_CallClass;
extern JS_FRIEND_DATA(js::Class) js_DeclEnvClass;
JS_ASSERT(obj->getParent());
js::Class *clasp = obj->getClass();
bool cacheable = (clasp == &js_CallClass ||
clasp == &js_BlockClass ||
clasp == &js_DeclEnvClass);
- JS_ASSERT_IF(cacheable, obj->map->ops->lookupProperty == js_LookupProperty);
+ JS_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty);
return cacheable;
}
/*
* If cacheResult is false, return JS_NO_PROP_CACHE_FILL on success.
*/
extern js::PropertyCacheEntry *
js_FindPropertyHelper(JSContext *cx, jsid id, JSBool cacheResult,
@@ -1230,19 +1194,16 @@ extern JSBool
js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, bool added,
js::Value *vp);
extern JSBool
js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN getHow,
js::Value *vp);
extern JSBool
-js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
-
-extern JSBool
js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool
js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, js::Value *vp);
/*
* Check whether it is OK to assign an undeclared property with name
* propname of the global object in the current script on cx. Reports
@@ -1251,57 +1212,34 @@ js_GetMethod(JSContext *cx, JSObject *ob
*/
extern JS_FRIEND_API(bool)
js_CheckUndeclaredVarAssignment(JSContext *cx, JSString *propname);
extern JSBool
js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
js::Value *vp);
-extern JSBool
-js_SetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
-
-extern JSBool
-js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
-
-extern JSBool
-js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
-
/*
* Change attributes for the given native property. The caller must ensure
* that obj is locked and this function always unlocks obj on return.
*/
extern JSBool
js_SetNativeAttributes(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
uintN attrs);
-extern JSBool
-js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *rval);
-
namespace js {
extern JSBool
DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
-}
-
-extern JSBool
-js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
- js::Value *statep, jsid *idp);
-
-namespace js {
-
extern JSBool
CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
js::Value *vp, uintN *attrsp);
-}
-
-extern JSType
-js_TypeOf(JSContext *cx, JSObject *obj);
+} /* namespace js */
extern bool
js_IsDelegate(JSContext *cx, JSObject *obj, const js::Value &v);
/*
* If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
* JSProto_Null, clasp must non-null.
*/
@@ -1346,17 +1284,17 @@ js_XDRObject(JSXDRState *xdr, JSObject *
extern void
js_TraceObject(JSTracer *trc, JSObject *obj);
extern void
js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize);
extern void
-js_Clear(JSContext *cx, JSObject *obj);
+js_ClearNative(JSContext *cx, JSObject *obj);
extern bool
js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, js::Value *vp);
extern bool
js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, const js::Value &v);
/*
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -488,41 +488,41 @@ class AutoPropertyDescriptorRooter : pri
setter = desc->setter;
value = desc->value;
}
friend void AutoGCRooter::trace(JSTracer *trc);
};
static inline bool
-InitScopeForObject(JSContext* cx, JSObject* obj, js::Class *clasp, JSObject* proto, JSObjectOps* ops)
+InitScopeForObject(JSContext* cx, JSObject* obj, js::Class *clasp, JSObject* proto)
{
- JS_ASSERT(ops->isNative());
+ JS_ASSERT(clasp->isNative());
JS_ASSERT(proto == obj->getProto());
/* Share proto's emptyScope only if obj is similar to proto. */
JSScope *scope = NULL;
if (proto && proto->isNative()) {
JS_LOCK_OBJ(cx, proto);
scope = proto->scope();
- if (scope->canProvideEmptyScope(ops, clasp)) {
+ if (scope->canProvideEmptyScope(clasp)) {
JSScope *emptyScope = scope->getEmptyScope(cx, clasp);
JS_UNLOCK_SCOPE(cx, scope);
if (!emptyScope)
goto bad;
scope = emptyScope;
} else {
JS_UNLOCK_SCOPE(cx, scope);
scope = NULL;
}
}
if (!scope) {
- scope = JSScope::create(cx, ops, clasp, obj, js_GenerateShape(cx, false));
+ scope = JSScope::create(cx, clasp, obj, js_GenerateShape(cx, false));
if (!scope)
goto bad;
uint32 freeslot = JSSLOT_FREE(clasp);
JS_ASSERT(freeslot >= scope->freeslot);
if (freeslot > JS_INITIAL_NSLOTS && !obj->allocSlots(cx, freeslot))
goto bad;
scope->freeslot = freeslot;
#ifdef DEBUG
@@ -565,17 +565,17 @@ NewNativeClassInstance(JSContext *cx, Cl
/*
* Default parent to the parent of the prototype, which was set from
* the parent of the prototype's constructor.
*/
obj->init(clasp, proto, parent, JSObject::defaultPrivate(clasp));
JS_LOCK_OBJ(cx, proto);
JSScope *scope = proto->scope();
- JS_ASSERT(scope->canProvideEmptyScope(&js_ObjectOps, clasp));
+ JS_ASSERT(scope->canProvideEmptyScope(clasp));
scope = scope->getEmptyScope(cx, clasp);
JS_UNLOCK_OBJ(cx, proto);
if (!scope) {
obj = NULL;
} else {
obj->map = scope;
}
@@ -633,21 +633,16 @@ NewBuiltinClassInstance(JSContext *cx, C
* proto->getParent() if proto is non-null (else to null). NB: only this helper
* and NewObject can be used to construct full-sized JSFunction instances.
*/
static inline JSObject *
NewObjectWithGivenProto(JSContext *cx, Class *clasp, JSObject *proto, JSObject *parent)
{
DTrace::ObjectCreationScope objectCreationScope(cx, cx->fp, clasp);
- /* Always call the class's getObjectOps hook if it has one. */
- JSObjectOps *ops = clasp->getObjectOps
- ? clasp->getObjectOps(cx, clasp)
- : &js_ObjectOps;
-
/*
* Allocate an object from the GC heap and initialize all its fields before
* doing any operation that can potentially trigger GC. Functions have a
* larger non-standard allocation size.
*/
JSObject* obj;
if (clasp == &js_FunctionClass) {
obj = (JSObject*) js_NewGCFunction(cx);
@@ -667,24 +662,23 @@ NewObjectWithGivenProto(JSContext *cx, C
* Default parent to the parent of the prototype, which was set from
* the parent of the prototype's constructor.
*/
obj->init(clasp,
proto,
(!parent && proto) ? proto->getParent() : parent,
JSObject::defaultPrivate(clasp));
- if (ops->isNative()) {
- if (!InitScopeForObject(cx, obj, clasp, proto, ops)) {
+ if (clasp->isNative()) {
+ if (!InitScopeForObject(cx, obj, clasp, proto)) {
obj = NULL;
goto out;
}
} else {
- JS_ASSERT(ops->objectMap->ops == ops);
- obj->map = const_cast<JSObjectMap *>(ops->objectMap);
+ obj->map = const_cast<JSObjectMap *>(&JSObjectMap::sharedNonNative);
}
out:
objectCreationScope.handleCreation(obj);
return obj;
}
static inline JSProtoKey
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -94,19 +94,23 @@ struct JSONParser
#ifdef _MSC_VER
#pragma warning(pop)
#endif
Class js_JSONClass = {
js_JSON_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_JSON),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub
};
JSBool
js_json_parse(JSContext *cx, uintN argc, Value *vp)
{
JSString *s = NULL;
Value *argv = vp + 2;
AutoValueRooter reviver(cx);
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -883,92 +883,65 @@ proxy_DeleteProperty(JSContext *cx, JSOb
static void
proxy_TraceObject(JSTracer *trc, JSObject *obj)
{
JSContext *cx = trc->context;
if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList))
js_TraceWatchPoints(trc, obj);
- Class *clasp = obj->getClass();
- if (clasp->mark) {
- if (clasp->flags & JSCLASS_MARK_IS_TRACE)
- ((JSTraceOp) clasp->mark)(trc, obj);
- else if (IS_GC_MARKING_TRACER(trc))
- (void) clasp->mark(cx, obj, trc);
- }
-
- obj->traceProtoAndParent(trc);
obj->getProxyHandler()->trace(trc, obj);
MarkValue(trc, obj->getProxyPrivate(), "private");
if (obj->isFunctionProxy()) {
MarkValue(trc, GetCall(obj), "call");
MarkValue(trc, GetConstruct(obj), "construct");
}
}
-static JSType
-proxy_TypeOf_obj(JSContext *cx, JSObject *obj)
-{
- return JSTYPE_OBJECT;
-}
-
void
proxy_Finalize(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isProxy());
if (!obj->getSlot(JSSLOT_PROXY_HANDLER).isUndefined())
obj->getProxyHandler()->finalize(cx, obj);
}
-extern JSObjectOps js_ObjectProxyObjectOps;
-
-static const JSObjectMap SharedObjectProxyMap(&js_ObjectProxyObjectOps, JSObjectMap::SHAPELESS);
-
-JSObjectOps js_ObjectProxyObjectOps = {
- &SharedObjectProxyMap,
- proxy_LookupProperty,
- proxy_DefineProperty,
- proxy_GetProperty,
- proxy_SetProperty,
- proxy_GetAttributes,
- proxy_SetAttributes,
- proxy_DeleteProperty,
- js_Enumerate,
- proxy_TypeOf_obj,
- proxy_TraceObject,
- NULL, /* thisObject */
- proxy_Finalize
-};
-
-static JSObjectOps *
-obj_proxy_getObjectOps(JSContext *cx, Class *clasp)
-{
- return &js_ObjectProxyObjectOps;
-}
-
JS_FRIEND_API(Class) ObjectProxyClass = {
"Proxy",
- JSCLASS_HAS_RESERVED_SLOTS(2),
- PropertyStub,
- PropertyStub,
- PropertyStub,
- PropertyStub,
+ Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(2),
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
EnumerateStub,
ResolveStub,
ConvertStub,
- NULL,
- obj_proxy_getObjectOps,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
+ NULL, /* finalize */
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ NULL, /* mark */
+ JS_NULL_CLASS_EXT,
+ {
+ proxy_LookupProperty,
+ proxy_DefineProperty,
+ proxy_GetProperty,
+ proxy_SetProperty,
+ proxy_GetAttributes,
+ proxy_SetAttributes,
+ proxy_DeleteProperty,
+ NULL, /* enumerate */
+ NULL, /* typeof */
+ proxy_TraceObject,
+ NULL, /* thisObject */
+ proxy_Finalize, /* clear */
+ }
};
JSBool
proxy_Call(JSContext *cx, uintN argc, Value *vp)
{
JSObject *proxy = &JS_CALLEE(cx, vp).toObject();
JS_ASSERT(proxy->isProxy());
return JSProxy::call(cx, proxy, argc, vp);
@@ -983,63 +956,51 @@ proxy_Construct(JSContext *cx, JSObject
}
static JSType
proxy_TypeOf_fun(JSContext *cx, JSObject *obj)
{
return JSTYPE_FUNCTION;
}
-extern JSObjectOps js_FunctionProxyObjectOps;
-
-static const JSObjectMap SharedFunctionProxyMap(&js_FunctionProxyObjectOps, JSObjectMap::SHAPELESS);
-
#define proxy_HasInstance js_FunctionClass.hasInstance
-JSObjectOps js_FunctionProxyObjectOps = {
- &SharedFunctionProxyMap,
- proxy_LookupProperty,
- proxy_DefineProperty,
- proxy_GetProperty,
- proxy_SetProperty,
- proxy_GetAttributes,
- proxy_SetAttributes,
- proxy_DeleteProperty,
- js_Enumerate,
- proxy_TypeOf_fun,
- proxy_TraceObject,
- NULL, /* thisObject */
- NULL /* clear */
-};
-
-static JSObjectOps *
-fun_proxy_getObjectOps(JSContext *cx, Class *clasp)
-{
- return &js_FunctionProxyObjectOps;
-}
-
JS_FRIEND_API(Class) FunctionProxyClass = {
"Proxy",
- JSCLASS_HAS_RESERVED_SLOTS(4) | CLASS_CALL_IS_FAST,
- PropertyStub,
- PropertyStub,
- PropertyStub,
- PropertyStub,
+ Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(4) | Class::CALL_IS_FAST,
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
EnumerateStub,
ResolveStub,
ConvertStub,
- NULL,
- fun_proxy_getObjectOps,
- NULL,
+ NULL, /* finalize */
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
CastCallOpAsNative(proxy_Call),
proxy_Construct,
- NULL,
+ NULL, /* xdrObject */
proxy_HasInstance,
- NULL,
- NULL
+ NULL, /* mark */
+ JS_NULL_CLASS_EXT,
+ {
+ proxy_LookupProperty,
+ proxy_DefineProperty,
+ proxy_GetProperty,
+ proxy_SetProperty,
+ proxy_GetAttributes,
+ proxy_SetAttributes,
+ proxy_DeleteProperty,
+ NULL, /* enumerate */
+ proxy_TypeOf_fun,
+ proxy_TraceObject,
+ NULL, /* thisObject */
+ NULL, /* clear */
+ }
};
JS_FRIEND_API(JSObject *)
NewProxyObject(JSContext *cx, JSProxyHandler *handler, const Value &priv, JSObject *proto,
JSObject *parent, JSObject *call, JSObject *construct)
{
bool fun = call || construct;
Class *clasp = fun ? &FunctionProxyClass : &ObjectProxyClass;
@@ -1238,20 +1199,28 @@ callable_Construct(JSContext *cx, JSObje
return true;
}
return InternalCall(cx, obj, fval, argc, argv, rval);
}
Class CallableObjectClass = {
"Function",
JSCLASS_HAS_RESERVED_SLOTS(2),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- NULL, NULL, callable_Call, callable_Construct,
- NULL, NULL, NULL, NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ NULL, /* finalize */
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ callable_Call,
+ callable_Construct,
};
JS_FRIEND_API(JSBool)
FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp)
{
AutoValueRooter tvr(cx);
if (!JSProxy::fix(cx, proxy, tvr.addr()))
return false;
@@ -1299,19 +1268,23 @@ FixProxy(JSContext *cx, JSObject *proxy,
return true;
}
}
Class js_ProxyClass = {
"Proxy",
JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub
};
JS_FRIEND_API(JSObject *)
js_InitProxyClass(JSContext *cx, JSObject *obj)
{
JSObject *module = NewObject(cx, &js_ProxyClass, NULL, obj);
if (!module)
return NULL;
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -341,20 +341,41 @@ typedef JSBool
* The type of ops->call. Same argument types as JSFastNative, but a different
* contract. A JSCallOp expects a dummy stack frame with the caller's
* scopeChain.
*/
typedef JSBool
(* JSCallOp)(JSContext *cx, uintN argc, jsval *vp);
/*
+ * A generic type for functions mapping an object to another object, or null
+ * if an error or exception was thrown on cx.
+ */
+typedef JSObject *
+(* JSObjectOp)(JSContext *cx, JSObject *obj);
+
+/*
+ * Hook that creates an iterator object for a given object. Returns the
+ * iterator object or null if an error or exception was thrown on cx.
+ */
+typedef JSObject *
+(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly);
+
+/*
* The following determines whether JS_EncodeCharacters and JS_DecodeBytes
* treat char[] as utf-8 or simply as bytes that need to be inflated/deflated.
*/
#ifdef JS_C_STRINGS_ARE_UTF8
# define js_CStringsAreUTF8 JS_TRUE
#else
extern JSBool js_CStringsAreUTF8;
#endif
+/*
+ * Hack to expose obj->getOps()->outer to the C implementation of the debugger
+ * interface.
+ */
+extern JS_FRIEND_API(JSObject *)
+js_ObjectToOuterObject(JSContext *cx, JSObject *obj);
+
JS_END_EXTERN_C
#endif /* jsprvtd_h___ */
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -102,17 +102,17 @@ typedef enum JSType {
/* Dense index into cached prototypes and class atoms for standard objects. */
typedef enum JSProtoKey {
#define JS_PROTO(name,code,init) JSProto_##name = code,
#include "jsproto.tbl"
#undef JS_PROTO
JSProto_LIMIT
} JSProtoKey;
-/* JSObjectOps.checkAccess mode enumeration. */
+/* js_CheckAccess mode enumeration. */
typedef enum JSAccessMode {
JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */
JSACC_PARENT = 1, /* XXXbe redundant w.r.t. id */
/*
* enum value #2 formerly called JSACC_IMPORT,
* gap preserved for ABI compatibility.
*/
@@ -140,28 +140,26 @@ typedef enum JSIterateOp {
JSENUMERATE_NEXT,
/* Destroy iterator state. */
JSENUMERATE_DESTROY
} JSIterateOp;
/* Struct typedefs. */
typedef struct JSClass JSClass;
-typedef struct JSExtendedClass JSExtendedClass;
typedef struct JSConstDoubleSpec JSConstDoubleSpec;
typedef struct JSContext JSContext;
typedef struct JSErrorReport JSErrorReport;
typedef struct JSFunction JSFunction;
typedef struct JSFunctionSpec JSFunctionSpec;
typedef struct JSTracer JSTracer;
typedef struct JSIdArray JSIdArray;
typedef struct JSPropertyDescriptor JSPropertyDescriptor;
typedef struct JSPropertySpec JSPropertySpec;
typedef struct JSObjectMap JSObjectMap;
-typedef struct JSObjectOps JSObjectOps;
typedef struct JSRuntime JSRuntime;
typedef struct JSScript JSScript;
typedef struct JSStackFrame JSStackFrame;
typedef struct JSXDRState JSXDRState;
typedef struct JSExceptionState JSExceptionState;
typedef struct JSLocaleCallbacks JSLocaleCallbacks;
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
typedef struct JSONParser JSONParser;
@@ -299,39 +297,16 @@ typedef void
/*
* Used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer
* to extend and reduce the set of string types finalized by the GC.
*/
typedef void
(* JSStringFinalizeOp)(JSContext *cx, JSString *str);
/*
- * The signature for JSClass.getObjectOps, used by JS_NewObject's internals
- * to discover the set of high-level object operations to use for new objects
- * of the given class. All native objects have a JSClass, which is stored as
- * a private (int-tagged) pointer in obj slots. In contrast, all native and
- * host objects have a JSObjectMap at obj->map, which may be shared among a
- * number of objects, and which contains the JSObjectOps *ops pointer used to
- * dispatch object operations from API calls.
- *
- * Thus JSClass (which pre-dates JSObjectOps in the API) provides a low-level
- * interface to class-specific code and data, while JSObjectOps allows for a
- * higher level of operation, which does not use the object's class except to
- * find the class's JSObjectOps struct, by calling clasp->getObjectOps, and to
- * finalize the object.
- *
- * If this seems backwards, that's because it is! API compatibility requires
- * a JSClass *clasp parameter to JS_NewObject, etc. Most host objects do not
- * need to implement the larger JSObjectOps, and can share the common JSScope
- * code and data used by the native (js_ObjectOps, see jsobj.c) ops.
- */
-typedef JSObjectOps *
-(* JSGetObjectOps)(JSContext *cx, JSClass *clasp);
-
-/*
* JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
* returning false on error/exception, true on success with obj[id]'s last-got
* value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id
* is either a string or an int jsval.
*/
typedef JSBool
(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
jsval *vp);
@@ -413,36 +388,19 @@ typedef void
/*
* DEBUG only callback that JSTraceOp implementation can provide to return
* a string describing the reference traced with JS_CallTracer.
*/
typedef void
(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
-/* JSExtendedClass function pointer typedefs. */
-
typedef JSBool
(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
-/*
- * A generic type for functions mapping an object to another object, or null
- * if an error or exception was thrown on cx. Used by JSObjectOps.thisObject
- * at present.
- */
-typedef JSObject *
-(* JSObjectOp)(JSContext *cx, JSObject *obj);
-
-/*
- * Hook that creates an iterator object for a given object. Returns the
- * iterator object or null if an error or exception was thrown on cx.
- */
-typedef JSObject *
-(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly);
-
/* Typedef for native functions called by the JS VM. */
typedef JSBool
(* JSNative)(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
/* See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros. */
typedef JSBool
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -5412,24 +5412,31 @@ regexp_trace(JSTracer *trc, JSObject *ob
JS_CALL_STRING_TRACER(trc, re->source, "source");
}
Class js_RegExpClass = {
js_RegExp_str,
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::REGEXP_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
- PropertyStub, PropertyStub,
- PropertyStub, PropertyStub,
- regexp_enumerate, reinterpret_cast<JSResolveOp>(regexp_resolve),
- ConvertStub, regexp_finalize,
- NULL, NULL,
- regexp_call, NULL,
- js_XDRRegExpObject, NULL,
- JS_CLASS_TRACE(regexp_trace), 0
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ regexp_enumerate,
+ reinterpret_cast<JSResolveOp>(regexp_resolve),
+ ConvertStub,
+ regexp_finalize,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ regexp_call,
+ NULL, /* construct */
+ js_XDRRegExpObject,
+ NULL, /* hasInstance */
+ JS_CLASS_TRACE(regexp_trace)
};
static const jschar empty_regexp_ucstr[] = {'(', '?', ':', ')', 0};
JSBool
js_regexp_toString(JSContext *cx, JSObject *obj, Value *vp)
{
JSRegExp *re;
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -81,30 +81,30 @@ js_GenerateShape(JSContext *cx, bool gcL
/*
* FIXME bug 440834: The shape id space has overflowed. Currently we
* cope badly with this and schedule the GC on the every call. But
* first we make sure that increments from other threads would not
* have a chance to wrap around shapeGen to zero.
*/
rt->shapeGen = SHAPE_OVERFLOW_BIT;
shape = SHAPE_OVERFLOW_BIT;
- cx->runtime->triggerGC(gcLocked);
+ js_TriggerGC(cx, gcLocked);
}
return shape;
}
JSScope *
js_GetMutableScope(JSContext *cx, JSObject *obj)
{
JSScope *scope = obj->scope();
JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
if (!scope->isSharedEmpty())
return scope;
- JSScope *newscope = JSScope::create(cx, scope->ops, obj->getClass(), obj, scope->shape);
+ JSScope *newscope = JSScope::create(cx, obj->getClass(), obj, scope->shape);
if (!newscope)
return NULL;
/* The newly allocated scope is single-threaded and, as such, is locked. */
JS_ASSERT(CX_OWNS_SCOPE_TITLE(cx, newscope));
JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, newscope));
obj->map = newscope;
@@ -195,52 +195,49 @@ JSScope::createTable(JSContext *cx, bool
table = (JSScopeProperty **) js_calloc(JS_BIT(sizeLog2) * sizeof(JSScopeProperty *));
if (!table) {
if (report)
JS_ReportOutOfMemory(cx);
METER(tableAllocFails);
return false;
}
- cx->runtime->updateMallocCounter(JS_BIT(sizeLog2) * sizeof(JSScopeProperty *));
+ cx->updateMallocCounter(JS_BIT(sizeLog2) * sizeof(JSScopeProperty *));
hashShift = JS_DHASH_BITS - sizeLog2;
for (sprop = lastProp; sprop; sprop = sprop->parent) {
spp = search(sprop->id, true);
SPROP_STORE_PRESERVING_COLLISION(spp, sprop);
}
return true;
}
JSScope *
-JSScope::create(JSContext *cx, const JSObjectOps *ops, Class *clasp,
- JSObject *obj, uint32 shape)
+JSScope::create(JSContext *cx, Class *clasp, JSObject *obj, uint32 shape)
{
- JS_ASSERT(ops->isNative());
JS_ASSERT(obj);
- JSScope *scope = cx->create<JSScope>(ops, obj);
+ JSScope *scope = cx->create<JSScope>(obj);
if (!scope)
return NULL;
scope->freeslot = JSSLOT_START(clasp);
scope->flags = cx->runtime->gcRegenShapesScopeFlag;
scope->initMinimal(cx, shape);
#ifdef JS_THREADSAFE
js_InitTitle(cx, &scope->title);
#endif
JS_RUNTIME_METER(cx->runtime, liveScopes);
JS_RUNTIME_METER(cx->runtime, totalScopes);
return scope;
}
-JSEmptyScope::JSEmptyScope(JSContext *cx, const JSObjectOps *ops,
- Class *clasp)
- : JSScope(ops, NULL), clasp(clasp)
+JSEmptyScope::JSEmptyScope(JSContext *cx, Class *clasp)
+ : JSScope(NULL), clasp(clasp)
{
/*
* This scope holds a reference to the new empty scope. Our only caller,
* getEmptyScope, also promises to incref on behalf of its caller.
*/
nrefs = 2;
freeslot = JSSLOT_START(clasp);
flags = OWN_SHAPE | cx->runtime->gcRegenShapesScopeFlag;
@@ -285,24 +282,24 @@ JSScope::destroy(JSContext *cx)
bool
JSScope::initRuntimeState(JSContext *cx)
{
JSRuntime *rt = cx->runtime;
#define SCOPE(Name) rt->empty##Name##Scope
#define CLASP(Name) &js_##Name##Class
-#define INIT_EMPTY_SCOPE(Name,NAME,ops) \
- INIT_EMPTY_SCOPE_WITH_CLASS(Name, NAME, ops, CLASP(Name))
+#define INIT_EMPTY_SCOPE(Name,NAME) \
+ INIT_EMPTY_SCOPE_WITH_CLASS(Name, NAME, CLASP(Name))
-#define INIT_EMPTY_SCOPE_WITH_CLASS(Name,NAME,ops,clasp) \
- INIT_EMPTY_SCOPE_WITH_FREESLOT(Name, NAME, ops, clasp, JSSLOT_FREE(clasp))
+#define INIT_EMPTY_SCOPE_WITH_CLASS(Name,NAME,clasp) \
+ INIT_EMPTY_SCOPE_WITH_FREESLOT(Name, NAME, clasp, JSSLOT_FREE(clasp))
-#define INIT_EMPTY_SCOPE_WITH_FREESLOT(Name,NAME,ops,clasp,slot) \
- SCOPE(Name) = cx->create<JSEmptyScope>(cx, ops, clasp); \
+#define INIT_EMPTY_SCOPE_WITH_FREESLOT(Name,NAME,clasp,slot) \
+ SCOPE(Name) = cx->create<JSEmptyScope>(cx, clasp); \
if (!SCOPE(Name)) \
return false; \
JS_ASSERT(SCOPE(Name)->shape == JSScope::EMPTY_##NAME##_SHAPE); \
JS_ASSERT(SCOPE(Name)->nrefs == 2); \
SCOPE(Name)->nrefs = 1; \
SCOPE(Name)->freeslot = slot
/*
@@ -318,39 +315,39 @@ JSScope::initRuntimeState(JSContext *cx)
* is less than freeslot to succeed. As the shared emptyArgumentsScope is
* never mutated, it's safe to pretend to have all the slots possible.
*
* Note how the fast paths in jsinterp.cpp for JSOP_LENGTH and JSOP_GETELEM
* bypass resolution of scope properties for length and element indices on
* arguments objects. This helps ensure that any arguments object needing
* its own mutable scope (with unique shape) is a rare event.
*/
- INIT_EMPTY_SCOPE_WITH_FREESLOT(Arguments, ARGUMENTS, &js_ObjectOps, CLASP(Arguments),
+ INIT_EMPTY_SCOPE_WITH_FREESLOT(Arguments, ARGUMENTS, CLASP(Arguments),
JS_INITIAL_NSLOTS + JS_ARGS_LENGTH_MAX);
- INIT_EMPTY_SCOPE(Block, BLOCK, &js_ObjectOps);
+ INIT_EMPTY_SCOPE(Block, BLOCK);
/*
* Initialize the shared scope for all empty Call objects so gets for args
* and vars do not force the creation of a mutable scope for the particular
* call object being accessed.
*
* See comment above for rt->emptyArgumentsScope->freeslot initialization.
*/
- INIT_EMPTY_SCOPE_WITH_FREESLOT(Call, CALL, &js_ObjectOps, CLASP(Call),
+ INIT_EMPTY_SCOPE_WITH_FREESLOT(Call, CALL, CLASP(Call),
JS_INITIAL_NSLOTS + JSFunction::MAX_ARGS_AND_VARS);
/* A DeclEnv object holds the name binding for a named function expression. */
- INIT_EMPTY_SCOPE(DeclEnv, DECL_ENV, &js_ObjectOps);
+ INIT_EMPTY_SCOPE(DeclEnv, DECL_ENV);
/* Non-escaping native enumerator objects share this empty scope. */
- INIT_EMPTY_SCOPE_WITH_CLASS(Enumerator, ENUMERATOR, &js_ObjectOps, &js_IteratorClass.base);
+ INIT_EMPTY_SCOPE_WITH_CLASS(Enumerator, ENUMERATOR, &js_IteratorClass);
/* Same drill for With objects. */
- INIT_EMPTY_SCOPE(With, WITH, &js_WithObjectOps);
+ INIT_EMPTY_SCOPE_WITH_CLASS(With, WITH, &js_WithClass);
#undef SCOPE
#undef CLASP
#undef INIT_EMPTY_SCOPE
#undef INIT_EMPTY_SCOPE_WITH_CLASS
#undef INIT_EMPTY_SCOPE_WITH_FREESLOT
return true;
@@ -511,17 +508,17 @@ JSScope::changeTable(JSContext *cx, int
/* Now that we have newtable allocated, update members. */
hashShift = JS_DHASH_BITS - newlog2;
removedCount = 0;
oldtable = table;
table = newtable;
/* Treat the above calloc as a JS_malloc, to match CreateScopeTable. */
- cx->runtime->updateMallocCounter(nbytes);
+ cx->updateMallocCounter(nbytes);
/* Copy only live entries, leaving removed and free ones behind. */
for (oldspp = oldtable; oldsize != 0; oldspp++) {
sprop = SPROP_FETCH(oldspp);
if (sprop) {
spp = search(sprop->id, true);
JS_ASSERT(SPROP_IS_FREE(*spp));
*spp = sprop;
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -287,37 +287,36 @@ struct JSScope : public JSObjectMap
JSScopeProperty *addPropertyHelper(JSContext *cx, jsid id,
js::PropertyOp getter, js::PropertyOp setter,
uint32 slot, uintN attrs,
uintN flags, intN shortid,
JSScopeProperty **spp);
public:
- JSScope(const JSObjectOps *ops, JSObject *obj)
- : JSObjectMap(ops, 0), object(obj) {}
+ JSScope(JSObject *obj)
+ : JSObjectMap(0), object(obj) {}
/* Create a mutable, owned, empty scope. */
- static JSScope *create(JSContext *cx, const JSObjectOps *ops,
- js::Class *clasp, JSObject *obj, uint32 shape);
+ static JSScope *create(JSContext *cx, js::Class *clasp, JSObject *obj, uint32 shape);
void destroy(JSContext *cx);
/*
* Return an immutable, shareable, empty scope with the same ops as this
* and the same freeslot as this had when empty.
*
* If |this| is the scope of an object |proto|, the resulting scope can be
* used as the scope of a new object whose prototype is |proto|.
*/
inline JSEmptyScope *getEmptyScope(JSContext *cx, js::Class *clasp);
inline bool ensureEmptyScope(JSContext *cx, js::Class *clasp);
- inline bool canProvideEmptyScope(JSObjectOps *ops, js::Class *clasp);
+ inline bool canProvideEmptyScope(js::Class *clasp);
JSScopeProperty *lookup(jsid id);
inline bool hasProperty(jsid id) { return lookup(id) != NULL; }
inline bool hasProperty(JSScopeProperty *sprop);
/* Add a property whose id is not yet in this scope. */
JSScopeProperty *addProperty(JSContext *cx, jsid id,
@@ -450,18 +449,18 @@ struct JSScope : public JSObjectMap
void setIndexedProperties() { flags |= INDEXED_PROPERTIES; }
bool hasOwnShape() { return flags & OWN_SHAPE; }
bool hasRegenFlag(uint8 regenFlag) { return (flags & SHAPE_REGEN) == regenFlag; }
/*
* A scope has a method barrier when some compiler-created "null closure"
- * function objects (functions that do not use lexical bindings above their
- * scope, only free variable names) that have a correct JSSLOT_PARENT value
+ * function objects (functions that do not use lexical bindings above
+ * their scope, only free variable names) that have a correct parent value
* thanks to the COMPILE_N_GO optimization are stored as newly added direct
* property values of the scope's object.
*
* The de-facto standard JS language requires each evaluation of such a
* closure to result in a unique (according to === and observable effects)
* function object. ES3 tried to allow implementations to "join" such
* objects to a single compiler-created object, but this makes an overt
* mutation hazard, also an "identity hazard" against interoperation among
@@ -521,17 +520,17 @@ struct JSScope : public JSObjectMap
};
};
struct JSEmptyScope : public JSScope
{
js::Class * const clasp;
jsrefcount nrefs; /* count of all referencing objects */
- JSEmptyScope(JSContext *cx, const JSObjectOps *ops, js::Class *clasp);
+ JSEmptyScope(JSContext *cx, js::Class *clasp);
JSEmptyScope *hold() {
/* The method is only called for already held objects. */
JS_ASSERT(nrefs >= 1);
JS_ATOMIC_INCREMENT(&nrefs);
return this;
}
@@ -893,16 +892,20 @@ JSScope::insertDictionaryProperty(JSScop
*/
#define SPROP_USERID(sprop) \
((sprop)->hasShortID() ? INT_TO_JSID((sprop)->shortid) \
: (sprop)->id)
#define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot)
#define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope)
+#ifndef JS_THREADSAFE
+# define js_GenerateShape(cx, gcLocked) js_GenerateShape (cx)
+#endif
+
extern uint32
js_GenerateShape(JSContext *cx, bool gcLocked);
#ifdef DEBUG
struct JSScopeStats {
jsrefcount searches;
jsrefcount hits;
jsrefcount misses;
@@ -953,25 +956,25 @@ JSScope::search(jsid id, bool adding)
return spp;
}
return searchTable(id, adding);
}
#undef METER
inline bool
-JSScope::canProvideEmptyScope(JSObjectOps *ops, js::Class *clasp)
+JSScope::canProvideEmptyScope(js::Class *clasp)
{
/*
* An empty scope cannot provide another empty scope, or wrongful two-level
* prototype shape sharing ensues -- see bug 497789.
*/
if (!object)
return false;
- return this->ops == ops && (!emptyScope || emptyScope->clasp == clasp);
+ return !emptyScope || emptyScope->clasp == clasp;
}
inline bool
JSScopeProperty::isSharedPermanent() const
{
return (~attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0;
}
--- a/js/src/jsscopeinlines.h
+++ b/js/src/jsscopeinlines.h
@@ -48,17 +48,17 @@
#include "jscntxtinlines.h"
inline JSEmptyScope *
JSScope::createEmptyScope(JSContext *cx, js::Class *clasp)
{
JS_ASSERT(!isSharedEmpty());
JS_ASSERT(!emptyScope);
- emptyScope = cx->create<JSEmptyScope>(cx, ops, clasp);
+ emptyScope = cx->create<JSEmptyScope>(cx, clasp);
return emptyScope;
}
inline JSEmptyScope *
JSScope::getEmptyScope(JSContext *cx, js::Class *clasp)
{
if (emptyScope) {
JS_ASSERT(clasp == emptyScope->clasp);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -415,20 +415,31 @@ script_trace(JSTracer *trc, JSObject *ob
if (script)
js_TraceScript(trc, script);
}
Class js_ScriptClass = {
"Script",
JSCLASS_HAS_PRIVATE |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, script_finalize,
- NULL, NULL, NULL, NULL,/*XXXbe xdr*/
- NULL, NULL, JS_CLASS_TRACE(script_trace), NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ script_finalize,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ JS_CLASS_TRACE(script_trace)
};
/*
* Shared script filename management.
*/
static int
js_compare_strings(const void *k1, const void *k2)
{
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -801,19 +801,23 @@ str_resolve(JSContext *cx, JSObject *obj
}
return JS_TRUE;
}
Class js_StringClass = {
js_String_str,
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_CACHED_PROTO(JSProto_String),
- PropertyStub, PropertyStub, str_getProperty, PropertyStub,
- str_enumerate, (JSResolveOp)str_resolve, ConvertStub, NULL,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ str_getProperty,
+ PropertyStub, /* setProperty */
+ str_enumerate,
+ (JSResolveOp)str_resolve,
+ ConvertStub
};
#define NORMALIZE_THIS(cx,vp,str) \
JS_BEGIN_MACRO \
if (vp[1].isString()) { \
str = vp[1].toString(); \
} else { \
str = NormalizeThis(cx, vp); \
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -2906,17 +2906,17 @@ NativeToValue(JSContext* cx, Value& v, J
}
case JSVAL_TYPE_STRORNULL:
debug_only_printf(LC_TMTracer, "nullablestr<%p> ", v.isNull() ? NULL : (void *)v.toString());
break;
case JSVAL_TYPE_OBJORNULL:
debug_only_printf(LC_TMTracer, "nullablestr<%p> ", v.isNull() ? NULL : (void *)&v.toObject());
break;
case JSVAL_TYPE_BOXED:
- debug_only_printf(LC_TMTracer, "box<%llx> ", v.asRawBits());
+ debug_only_printf(LC_TMTracer, "box<%llx> ", (long long unsigned int)v.asRawBits());
break;
default:
JS_NOT_REACHED("unexpected type");
break;
}
#endif
}
@@ -3002,16 +3002,17 @@ public:
mCx(cx),
mTypeMap(typeMap),
mGlobal(global)
{}
JS_REQUIRES_STACK JS_ALWAYS_INLINE void
visitGlobalSlot(Value *vp, unsigned n, unsigned slot) {
debug_only_printf(LC_TMTracer, "global%d=", n);
+ JS_ASSERT(JS_THREAD_DATA(mCx)->waiveGCQuota);
NativeToValue(mCx, *vp, *mTypeMap++, &mGlobal[slot]);
}
};
class FlushNativeStackFrameVisitor : public SlotVisitorBase
{
JSContext *mCx;
const JSValueType *mInitTypeMap;
@@ -3035,31 +3036,33 @@ public:
const JSValueType* getTypeMap()
{
return mTypeMap;
}
JS_REQUIRES_STACK JS_ALWAYS_INLINE bool
visitStackSlots(Value *vp, size_t count, JSStackFrame* fp) {
+ JS_ASSERT(JS_THREAD_DATA(mCx)->waiveGCQuota);
for (size_t i = 0; i < count; ++i) {
if (vp == mStop)
return false;
debug_only_printf(LC_TMTracer, "%s%u=", stackSlotKind(), unsigned(i));
if (unsigned(mTypeMap - mInitTypeMap) >= mIgnoreSlots)
NativeToValue(mCx, *vp, *mTypeMap, mStack);
vp++;
mTypeMap++;
mStack++;
}
return true;
}
JS_REQUIRES_STACK JS_ALWAYS_INLINE bool
visitFrameObjPtr(JSObject **p, JSStackFrame* fp) {
+ JS_ASSERT(JS_THREAD_DATA(mCx)->waiveGCQuota);
if ((Value *)p == mStop)
return false;
debug_only_printf(LC_TMTracer, "%s%u=", stackSlotKind(), 0);
if (unsigned(mTypeMap - mInitTypeMap) >= mIgnoreSlots) {
*p = *(JSObject **)mStack;
#ifdef DEBUG
JSValueType type = *mTypeMap;
if (type == JSVAL_TYPE_NULL) {
@@ -6743,23 +6746,41 @@ ExecuteTree(JSContext* cx, TreeFragment*
LeaveTree(tm, state, lr);
*lrp = state.innermost;
bool ok = !(state.builtinStatus & BUILTIN_ERROR);
JS_ASSERT_IF(cx->throwing, !ok);
return ok;
}
+class Guardian {
+ bool *flagp;
+public:
+ Guardian(bool *flagp) {
+ this->flagp = flagp;
+ JS_ASSERT(!*flagp);
+ *flagp = true;
+ }
+
+ ~Guardian() {
+ JS_ASSERT(*flagp);
+ *flagp = false;
+ }
+};
+
static JS_FORCES_STACK void
LeaveTree(TraceMonitor *tm, TracerState& state, VMSideExit* lr)
{
VOUCH_DOES_NOT_REQUIRE_STACK();
JSContext* cx = state.cx;
+ /* Temporary waive the soft GC quota to make sure LeaveTree() doesn't fail. */
+ Guardian waiver(&JS_THREAD_DATA(cx)->waiveGCQuota);
+
FrameInfo** callstack = state.callstackBase;
double* stack = state.stackBase;
/*
* Except if we find that this is a nested bailout, the guard the call
* returned is the one we have to use to adjust pc and sp.
*/
VMSideExit* innermost = lr;
@@ -8965,18 +8986,17 @@ TraceRecorder::equalityHelper(Value& l,
*/
if (getPromotedType(l) == getPromotedType(r)) {
if (l.isUndefined() || l.isNull()) {
cond = true;
if (l.isNull())
op = LIR_eqp;
} else if (l.isObject()) {
- Class *clasp = l.toObject().getClass();
- if ((clasp->flags & JSCLASS_IS_EXTENDED) && ((JSExtendedClass*) clasp)->equality)
+ if (l.toObject().getClass()->ext.equality)
RETURN_STOP_A("Can't trace extended class equality operator");
op = LIR_eqp;
cond = (l == r);
} else if (l.isBoolean()) {
JS_ASSERT(r.isBoolean());
cond = (l == r);
} else if (l.isString()) {
args[0] = r_ins, args[1] = l_ins;
@@ -9376,18 +9396,16 @@ void
TraceRecorder::forgetGuardedShapes()
{
#if defined DEBUG_notme && defined XP_UNIX
dumpGuardedShapes("forget-all");
#endif
guardedShapeTable.clear();
}
-JS_STATIC_ASSERT(offsetof(JSObjectOps, objectMap) == 0);
-
inline LIns*
TraceRecorder::map(LIns* obj_ins)
{
return addName(lir->insLoad(LIR_ldp, obj_ins, (int) offsetof(JSObject, map), ACCSET_OTHER), "map");
}
JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2, PCVal& pcval)
@@ -9964,17 +9982,17 @@ TraceRecorder::box_value_into_alloc(cons
return alloc_ins;
}
#endif /* JS_BITS_PER_WORD */
LIns*
TraceRecorder::stobj_get_parent(nanojit::LIns* obj_ins)
{
- return stobj_get_fslot_ptr(obj_ins, JSSLOT_PARENT);
+ return lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, parent), ACCSET_OTHER);
}
LIns*
TraceRecorder::stobj_get_private(nanojit::LIns* obj_ins)
{
return stobj_get_fslot_ptr(obj_ins, JSSLOT_PRIVATE);
}
@@ -11385,17 +11403,17 @@ TraceRecorder::callNative(uintN argc, JS
JS_ASSERT(((jsuword) clasp & 3) == 0);
// Abort on |new Function|. js_NewInstance would allocate a regular-
// sized JSObject, not a Function-sized one. (The Function ctor would
// deep-bail anyway but let's not go there.)
if (clasp == &js_FunctionClass)
RETURN_STOP("new Function");
- if (clasp->getObjectOps)
+ if (!clasp->isNative())
RETURN_STOP("new with non-native ops");
args[0] = INS_CONSTOBJ(funobj);
args[1] = INS_CONSTPTR(clasp);
args[2] = cx_ins;
newobj_ins = lir->insCall(&js_NewInstance_ci, args);
guard(false, lir->insEqP_0(newobj_ins), OOM_EXIT);
this_ins = newobj_ins;
@@ -11813,17 +11831,17 @@ TraceRecorder::record_JSOP_GETPROP()
JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::record_JSOP_SETPROP()
{
Value& l = stackval(-2);
if (l.isPrimitive())
RETURN_STOP_A("primitive this for SETPROP");
JSObject* obj = &l.toObject();
- if (obj->map->ops->setProperty != js_SetProperty)
+ if (obj->getOps()->setProperty)
RETURN_STOP_A("non-native JSObjectOps::setProperty");
return ARECORD_CONTINUE;
}
/* Emit a specialized, inlined copy of js_NativeSet. */
JS_REQUIRES_STACK RecordingStatus
TraceRecorder::nativeSet(JSObject* obj, LIns* obj_ins, JSScopeProperty* sprop,
const Value &v, LIns* v_ins)
@@ -13520,17 +13538,17 @@ TraceRecorder::prop(JSObject* obj, LIns*
{
/*
* Insist that obj have js_SetProperty as its set object-op. This suffices
* to prevent a rogue obj from being used on-trace (loaded via obj_ins),
* because we will guard on shape (or else global object identity) and any
* object not having the same op must have a different class, and therefore
* must differ in its shape (or not be the global object).
*/
- if (!obj->isDenseArray() && obj->map->ops->getProperty != js_GetProperty)
+ if (!obj->isDenseArray() && obj->getOps()->getProperty)
RETURN_STOP_A("non-dense-array, non-native JSObjectOps::getProperty");
JS_ASSERT((slotp && v_insp && !outp) || (!slotp && !v_insp && outp));
/*
* Property cache ensures that we are dealing with an existing property,
* and guards the shape for us.
*/
@@ -14203,34 +14221,34 @@ TraceRecorder::record_JSOP_MOREITER()
RETURN_IF_XML_A(iterobj_val);
JSObject* iterobj = &iterobj_val.toObject();
LIns* iterobj_ins = get(&iterobj_val);
bool cond;
LIns* cond_ins;
/* JSOP_FOR* already guards on this, but in certain rare cases we might record misformed loop traces. */
- if (iterobj->hasClass(&js_IteratorClass.base)) {
- guardClass(iterobj_ins, &js_IteratorClass.base, snapshot(BRANCH_EXIT), LOAD_NORMAL);
+ if (iterobj->hasClass(&js_IteratorClass)) {
+ guardClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL);
NativeIterator *ni = (NativeIterator *) iterobj->getPrivate();
void *cursor = ni->props_cursor;
void *end = ni->props_end;
LIns *ni_ins = stobj_get_const_private_ptr(iterobj_ins);
LIns *cursor_ins =
addName(lir->insLoad(LIR_ldp, ni_ins,
offsetof(NativeIterator, props_cursor), ACCSET_OTHER), "cursor");
LIns *end_ins = addName(lir->insLoad(LIR_ldp, ni_ins, offsetof(NativeIterator, props_end),
ACCSET_OTHER), "end");
/* Figure out whether the native iterator contains more values. */
cond = cursor < end;
cond_ins = lir->ins2(LIR_ltp, cursor_ins, end_ins);
} else {
- guardNotClass(iterobj_ins, &js_IteratorClass.base, snapshot(BRANCH_EXIT), LOAD_NORMAL);
+ guardNotClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL);
enterDeepBailCall();
LIns* vp_ins = lir->insAlloc(sizeof(Value));
LIns* args[] = { vp_ins, iterobj_ins, cx_ins };
LIns* ok_ins = lir->insCall(&IteratorMore_ci, args);
/*
@@ -14318,18 +14336,18 @@ TraceRecorder::storeMagic(JSWhyMagic why
JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::unboxNextValue(LIns* &v_ins)
{
Value &iterobj_val = stackval(-1);
JSObject *iterobj = &iterobj_val.toObject();
LIns* iterobj_ins = get(&iterobj_val);
- if (iterobj->hasClass(&js_IteratorClass.base)) {
- guardClass(iterobj_ins, &js_IteratorClass.base, snapshot(BRANCH_EXIT), LOAD_NORMAL);
+ if (iterobj->hasClass(&js_IteratorClass)) {
+ guardClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL);
NativeIterator *ni = (NativeIterator *) iterobj->getPrivate();
LIns *ni_ins = stobj_get_const_private_ptr(iterobj_ins);
LIns *cursor_ins = addName(lir->insLoad(LIR_ldp, ni_ins, offsetof(NativeIterator, props_cursor), ACCSET_OTHER), "cursor");
/* Emit code to stringify the id if necessary. */
if (!(((NativeIterator *) iterobj->getPrivate())->flags & JSITER_FOREACH)) {
/* Read the next id from the iterator. */
@@ -14359,19 +14377,20 @@ TraceRecorder::unboxNextValue(LIns* &v_i
/* Read the next value from the iterator. */
Value v = *ni->currentValue();
v_ins = unbox_value(v, cursor_ins, 0, snapshot(BRANCH_EXIT));
/* Increment the cursor by one Value and store it back. */
cursor_ins = lir->ins2(LIR_addp, cursor_ins, INS_CONSTWORD(sizeof(Value)));
}
- lir->insStore(LIR_stp, cursor_ins, ni_ins, offsetof(NativeIterator, props_cursor), ACCSET_OTHER);
- } else {
- guardNotClass(iterobj_ins, &js_IteratorClass.base, snapshot(BRANCH_EXIT), LOAD_NORMAL);
+ lir->insStore(LIR_stp, cursor_ins, ni_ins, offsetof(NativeIterator, props_cursor),
+ ACCSET_OTHER);
+ } else {
+ guardNotClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL);
v_ins = unbox_value(cx->iterValue, cx_ins, offsetof(JSContext, iterValue),
snapshot(BRANCH_EXIT));
storeMagic(JS_NO_ITER_VALUE, cx_ins, offsetof(JSContext, iterValue), ACCSET_OTHER);
}
return ARECORD_CONTINUE;
}
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -313,19 +313,16 @@ TypedArray::obj_lookupProperty(JSContext
return proto->lookupProperty(cx, id, objp, propp);
}
void
TypedArray::obj_trace(JSTracer *trc, JSObject *obj)
{
TypedArray *tarray = fromJSObject(obj);
JS_ASSERT(tarray);
-
- obj->traceProtoAndParent(trc);
-
JS_CALL_OBJECT_TRACER(trc, tarray->bufferJS, "typedarray.buffer");
}
JSBool
TypedArray::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
{
*attrsp = (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
? JSPROP_PERMANENT | JSPROP_READONLY
@@ -488,36 +485,28 @@ class TypedArrayTemplate
: public TypedArray
{
public:
typedef TypedArrayTemplate<NativeType> ThisTypeArray;
static const int ArrayTypeID() { return TypeIDOfType<NativeType>(); }
static const bool ArrayTypeIsUnsigned() { return TypeIsUnsigned<NativeType>(); }
static const bool ArrayTypeIsFloatingPoint() { return TypeIsFloatingPoint<NativeType>(); }
- static JSObjectOps fastObjectOps;
- static JSObjectMap fastObjectMap;
-
static JSFunctionSpec jsfuncs[];
static inline Class *slowClass()
{
return &TypedArray::slowClasses[ArrayTypeID()];
}
static inline Class *fastClass()
{
return &TypedArray::fastClasses[ArrayTypeID()];
}
- static JSObjectOps *getObjectOps(JSContext *cx, Class *clasp)
- {
- return &fastObjectOps;
- }
-
static JSBool
obj_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
JS_ASSERT(tarray);
if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
vp->setNumber(tarray->length);
@@ -921,17 +910,17 @@ class TypedArrayTemplate
// helper used by both the constructor and Slice()
static void
makeFastWithPrivate(JSContext *cx, JSObject *obj, ThisTypeArray *tarray)
{
JS_ASSERT(obj->getClass() == slowClass());
obj->setPrivate(tarray);
obj->clasp = fastClass();
- obj->map = &fastObjectMap;
+ obj->map = const_cast<JSObjectMap *>(&JSObjectMap::sharedNonNative);
}
public:
TypedArrayTemplate() { }
bool
init(JSContext *cx, uint32 len)
{
@@ -1259,19 +1248,24 @@ TypedArrayTemplate<double>::copyIndexToV
/*
* ArrayBuffer (base)
*/
Class ArrayBuffer::jsclass = {
"ArrayBuffer",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayBuffer),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, ArrayBuffer::class_finalize,
- JSCLASS_NO_OPTIONAL_MEMBERS
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ ArrayBuffer::class_finalize,
};
JSPropertySpec ArrayBuffer::jsprops[] = {
{ "byteLength",
-1, JSPROP_SHARED | JSPROP_PERMANENT | JSPROP_READONLY,
Jsvalify(ArrayBuffer::prop_getByteLength), Jsvalify(ArrayBuffer::prop_getByteLength) },
{0,0,0,0,0}
};
@@ -1296,56 +1290,69 @@ JSPropertySpec TypedArray::jsprops[] = {
{0,0,0,0,0}
};
/*
* TypedArray boilerplate
*/
#define IMPL_TYPED_ARRAY_STATICS(_typedArray) \
-template<> JSObjectMap _typedArray::fastObjectMap(&_typedArray::fastObjectOps, \
- JSObjectMap::SHAPELESS); \
-template<> JSObjectOps _typedArray::fastObjectOps = { \
- &_typedArray::fastObjectMap, \
- _typedArray::obj_lookupProperty, \
- _typedArray::obj_defineProperty, \
- _typedArray::obj_getProperty, \
- _typedArray::obj_setProperty, \
- _typedArray::obj_getAttributes, \
- _typedArray::obj_setAttributes, \
- _typedArray::obj_deleteProperty, \
- _typedArray::obj_enumerate, \
- _typedArray::obj_typeOf, \
- _typedArray::obj_trace, \
- NULL, /* thisObject */ \
- NULL /* clear */ \
-}; \
template<> JSFunctionSpec _typedArray::jsfuncs[] = { \
JS_FN("slice", _typedArray::fun_slice, 2, 0), \
JS_FS_END \
}
#define IMPL_TYPED_ARRAY_SLOW_CLASS(_typedArray) \
{ \
#_typedArray, \
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray), \
- PropertyStub, PropertyStub, PropertyStub, PropertyStub, \
- EnumerateStub, ResolveStub, ConvertStub, FinalizeStub, \
- JSCLASS_NO_OPTIONAL_MEMBERS \
+ PropertyStub, /* addProperty */ \
+ PropertyStub, /* delProperty */ \
+ PropertyStub, /* getProperty */ \
+ PropertyStub, /* setProperty */ \
+ EnumerateStub, \
+ ResolveStub, \
+ ConvertStub, \
+ FinalizeStub \
}
#define IMPL_TYPED_ARRAY_FAST_CLASS(_typedArray) \
{ \
#_typedArray, \
- JSCLASS_HAS_PRIVATE, \
- PropertyStub, PropertyStub, PropertyStub, PropertyStub, \
- EnumerateStub, ResolveStub, ConvertStub, \
+ Class::NON_NATIVE | JSCLASS_HAS_PRIVATE, \
+ PropertyStub, /* addProperty */ \
+ PropertyStub, /* delProperty */ \
+ PropertyStub, /* getProperty */ \
+ PropertyStub, /* setProperty */ \
+ EnumerateStub, \
+ ResolveStub, \
+ ConvertStub, \
_typedArray::class_finalize, \
- _typedArray::getObjectOps, NULL, NULL, NULL, \
- NULL, NULL, NULL, NULL \
+ NULL, /* reserved0 */ \
+ NULL, /* checkAccess */ \
+ NULL, /* call */ \
+ NULL, /* construct */ \
+ NULL, /* xdrObject */ \
+ NULL, /* hasInstance */ \
+ NULL, /* mark */ \
+ JS_NULL_CLASS_EXT, \
+ { \
+ _typedArray::obj_lookupProperty, \
+ _typedArray::obj_defineProperty, \
+ _typedArray::obj_getProperty, \
+ _typedArray::obj_setProperty, \
+ _typedArray::obj_getAttributes, \
+ _typedArray::obj_setAttributes, \
+ _typedArray::obj_deleteProperty, \
+ _typedArray::obj_enumerate, \
+ _typedArray::obj_typeOf, \
+ _typedArray::obj_trace, \
+ NULL, /* thisObject */ \
+ NULL, /* clear */ \
+ } \
}
#define INIT_TYPED_ARRAY_CLASS(_typedArray,_type) \
do { \
proto = js_InitClass(cx, obj, NULL, \
&TypedArray::slowClasses[TypedArray::_type], \
_typedArray::class_constructor, 3, \
_typedArray::jsprops, \
--- a/js/src/jsvalue.h
+++ b/js/src/jsvalue.h
@@ -774,18 +774,16 @@ typedef JSBool
typedef JSBool
(* NewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
Value *statep, jsid *idp);
typedef JSBool
(* HasInstanceOp)(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp);
typedef JSBool
(* CheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
Value *vp);
-typedef JSObjectOps *
-(* GetObjectOps)(JSContext *cx, Class *clasp);
typedef JSBool
(* EqualityOp)(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp);
typedef JSBool
(* DefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
PropertyOp getter, PropertyOp setter, uintN attrs);
typedef JSBool
(* PropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp);
typedef JSBool
@@ -800,101 +798,135 @@ static inline JSPropertyOp Jsvalify
static inline ConvertOp Valueify(JSConvertOp f) { return (ConvertOp)f; }
static inline JSConvertOp Jsvalify(ConvertOp f) { return (JSConvertOp)f; }
static inline NewEnumerateOp Valueify(JSNewEnumerateOp f) { return (NewEnumerateOp)f; }
static inline JSNewEnumerateOp Jsvalify(NewEnumerateOp f) { return (JSNewEnumerateOp)f; }
static inline HasInstanceOp Valueify(JSHasInstanceOp f) { return (HasInstanceOp)f; }
static inline JSHasInstanceOp Jsvalify(HasInstanceOp f) { return (JSHasInstanceOp)f; }
static inline CheckAccessOp Valueify(JSCheckAccessOp f) { return (CheckAccessOp)f; }
static inline JSCheckAccessOp Jsvalify(CheckAccessOp f) { return (JSCheckAccessOp)f; }
-static inline GetObjectOps Valueify(JSGetObjectOps f) { return (GetObjectOps)f; }
-static inline JSGetObjectOps Jsvalify(GetObjectOps f) { return (JSGetObjectOps)f; }
static inline EqualityOp Valueify(JSEqualityOp f); /* Same type as JSHasInstanceOp */
static inline JSEqualityOp Jsvalify(EqualityOp f); /* Same type as HasInstanceOp */
static inline DefinePropOp Valueify(JSDefinePropOp f) { return (DefinePropOp)f; }
static inline JSDefinePropOp Jsvalify(DefinePropOp f) { return (JSDefinePropOp)f; }
static inline PropertyIdOp Valueify(JSPropertyIdOp f); /* Same type as JSPropertyOp */
static inline JSPropertyIdOp Jsvalify(PropertyIdOp f); /* Same type as PropertyOp */
static inline CallOp Valueify(JSCallOp f); /* Same type as JSFastNative */
static inline JSCallOp Jsvalify(CallOp f); /* Same type as FastNative */
static const PropertyOp PropertyStub = (PropertyOp)JS_PropertyStub;
static const JSEnumerateOp EnumerateStub = JS_EnumerateStub;
static const JSResolveOp ResolveStub = JS_ResolveStub;
static const ConvertOp ConvertStub = (ConvertOp)JS_ConvertStub;
static const JSFinalizeOp FinalizeStub = JS_FinalizeStub;
-struct Class {
- const char *name;
- uint32 flags;
+#define JS_CLASS_MEMBERS \
+ const char *name; \
+ uint32 flags; \
+ \
+ /* Mandatory non-null function pointer members. */ \
+ PropertyOp addProperty; \
+ PropertyOp delProperty; \
+ PropertyOp getProperty; \
+ PropertyOp setProperty; \
+ JSEnumerateOp enumerate; \
+ JSResolveOp resolve; \
+ ConvertOp convert; \
+ JSFinalizeOp finalize; \
+ \
+ /* Optionally non-null members start here. */ \
+ JSClassInternal reserved0; \
+ CheckAccessOp checkAccess; \
+ Native call; \
+ Native construct; \
+ JSXDRObjectOp xdrObject; \
+ HasInstanceOp hasInstance; \
+ JSMarkOp mark
+
+
+/*
+ * The helper struct to measure the size of JS_CLASS_MEMBERS to know how much
+ * we have to padd js::Class to match the size of JSClass;
+ */
+struct ClassSizeMeasurement {
+ JS_CLASS_MEMBERS;
+};
+
+struct ClassExtension {
+ EqualityOp equality;
+ JSObjectOp outerObject;
+ JSObjectOp innerObject;
+ JSIteratorOp iteratorObject;
+ JSObjectOp wrappedObject; /* NB: infallible, null returns are
+ treated as the original object */
+};
+
+#define JS_NULL_CLASS_EXT {NULL,NULL,NULL,NULL,NULL}
- /* Mandatory non-null function pointer members. */
- PropertyOp addProperty;
- PropertyOp delProperty;
- PropertyOp getProperty;
- PropertyOp setProperty;
- JSEnumerateOp enumerate;
- JSResolveOp resolve;
- ConvertOp convert;
- JSFinalizeOp finalize;
+struct ObjectOps {
+ JSLookupPropOp lookupProperty;
+ js::DefinePropOp defineProperty;
+ js::PropertyIdOp getProperty;
+ js::PropertyIdOp setProperty;
+ JSAttributesOp getAttributes;
+ JSAttributesOp setAttributes;
+ js::PropertyIdOp deleteProperty;
+ js::NewEnumerateOp enumerate;
+ JSTypeOfOp typeOf;
+ JSTraceOp trace;
+ JSObjectOp thisObject;
+ JSFinalizeOp clear;
+};
+
+#define JS_NULL_OBJECT_OPS {NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL}
- /* Optionally non-null members start here. */
- GetObjectOps getObjectOps;
- CheckAccessOp checkAccess;
- Native call;
- Native construct;
- JSXDRObjectOp xdrObject;
- HasInstanceOp hasInstance;
- JSMarkOp mark;
- void (*reserved0)(void);
+struct Class {
+ JS_CLASS_MEMBERS;
+ ClassExtension ext;
+ ObjectOps ops;
+ uint8 pad[sizeof(JSClass) - sizeof(ClassSizeMeasurement) -
+ sizeof(ClassExtension) - sizeof(ObjectOps)];
+
+ /* Flag indicating that Class::call is a fast native. */
+ static const uint32 CALL_IS_FAST = JSCLASS_INTERNAL_FLAG1;
+
+ /* Class is not native and its map is not a scope. */
+ static const uint32 NON_NATIVE = JSCLASS_INTERNAL_FLAG2;
+
+ bool isNative() const {
+ return !(flags & NON_NATIVE);
+ }
};
+
+/* Helper to initialize Class::call when Class::CALL_IS_FAST. */
+inline Native
+CastCallOpAsNative(CallOp op)
+{
+ return reinterpret_cast<Native>(op);
+}
+
JS_STATIC_ASSERT(offsetof(JSClass, name) == offsetof(Class, name));
JS_STATIC_ASSERT(offsetof(JSClass, flags) == offsetof(Class, flags));
JS_STATIC_ASSERT(offsetof(JSClass, addProperty) == offsetof(Class, addProperty));
JS_STATIC_ASSERT(offsetof(JSClass, delProperty) == offsetof(Class, delProperty));
JS_STATIC_ASSERT(offsetof(JSClass, getProperty) == offsetof(Class, getProperty));
JS_STATIC_ASSERT(offsetof(JSClass, setProperty) == offsetof(Class, setProperty));
JS_STATIC_ASSERT(offsetof(JSClass, enumerate) == offsetof(Class, enumerate));
JS_STATIC_ASSERT(offsetof(JSClass, resolve) == offsetof(Class, resolve));
JS_STATIC_ASSERT(offsetof(JSClass, convert) == offsetof(Class, convert));
JS_STATIC_ASSERT(offsetof(JSClass, finalize) == offsetof(Class, finalize));
-JS_STATIC_ASSERT(offsetof(JSClass, getObjectOps) == offsetof(Class, getObjectOps));
+JS_STATIC_ASSERT(offsetof(JSClass, reserved0) == offsetof(Class, reserved0));
JS_STATIC_ASSERT(offsetof(JSClass, checkAccess) == offsetof(Class, checkAccess));
JS_STATIC_ASSERT(offsetof(JSClass, call) == offsetof(Class, call));
JS_STATIC_ASSERT(offsetof(JSClass, construct) == offsetof(Class, construct));
JS_STATIC_ASSERT(offsetof(JSClass, xdrObject) == offsetof(Class, xdrObject));
JS_STATIC_ASSERT(offsetof(JSClass, hasInstance) == offsetof(Class, hasInstance));
JS_STATIC_ASSERT(offsetof(JSClass, mark) == offsetof(Class, mark));
-JS_STATIC_ASSERT(offsetof(JSClass, reserved0) == offsetof(Class, reserved0));
JS_STATIC_ASSERT(sizeof(JSClass) == sizeof(Class));
-struct ExtendedClass {
- Class base;
- EqualityOp equality;
- JSObjectOp outerObject;
- JSObjectOp innerObject;
- JSIteratorOp iteratorObject;
- JSObjectOp wrappedObject; /* NB: infallible, null
- returns are treated as
- the original object */
- void (*reserved0)(void);
- void (*reserved1)(void);
- void (*reserved2)(void);
-};
-JS_STATIC_ASSERT(offsetof(JSExtendedClass, base) == offsetof(ExtendedClass, base));
-JS_STATIC_ASSERT(offsetof(JSExtendedClass, equality) == offsetof(ExtendedClass, equality));
-JS_STATIC_ASSERT(offsetof(JSExtendedClass, outerObject) == offsetof(ExtendedClass, outerObject));
-JS_STATIC_ASSERT(offsetof(JSExtendedClass, innerObject) == offsetof(ExtendedClass, innerObject));
-JS_STATIC_ASSERT(offsetof(JSExtendedClass, iteratorObject) == offsetof(ExtendedClass, iteratorObject));
-JS_STATIC_ASSERT(offsetof(JSExtendedClass, wrappedObject) == offsetof(ExtendedClass, wrappedObject));
-JS_STATIC_ASSERT(offsetof(JSExtendedClass, reserved0) == offsetof(ExtendedClass, reserved0));
-JS_STATIC_ASSERT(offsetof(JSExtendedClass, reserved1) == offsetof(ExtendedClass, reserved1));
-JS_STATIC_ASSERT(offsetof(JSExtendedClass, reserved2) == offsetof(ExtendedClass, reserved2));
-JS_STATIC_ASSERT(sizeof(JSExtendedClass) == sizeof(ExtendedClass));
-
struct PropertyDescriptor {
JSObject *obj;
uintN attrs;
PropertyOp getter;
PropertyOp setter;
Value value;
uintN shortid;
};
@@ -903,18 +935,16 @@ JS_STATIC_ASSERT(offsetof(JSPropertyDesc
JS_STATIC_ASSERT(offsetof(JSPropertyDescriptor, getter) == offsetof(PropertyDescriptor, getter));
JS_STATIC_ASSERT(offsetof(JSPropertyDescriptor, setter) == offsetof(PropertyDescriptor, setter));
JS_STATIC_ASSERT(offsetof(JSPropertyDescriptor, value) == offsetof(PropertyDescriptor, value));
JS_STATIC_ASSERT(offsetof(JSPropertyDescriptor, shortid) == offsetof(PropertyDescriptor, shortid));
JS_STATIC_ASSERT(sizeof(JSPropertyDescriptor) == sizeof(PropertyDescriptor));
static JS_ALWAYS_INLINE JSClass * Jsvalify(Class *c) { return (JSClass *)c; }
static JS_ALWAYS_INLINE Class * Valueify(JSClass *c) { return (Class *)c; }
-static JS_ALWAYS_INLINE JSExtendedClass * Jsvalify(ExtendedClass *c) { return (JSExtendedClass *)c; }
-static JS_ALWAYS_INLINE ExtendedClass * Valueify(JSExtendedClass *c) { return (ExtendedClass *)c; }
static JS_ALWAYS_INLINE JSPropertyDescriptor * Jsvalify(PropertyDescriptor *p) { return (JSPropertyDescriptor *) p; }
static JS_ALWAYS_INLINE PropertyDescriptor * Valueify(JSPropertyDescriptor *p) { return (PropertyDescriptor *) p; }
/******************************************************************************/
/*
* In some cases (quickstubs) we want to take a value in whatever manner is
* appropriate for the architecture and normalize to a const js::Value &. On
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -679,17 +679,17 @@ JSCrossCompartmentWrapper::enumerateOwn(
* We can reify non-escaping iterator objects instead of having to wrap them. This
* allows fast iteration over objects across a compartment boundary.
*/
static bool
CanReify(Value *vp)
{
JSObject *obj;
return vp->isObject() &&
- (obj = &vp->toObject())->getClass() == &js_IteratorClass.base &&
+ (obj = &vp->toObject())->getClass() == &js_IteratorClass &&
(obj->getNativeIterator()->flags & JSITER_ENUMERATE);
}
static bool
Reify(JSContext *cx, JSCompartment *origin, Value *vp)
{
JSObject *iterObj = &vp->toObject();
NativeIterator *ni = iterObj->getNativeIterator();
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -185,17 +185,17 @@ GetLocalName(const JSObject *obj)
return JSVAL_TO_STRING(v);
}
static JSBool
IsDeclared(const JSObject *obj)
{
jsval v;
- JS_ASSERT(obj->getClass() == &js_NamespaceClass.base);
+ JS_ASSERT(obj->getClass() == &js_NamespaceClass);
v = obj->getNamespaceDeclared();
JS_ASSERT(JSVAL_IS_VOID(v) || v == JSVAL_TRUE);
return v == JSVAL_TRUE;
}
static JSBool
xml_isXMLName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
@@ -219,51 +219,67 @@ AppendString(JSCharBuffer &cb, JSString
code; \
return true; \
}
/*
* Namespace class and library functions.
*/
DEFINE_GETTER(NamePrefix_getter,
- if (obj->getClass() == &js_NamespaceClass.base) *vp = obj->getNamePrefix())
+ if (obj->getClass() == &js_NamespaceClass) *vp = obj->getNamePrefix())
DEFINE_GETTER(NameURI_getter,
- if (obj->getClass() == &js_NamespaceClass.base) *vp = obj->getNameURI())
+ if (obj->getClass() == &js_NamespaceClass) *vp = obj->getNameURI())
static void
namespace_finalize(JSContext *cx, JSObject *obj)
{
if (cx->runtime->functionNamespaceObject == obj)
cx->runtime->functionNamespaceObject = NULL;
}
static JSBool
namespace_equality(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
{
JSObject *obj2;
JS_ASSERT(v->isObjectOrNull());
obj2 = v->toObjectOrNull();
- *bp = (!obj2 || obj2->getClass() != &js_NamespaceClass.base)
+ *bp = (!obj2 || obj2->getClass() != &js_NamespaceClass)
? JS_FALSE
: js_EqualStrings(GetURI(obj), GetURI(obj2));
return JS_TRUE;
}
-JS_FRIEND_DATA(ExtendedClass) js_NamespaceClass = {
- { "Namespace",
- JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED |
+JS_FRIEND_DATA(Class) js_NamespaceClass = {
+ "Namespace",
+ JSCLASS_CONSTRUCT_PROTOTYPE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::NAMESPACE_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, namespace_finalize,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL },
- namespace_equality,NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ namespace_finalize,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ NULL, /* mark */
+ {
+ namespace_equality,
+ NULL, /* outerObject */
+ NULL, /* innerObject */
+ NULL, /* iteratorObject */
+ NULL, /* wrappedObject */
+ }
};
#define NAMESPACE_ATTRS \
(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
static JSPropertySpec namespace_props[] = {
{js_prefix_str, 0, NAMESPACE_ATTRS, NamePrefix_getter, 0},
{js_uri_str, 0, NAMESPACE_ATTRS, NameURI_getter, 0},
@@ -271,33 +287,33 @@ static JSPropertySpec namespace_props[]
};
static JSBool
namespace_toString(JSContext *cx, uintN argc, jsval *vp)
{
JSObject *obj;
obj = JS_THIS_OBJECT(cx, vp);
- if (!JS_InstanceOf(cx, obj, Jsvalify(&js_NamespaceClass.base), vp + 2))
+ if (!JS_InstanceOf(cx, obj, Jsvalify(&js_NamespaceClass), vp + 2))
return JS_FALSE;
*vp = obj->getNameURI();
return JS_TRUE;
}
static JSFunctionSpec namespace_methods[] = {
JS_FN(js_toString_str, namespace_toString, 0,0),
JS_FS_END
};
static JSObject *
NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, JSBool declared)
{
JSObject *obj;
- obj = NewBuiltinClassInstance(cx, &js_NamespaceClass.base);
+ obj = NewBuiltinClassInstance(cx, &js_NamespaceClass);
if (!obj)
return JS_FALSE;
JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefix()));
JS_ASSERT(JSVAL_IS_VOID(obj->getNameURI()));
JS_ASSERT(JSVAL_IS_VOID(obj->getNamespaceDeclared()));
if (prefix)
obj->setNamePrefix(STRING_TO_JSVAL(prefix));
if (uri)
@@ -307,20 +323,20 @@ NewXMLNamespace(JSContext *cx, JSString
METER(xml_stats.xmlnamespace);
return obj;
}
/*
* QName class and library functions.
*/
DEFINE_GETTER(QNameNameURI_getter,
- if (obj->getClass() == &js_QNameClass.base)
+ if (obj->getClass() == &js_QNameClass)
*vp = JSVAL_IS_VOID(obj->getNameURI()) ? JSVAL_NULL : obj->getNameURI())
DEFINE_GETTER(QNameLocalName_getter,
- if (obj->getClass() == &js_QNameClass.base)
+ if (obj->getClass() == &js_QNameClass)
*vp = obj->getQNameLocalName())
static void
anyname_finalize(JSContext* cx, JSObject* obj)
{
/* Make sure the next call to js_GetAnyName doesn't try to use obj. */
if (cx->runtime->anynameObject == obj)
cx->runtime->anynameObject = NULL;
@@ -340,65 +356,87 @@ qname_identity(JSObject *qna, JSObject *
}
static JSBool
qname_equality(JSContext *cx, JSObject *qn, const Value *v, JSBool *bp)
{
JSObject *obj2;
obj2 = v->toObjectOrNull();
- *bp = (!obj2 || obj2->getClass() != &js_QNameClass.base)
+ *bp = (!obj2 || obj2->getClass() != &js_QNameClass)
? JS_FALSE
: qname_identity(qn, obj2);
return JS_TRUE;
}
-JS_FRIEND_DATA(ExtendedClass) js_QNameClass = {
- { "QName",
- JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED |
+JS_FRIEND_DATA(Class) js_QNameClass = {
+ "QName",
+ JSCLASS_CONSTRUCT_PROTOTYPE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_QName),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL },
- qname_equality, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ FinalizeStub,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ NULL, /* mark */
+ {
+ qname_equality,
+ NULL, /* outerObject */
+ NULL, /* innerObject */
+ NULL, /* iteratorObject */
+ NULL, /* wrappedObject */
+ }
};
/*
* Classes for the ECMA-357-internal types AttributeName and AnyName, which
* are like QName, except that they have no property getters. They share the
* qname_toString method, and therefore are exposed as constructable objects
* in this implementation.
*/
JS_FRIEND_DATA(Class) js_AttributeNameClass = {
js_AttributeName_str,
JSCLASS_CONSTRUCT_PROTOTYPE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_AttributeName),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub
};
JS_FRIEND_DATA(Class) js_AnyNameClass = {
js_AnyName_str,
JSCLASS_CONSTRUCT_PROTOTYPE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_AnyName),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, anyname_finalize,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ anyname_finalize
};
-#define QNAME_ATTRS \
- (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
+#define QNAME_ATTRS (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
static JSPropertySpec qname_props[] = {
{js_uri_str, 0, QNAME_ATTRS, QNameNameURI_getter, 0},
{js_localName_str, 0, QNAME_ATTRS, QNameLocalName_getter, 0},
{0,0,0,0,0}
};
static JSBool
@@ -411,17 +449,17 @@ qname_toString(JSContext *cx, uintN argc
jschar *chars;
obj = JS_THIS_OBJECT(cx, vp);
if (!obj)
return JS_FALSE;
clasp = obj->getClass();
if (clasp != &js_AttributeNameClass &&
clasp != &js_AnyNameClass &&
- !JS_InstanceOf(cx, obj, Jsvalify(&js_QNameClass.base), vp + 2)) {
+ !JS_InstanceOf(cx, obj, Jsvalify(&js_QNameClass), vp + 2)) {
return JS_FALSE;
}
uri = GetURI(obj);
if (!uri) {
/* No uri means wildcard qualifier. */
str = ATOM_TO_STRING(cx->runtime->atomState.starQualifierAtom);
} else if (uri->empty()) {
@@ -474,17 +512,17 @@ InitXMLQName(JSObject *obj, JSString *ur
if (prefix)
obj->setNamePrefix(STRING_TO_JSVAL(prefix));
if (localName)
obj->setQNameLocalName(STRING_TO_JSVAL(localName));
}
static JSObject *
NewXMLQName(JSContext *cx, JSString *uri, JSString *prefix, JSString *localName,
- Class *clasp = &js_QNameClass.base)
+ Class *clasp = &js_QNameClass)
{
JSObject *obj = NewBuiltinClassInstance(cx, clasp);
if (!obj)
return NULL;
JS_ASSERT(obj->isQName());
InitXMLQName(obj, uri, prefix, localName);
METER(xml_stats.qname);
return obj;
@@ -502,17 +540,17 @@ js_ConstructXMLQNameObject(JSContext *cx
*/
if (nsval.isObject() &&
nsval.toObject().getClass() == &js_AnyNameClass) {
argv[0].setNull();
} else {
argv[0] = nsval;
}
argv[1] = lnval;
- return js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 2, argv);
+ return js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 2, argv);
}
static JSBool
IsXMLName(const jschar *cp, size_t n)
{
JSBool rv;
jschar c;
@@ -576,30 +614,30 @@ NamespaceHelper(JSContext *cx, JSObject
#endif
if (argc <= 0) {
urival = JSVAL_VOID;
} else {
urival = argv[argc > 1];
if (!JSVAL_IS_PRIMITIVE(urival)) {
uriobj = JSVAL_TO_OBJECT(urival);
clasp = uriobj->getClass();
- isNamespace = (clasp == &js_NamespaceClass.base);
- isQName = (clasp == &js_QNameClass.base);
+ isNamespace = (clasp == &js_NamespaceClass);
+ isQName = (clasp == &js_QNameClass);
}
}
if (!obj) {
/* Namespace called as function. */
if (argc == 1 && isNamespace) {
/* Namespace called with one Namespace argument is identity. */
*rval = urival;
return JS_TRUE;
}
- obj = NewBuiltinClassInstance(cx, &js_NamespaceClass.base);
+ obj = NewBuiltinClassInstance(cx, &js_NamespaceClass);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
}
METER(xml_stats.xmlnamespace);
empty = cx->runtime->emptyString;
obj->setNamePrefix(STRING_TO_JSVAL(empty));
@@ -672,26 +710,26 @@ QNameHelper(JSContext *cx, JSObject *obj
jsval *argv, jsval *rval)
{
jsval nameval, nsval;
JSBool isQName, isNamespace;
JSObject *qn;
JSString *uri, *prefix, *name;
JSObject *obj2;
- JS_ASSERT(clasp == &js_QNameClass.base ||
+ JS_ASSERT(clasp == &js_QNameClass ||
clasp == &js_AttributeNameClass);
if (argc <= 0) {
nameval = JSVAL_VOID;
isQName = JS_FALSE;
} else {
nameval = argv[argc > 1];
isQName =
!JSVAL_IS_PRIMITIVE(nameval) &&
- JSVAL_TO_OBJECT(nameval)->getClass() == &js_QNameClass.base;
+ JSVAL_TO_OBJECT(nameval)->getClass() == &js_QNameClass;
}
if (!obj) {
/* QName called as function. */
if (argc == 1 && isQName) {
/* QName called with one QName argument is identity. */
*rval = nameval;
return JS_TRUE;
@@ -737,17 +775,17 @@ QNameHelper(JSContext *cx, JSObject *obj
nsval = argv[0];
} else if (IS_STAR(name)) {
nsval = JSVAL_NULL;
} else {
if (!js_GetDefaultXMLNamespace(cx, &nsval))
return JS_FALSE;
JS_ASSERT(!JSVAL_IS_PRIMITIVE(nsval));
JS_ASSERT(JSVAL_TO_OBJECT(nsval)->getClass() ==
- &js_NamespaceClass.base);
+ &js_NamespaceClass);
}
if (JSVAL_IS_NULL(nsval)) {
/* NULL prefix represents *undefined* in ECMA-357 13.3.2 5(a). */
uri = prefix = NULL;
} else {
/*
* Inline specialization of the Namespace constructor called with
@@ -755,18 +793,18 @@ QNameHelper(JSContext *cx, JSObject *obj
* for the constructed namespace, without actually allocating the
* object or computing other members. See ECMA-357 13.3.2 6(a) and
* 13.2.2.
*/
isNamespace = isQName = JS_FALSE;
if (!JSVAL_IS_PRIMITIVE(nsval)) {
obj2 = JSVAL_TO_OBJECT(nsval);
clasp = obj2->getClass();
- isNamespace = (clasp == &js_NamespaceClass.base);
- isQName = (clasp == &js_QNameClass.base);
+ isNamespace = (clasp == &js_NamespaceClass);
+ isQName = (clasp == &js_QNameClass);
}
#ifdef __GNUC__ /* suppress bogus gcc warnings */
else obj2 = NULL;
#endif
if (isNamespace) {
uri = GetURI(obj2);
prefix = GetPrefix(obj2);
@@ -789,17 +827,17 @@ out:
InitXMLQName(obj, uri, prefix, name);
return JS_TRUE;
}
static JSBool
QName(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
{
return QNameHelper(cx, cx->isConstructing() ? obj : NULL,
- &js_QNameClass.base, argc, Jsvalify(argv), Jsvalify(rval));
+ &js_QNameClass, argc, Jsvalify(argv), Jsvalify(rval));
}
static JSBool
AttributeName(JSContext *cx, JSObject *obj, uintN argc, Value *argv,
Value *rval)
{
return QNameHelper(cx, cx->isConstructing() ? obj : NULL,
&js_AttributeNameClass, argc, Jsvalify(argv), Jsvalify(rval));
@@ -2154,17 +2192,17 @@ GetNamespace(JSContext *cx, JSObject *qn
}
}
}
/* If we didn't match, make a new namespace from qn. */
if (!match) {
argv[0] = prefix ? STRING_TO_JSVAL(prefix) : JSVAL_VOID;
argv[1] = STRING_TO_JSVAL(uri);
- ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, NULL,
+ ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, NULL,
2, Valueify(argv));
if (!ns)
return NULL;
match = ns;
}
return match;
}
@@ -2709,17 +2747,17 @@ ToAttributeName(JSContext *cx, jsval v)
return NULL;
}
obj = JSVAL_TO_OBJECT(v);
clasp = obj->getClass();
if (clasp == &js_AttributeNameClass)
return obj;
- if (clasp == &js_QNameClass.base) {
+ if (clasp == &js_QNameClass) {
qn = obj;
uri = GetURI(qn);
prefix = GetPrefix(qn);
name = GetLocalName(qn);
} else {
if (clasp == &js_AnyNameClass) {
name = ATOM_TO_STRING(cx->runtime->atomState.starAtom);
} else {
@@ -2758,17 +2796,17 @@ IsFunctionQName(JSContext *cx, JSObject
}
*funidp = JSID_VOID;
return JS_TRUE;
}
JSBool
js_IsFunctionQName(JSContext *cx, JSObject *obj, jsid *funidp)
{
- if (obj->getClass() == &js_QNameClass.base)
+ if (obj->getClass() == &js_QNameClass)
return IsFunctionQName(cx, obj, funidp);
*funidp = JSID_VOID;
return JS_TRUE;
}
static JSObject *
ToXMLName(JSContext *cx, jsval v, jsid *funidp)
{
@@ -2783,17 +2821,17 @@ ToXMLName(JSContext *cx, jsval v, jsid *
} else {
if (JSVAL_IS_PRIMITIVE(v)) {
ReportBadXMLName(cx, Valueify(v));
return NULL;
}
obj = JSVAL_TO_OBJECT(v);
clasp = obj->getClass();
- if (clasp == &js_AttributeNameClass || clasp == &js_QNameClass.base)
+ if (clasp == &js_AttributeNameClass || clasp == &js_QNameClass)
goto out;
if (clasp == &js_AnyNameClass) {
name = ATOM_TO_STRING(cx->runtime->atomState.starAtom);
goto construct;
}
name = js_ValueToString(cx, Valueify(v));
if (!name)
return NULL;
@@ -2824,17 +2862,17 @@ ToXMLName(JSContext *cx, jsval v, jsid *
if (!name)
return NULL;
*funidp = JSID_VOID;
return ToAttributeName(cx, STRING_TO_JSVAL(name));
}
construct:
v = STRING_TO_JSVAL(name);
- obj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, Valueify(&v));
+ obj = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 1, Valueify(&v));
if (!obj)
return NULL;
out:
if (!IsFunctionQName(cx, obj, funidp))
return NULL;
return obj;
@@ -4596,23 +4634,23 @@ xml_trace_vector(JSTracer *trc, JSXML **
if (xml) {
JS_SET_TRACING_INDEX(trc, "xml_vector", i);
Mark(trc, xml, JSTRACE_XML);
}
}
}
/*
- * js_XMLObjectOps.newObjectMap is null, so XML objects appear to be native.
- * Thus xml_lookupProperty must return a valid JSScopeProperty pointer
- * parameter via *propp to signify "property found". Since the only call to
- * xml_lookupProperty is via JSObject::lookupProperty, and then only from
- * js_FindProperty (in jsobj.c, called from jsinterp.c) or from JSOP_IN case
- * in the interpreter, the only time we add a JSScopeProperty here is when an
- * unqualified name is being accessed or when "name in xml" is called.
+ * XML objects are native. Thus xml_lookupProperty must return a valid
+ * JSScopeProperty pointer parameter via *propp to signify "property found".
+ * Since the only call to xml_lookupProperty is via JSObject::lookupProperty,
+ * and then only from js_FindProperty (in jsobj.c, called from jsinterp.c) or
+ * from JSOP_IN case in the interpreter, the only time we add a
+ * JSScopeProperty here is when an unqualified name is being accessed or when
+ * "name in xml" is called.
*
* This scope property keeps the JSOP_NAME code in js_Interpret happy by
* giving it an sprop with (getter, setter) == (GetProperty, PutProperty).
*
* NB: xml_deleteProperty must take care to remove any property added here.
*
* FIXME This clashes with the function namespace implementation which also
* uses native properties. Effectively after xml_lookupProperty any property
@@ -5025,47 +5063,49 @@ js_ConcatenateXML(JSContext *cx, JSObjec
goto out;
vp->setObject(*listobj);
out:
js_LeaveLocalRootScopeWithResult(cx, *vp);
return ok;
}
-/* Use NULL for objectMap so XML objects satisfy obj->isNative() tests. */
-JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps = {
- NULL,
- xml_lookupProperty,
- xml_defineProperty,
- xml_getProperty,
- xml_setProperty,
- xml_getAttributes,
- xml_setAttributes,
- xml_deleteProperty,
- xml_enumerate,
- xml_typeOf,
- js_TraceObject,
- NULL, /* thisObject */
- xml_clear
-};
-
-static JSObjectOps *
-xml_getObjectOps(JSContext *cx, Class *clasp)
-{
- return &js_XMLObjectOps;
-}
-
JS_FRIEND_DATA(Class) js_XMLClass = {
js_XML_str,
- JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE |
- JSCLASS_HAS_CACHED_PROTO(JSProto_XML),
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, xml_convert, xml_finalize,
- xml_getObjectOps, NULL, NULL, NULL,
- NULL, xml_hasInstance, JS_CLASS_TRACE(xml_trace), NULL
+ JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_XML),
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ xml_convert,
+ xml_finalize,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ xml_hasInstance,
+ JS_CLASS_TRACE(xml_trace),
+ JS_NULL_CLASS_EXT,
+ {
+ xml_lookupProperty,
+ xml_defineProperty,
+ xml_getProperty,
+ xml_setProperty,
+ xml_getAttributes,
+ xml_setAttributes,
+ xml_deleteProperty,
+ xml_enumerate,
+ xml_typeOf,
+ NULL, /* trace */
+ NULL, /* thisObject */
+ xml_clear
+ }
};
static JSXML *
StartNonListXMLMethod(JSContext *cx, jsval *vp, JSObject **objp)
{
JSXML *xml;
JSFunction *fun;
char numBuf[12];
@@ -6249,17 +6289,17 @@ xml_replace(JSContext *cx, uintN argc, j
if (!xml)
return JS_FALSE;
if (argc == 0 || !js_IdValIsIndex(vp[2], &index)) {
/*
* Call function QName per spec, not ToXMLName, to avoid attribute
* names.
*/
- if (!QNameHelper(cx, NULL, &js_QNameClass.base, argc == 0 ? -1 : 1,
+ if (!QNameHelper(cx, NULL, &js_QNameClass, argc == 0 ? -1 : 1,
vp + 2, vp)) {
return JS_FALSE;
}
JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
nameqn = JSVAL_TO_OBJECT(*vp);
i = xml->xml_kids.length;
index = XML_NOT_FOUND;
@@ -6312,17 +6352,17 @@ xml_setLocalName(JSContext *cx, uintN ar
if (!JSXML_HAS_NAME(xml))
return JS_TRUE;
if (argc == 0) {
namestr = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
} else {
name = vp[2];
if (!JSVAL_IS_PRIMITIVE(name) &&
- JSVAL_TO_OBJECT(name)->getClass() == &js_QNameClass.base) {
+ JSVAL_TO_OBJECT(name)->getClass() == &js_QNameClass) {
nameqn = JSVAL_TO_OBJECT(name);
namestr = GetLocalName(nameqn);
} else {
if (!JS_ConvertValue(cx, name, JSTYPE_STRING, &vp[2]))
return JS_FALSE;
name = vp[2];
namestr = JSVAL_TO_STRING(name);
}
@@ -6349,23 +6389,23 @@ xml_setName(JSContext *cx, uintN argc, j
if (!JSXML_HAS_NAME(xml))
return JS_TRUE;
if (argc == 0) {
name = ATOM_TO_JSVAL(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
} else {
name = vp[2];
if (!JSVAL_IS_PRIMITIVE(name) &&
- JSVAL_TO_OBJECT(name)->getClass() == &js_QNameClass.base &&
+ JSVAL_TO_OBJECT(name)->getClass() == &js_QNameClass &&
!GetURI(nameqn = JSVAL_TO_OBJECT(name))) {
name = vp[2] = nameqn->getQNameLocalName();
}
}
- nameqn = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, Valueify(&name));
+ nameqn = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 1, Valueify(&name));
if (!nameqn)
return JS_FALSE;
/* ECMA-357 13.4.4.35 Step 4. */
if (xml->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION)
nameqn->setNameURI(STRING_TO_JSVAL(cx->runtime->emptyString));
xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
@@ -6454,26 +6494,26 @@ xml_setNamespace(JSContext *cx, uintN ar
NON_LIST_XML_METHOD_PROLOG;
if (!JSXML_HAS_NAME(xml))
return JS_TRUE;
xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
if (!xml)
return JS_FALSE;
- ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, obj,
+ ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, obj,
argc == 0 ? 0 : 1, Valueify(vp + 2));
if (!ns)
return JS_FALSE;
vp[0] = OBJECT_TO_JSVAL(ns);
ns->setNamespaceDeclared(JSVAL_TRUE);
qnargv[0] = vp[2] = OBJECT_TO_JSVAL(ns);
qnargv[1] = OBJECT_TO_JSVAL(xml->name);
- qn = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 2, Valueify(qnargv));
+ qn = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 2, Valueify(qnargv));
if (!qn)
return JS_FALSE;
xml->name = qn;
/*
* Erratum: the spec fails to update the governing in-scope namespaces.
* See the erratum noted in xml_setName, above.
@@ -6990,24 +7030,24 @@ js_GetXMLObject(JSContext *cx, JSXML *xm
return NULL;
xml->object = obj;
return obj;
}
JSObject *
js_InitNamespaceClass(JSContext *cx, JSObject *obj)
{
- return js_InitClass(cx, obj, NULL, &js_NamespaceClass.base, Namespace, 2,
+ return js_InitClass(cx, obj, NULL, &js_NamespaceClass, Namespace, 2,
namespace_props, namespace_methods, NULL, NULL);
}
JSObject *
js_InitQNameClass(JSContext *cx, JSObject *obj)
{
- return js_InitClass(cx, obj, NULL, &js_QNameClass.base, QName, 2,
+ return js_InitClass(cx, obj, NULL, &js_QNameClass, QName, 2,
qname_props, qname_methods, NULL, NULL);
}
JSObject *
js_InitAttributeNameClass(JSContext *cx, JSObject *obj)
{
return js_InitClass(cx, obj, NULL, &js_AttributeNameClass, AttributeName, 2,
qname_props, qname_methods, NULL, NULL);
@@ -7193,17 +7233,17 @@ js_GetDefaultXMLNamespace(JSContext *cx,
return JS_FALSE;
if (!JSVAL_IS_PRIMITIVE(v)) {
*vp = v;
return JS_TRUE;
}
obj = tmp;
}
- ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, obj, 0, NULL);
+ ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, obj, 0, NULL);
if (!ns)
return JS_FALSE;
v = OBJECT_TO_JSVAL(ns);
if (!obj->defineProperty(cx, JS_DEFAULT_XML_NAMESPACE_ID, Valueify(v),
PropertyStub, PropertyStub, JSPROP_PERMANENT)) {
return JS_FALSE;
}
*vp = v;
@@ -7214,17 +7254,17 @@ JSBool
js_SetDefaultXMLNamespace(JSContext *cx, const Value &v)
{
Value argv[2];
JSObject *ns, *varobj;
JSStackFrame *fp;
argv[0].setString(cx->runtime->emptyString);
argv[1] = v;
- ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, NULL, 2, argv);
+ ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, NULL, 2, argv);
if (!ns)
return JS_FALSE;
fp = js_GetTopStackFrame(cx);
varobj = fp->varobj(cx);
if (!varobj->defineProperty(cx, JS_DEFAULT_XML_NAMESPACE_ID, ObjectValue(*ns),
PropertyStub, PropertyStub, JSPROP_PERMANENT)) {
return JS_FALSE;
@@ -7380,23 +7420,23 @@ js_FindXMLProperty(JSContext *cx, const
JSBool found;
JSProperty *prop;
const char *printable;
JS_ASSERT(nameval.isObject());
nameobj = &nameval.toObject();
if (nameobj->getClass() == &js_AnyNameClass) {
v = ATOM_TO_JSVAL(cx->runtime->atomState.starAtom);
- nameobj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1,
+ nameobj = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 1,
Valueify(&v));
if (!nameobj)
return JS_FALSE;
} else {
JS_ASSERT(nameobj->getClass() == &js_AttributeNameClass ||
- nameobj->getClass() == &js_QNameClass.base);
+ nameobj->getClass() == &js_QNameClass);
}
qn = nameobj;
if (!IsFunctionQName(cx, qn, &funid))
return JS_FALSE;
obj = js_GetTopStackFrame(cx)->scopeChain;
do {
@@ -7561,20 +7601,31 @@ xmlfilter_finalize(JSContext *cx, JSObje
return;
cx->destroy(filter);
}
Class js_XMLFilterClass = {
"XMLFilter",
JSCLASS_HAS_PRIVATE | JSCLASS_IS_ANONYMOUS | JSCLASS_MARK_IS_TRACE,
- PropertyStub, PropertyStub, PropertyStub, PropertyStub,
- EnumerateStub, ResolveStub, ConvertStub, xmlfilter_finalize,
- NULL, NULL, NULL, NULL,
- NULL, NULL, JS_CLASS_TRACE(xmlfilter_trace), NULL
+ PropertyStub, /* addProperty */
+ PropertyStub, /* delProperty */
+ PropertyStub, /* getProperty */
+ PropertyStub, /* setProperty */
+ EnumerateStub,
+ ResolveStub,
+ ConvertStub,
+ xmlfilter_finalize,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ JS_CLASS_TRACE(xmlfilter_trace)
};
JSBool
js_StepXMLListFilter(JSContext *cx, JSBool initialized)
{
jsval *sp;
JSObject *obj, *filterobj, *resobj, *kidobj;
JSXML *xml, *list;
--- a/js/src/jsxml.h
+++ b/js/src/jsxml.h
@@ -211,55 +211,54 @@ extern void
js_FinalizeXML(JSContext *cx, JSXML *xml);
extern JSObject *
js_NewXMLObject(JSContext *cx, JSXMLClass xml_class);
extern JSObject *
js_GetXMLObject(JSContext *cx, JSXML *xml);
-extern JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps;
-extern JS_FRIEND_DATA(js::Class) js_XMLClass;
-extern JS_FRIEND_DATA(js::ExtendedClass) js_NamespaceClass;
-extern JS_FRIEND_DATA(js::ExtendedClass) js_QNameClass;
-extern JS_FRIEND_DATA(js::Class) js_AttributeNameClass;
-extern JS_FRIEND_DATA(js::Class) js_AnyNameClass;
-extern js::Class js_XMLFilterClass;
+extern JS_FRIEND_DATA(js::Class) js_XMLClass;
+extern JS_FRIEND_DATA(js::Class) js_NamespaceClass;
+extern JS_FRIEND_DATA(js::Class) js_QNameClass;
+extern JS_FRIEND_DATA(js::Class) js_AttributeNameClass;
+extern JS_FRIEND_DATA(js::Class) js_AnyNameClass;
+extern js::Class js_XMLFilterClass;
/*
* Methods to test whether an object or a value is of type "xml" (per typeof).
*/
inline bool
JSObject::isXML() const
{
- return map->ops == &js_XMLObjectOps;
+ return getClass() == &js_XMLClass;
}
inline bool
JSObject::isXMLId() const
{
js::Class *clasp = getClass();
- return clasp == &js_QNameClass.base ||
+ return clasp == &js_QNameClass ||
clasp == &js_AttributeNameClass ||
clasp == &js_AnyNameClass;
}
#define VALUE_IS_XML(v) (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isXML())
inline bool
JSObject::isNamespace() const
{
- return getClass() == &js_NamespaceClass.base;
+ return getClass() == &js_NamespaceClass;
}
inline bool
JSObject::isQName() const
{
js::Class* clasp = getClass();
- return clasp == &js_QNameClass.base ||
+ return clasp == &js_QNameClass ||
clasp == &js_AttributeNameClass ||
clasp == &js_AnyNameClass;
}
static inline bool
IsXML(const js::Value &v)
{
return v.isObject() && v.toObject().isXML();
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -2483,17 +2483,17 @@ mjit::Compiler::jsop_bindname(uint32 ind
pic.shapeReg = frame.allocReg();
pic.objReg = frame.allocReg();
pic.typeReg = Registers::ReturnReg;
pic.atom = script->getAtom(index);
pic.hasTypeCheck = false;
pic.hotPathBegin = masm.label();
- Address parent(pic.objReg, offsetof(JSObject, fslots) + JSSLOT_PARENT * sizeof(jsval));
+ Address parent(pic.objReg, offsetof(JSObject, parent));
masm.loadPtr(Address(JSFrameReg, offsetof(JSStackFrame, scopeChain)), pic.objReg);
pic.shapeGuard = masm.label();
#if defined JS_NUNBOX32
Jump j = masm.branchPtr(Assembler::NotEqual, masm.payloadOf(parent), ImmPtr(0));
#elif defined JS_PUNBOX64
masm.loadPayload(parent, Registers::ValueReg);
Jump j = masm.branchPtr(Assembler::NotEqual, Registers::ValueReg, ImmPtr(0));
@@ -2795,17 +2795,17 @@ mjit::Compiler::iterNext()
/* Is it worth trying to pin this longer? Prolly not. */
frame.pinReg(reg);
RegisterID T1 = frame.allocReg();
frame.unpinReg(reg);
/* Test clasp */
masm.loadPtr(Address(reg, offsetof(JSObject, clasp)), T1);
- Jump notFast = masm.branchPtr(Assembler::NotEqual, T1, ImmPtr(&js_IteratorClass.base));
+ Jump notFast = masm.branchPtr(Assembler::NotEqual, T1, ImmPtr(&js_IteratorClass));
stubcc.linkExit(notFast, Uses(1));
/* Get private from iter obj. */
masm.loadFunctionPrivate(reg, T1);
RegisterID T3 = frame.allocReg();
RegisterID T4 = frame.allocReg();
@@ -2851,17 +2851,17 @@ mjit::Compiler::iterMore()
RegisterID reg = frame.tempRegForData(fe);
frame.pinReg(reg);
RegisterID T1 = frame.allocReg();
frame.unpinReg(reg);
/* Test clasp */
masm.loadPtr(Address(reg, offsetof(JSObject, clasp)), T1);
- Jump notFast = masm.branchPtr(Assembler::NotEqual, T1, ImmPtr(&js_IteratorClass.base));
+ Jump notFast = masm.branchPtr(Assembler::NotEqual, T1, ImmPtr(&js_IteratorClass));
stubcc.linkExit(notFast, Uses(1));
/* Get private from iter obj. */
masm.loadFunctionPrivate(reg, T1);
/* Get props_cursor, test */
RegisterID T2 = frame.allocReg();
frame.forgetEverything();
@@ -3169,18 +3169,18 @@ mjit::Compiler::jsop_instanceof()
RegisterID temp = frame.allocReg();
MaybeJump isFalse;
if (!lhs->isTypeKnown())
isFalse = frame.testPrimitive(Assembler::Equal, lhs);
/* Quick test to avoid wrapped objects. */
masm.loadPtr(Address(obj, offsetof(JSObject, clasp)), temp);
- masm.load32(Address(temp, offsetof(JSClass, flags)), temp);
- masm.and32(Imm32(JSCLASS_IS_EXTENDED), temp);
+ masm.load32(Address(temp, offsetof(Class, ext)), temp);
+ masm.load32(Address(temp, offsetof(ClassExtension, wrappedObject)), temp);
j = masm.branchTest32(Assembler::NonZero, temp, temp);
stubcc.linkExit(j, Uses(3));
Address protoAddr(obj, offsetof(JSObject, proto));
Label loop = masm.label();
/* Walk prototype chain, break out on NULL or hit. */
masm.loadPayload(protoAddr, obj);
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -1271,17 +1271,17 @@ class ScopeNameCompiler : public PICStub
/* Guard on intervening shapes. */
masm.loadShape(pic.objReg, pic.shapeReg);
Jump j = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(tobj->shape()));
if (!fails.append(j))
return false;
/* Load the next link in the scope chain. */
- Address parent(pic.objReg, offsetof(JSObject, fslots) + JSSLOT_PARENT * sizeof(Value));
+ Address parent(pic.objReg, offsetof(JSObject, parent));
masm.load32(parent, pic.objReg);
tobj = tobj->getParent();
}
found = tobj == holder;
return true;
@@ -1535,17 +1535,17 @@ class BindNameCompiler : public PICStubC
/* Guard on the shape of the scope chain. */
masm.load32(Address(JSFrameReg, offsetof(JSStackFrame, scopeChain)), pic.objReg);
masm.loadShape(pic.objReg, pic.shapeReg);
Jump firstShape = masm.branch32(Assembler::NotEqual, pic.shapeReg,
Imm32(scopeChain->shape()));
/* Walk up the scope chain. */
JSObject *tobj = scopeChain;
- Address parent(pic.objReg, offsetof(JSObject, fslots) + JSSLOT_PARENT * sizeof(Value));
+ Address parent(pic.objReg, offsetof(JSObject, parent));
while (tobj && tobj != obj) {
if (!js_IsCacheableNonGlobalScope(tobj))
return disable("non-cacheable obj in scope chain");
masm.load32(parent, pic.objReg);
Jump nullTest = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg);
if (!fails.append(nullTest))
return false;
masm.loadShape(pic.objReg, pic.shapeReg);
@@ -1864,26 +1864,26 @@ ic::CallProp(VMFrame &f, uint32 index)
*/
jsid id;
id = ATOM_TO_JSID(origAtom);
regs.sp++;
regs.sp[-1].setNull();
if (lval.isObject()) {
if (!js_GetMethod(cx, &objv.toObject(), id,
- JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)
+ JS_LIKELY(!js_GetProperty)
? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
: JSGET_NO_METHOD_BARRIER,
&rval)) {
THROW();
}
regs.sp[-1] = objv;
regs.sp[-2] = rval;
} else {
- JS_ASSERT(objv.toObject().map->ops->getProperty == js_GetProperty);
+ JS_ASSERT(!objv.toObject().getOps()->getProperty);
if (!js_GetPropertyHelper(cx, &objv.toObject(), id,
JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER,
&rval)) {
THROW();
}
regs.sp[-1] = lval;
regs.sp[-2] = rval;
}
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -282,17 +282,17 @@ mjit::stubs::SetName(VMFrame &f, JSAtom
}
if (sprop)
break;
}
if (!atom)
atom = origAtom;
jsid id = ATOM_TO_JSID(atom);
- if (entry && JS_LIKELY(obj->map->ops->setProperty == js_SetProperty)) {
+ if (entry && JS_LIKELY(obj->getOps()->setProperty == js_SetProperty)) {
uintN defineHow;
JSOp op = JSOp(*f.regs.pc);
if (op == JSOP_SETMETHOD)
defineHow = JSDNP_CACHE_RESULT | JSDNP_SET_METHOD;
else if (op == JSOP_SETNAME)
defineHow = JSDNP_CACHE_RESULT | JSDNP_UNQUALIFIED;
else
defineHow = JSDNP_CACHE_RESULT;
@@ -424,17 +424,17 @@ stubs::GetGlobalName(VMFrame &f)
JSObject *globalObj = f.fp->scopeChain->getGlobal();
if (!NameOp(f, globalObj))
THROW();
}
static inline bool
IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
{
- if (iterobj->getClass() == &js_IteratorClass.base) {
+ if (iterobj->getClass() == &js_IteratorClass) {
NativeIterator *ni = (NativeIterator *) iterobj->getPrivate();
JS_ASSERT(ni->props_cursor < ni->props_end);
if (ni->isKeyIter()) {
jsid id = *ni->currentKey();
if (JSID_IS_ATOM(id)) {
rval->setString(JSID_TO_STRING(id));
ni->incKeyCursor();
return true;
@@ -1011,17 +1011,16 @@ stubs::Not(VMFrame &f)
JSBool b = !js_ValueToBoolean(f.regs.sp[-1]);
f.regs.sp[-1].setBoolean(b);
}
template <JSBool EQ, bool IFNAN>
static inline bool
StubEqualityOp(VMFrame &f)
{
- Class *clasp;
JSContext *cx = f.cx;
JSFrameRegs ®s = f.regs;
Value rval = regs.sp[-1];
Value lval = regs.sp[-2];
JSBool cond;
@@ -1043,19 +1042,18 @@ StubEqualityOp(VMFrame &f)
double l = lval.toDouble();
double r = rval.toDouble();
if (EQ)
cond = JSDOUBLE_COMPARE(l, ==, r, IFNAN);
else
cond = JSDOUBLE_COMPARE(l, !=, r, IFNAN);
} else if (lval.isObject()) {
JSObject *l = &lval.toObject(), *r = &rval.toObject();
- if (((clasp = l->getClass())->flags & JSCLASS_IS_EXTENDED) &&
- ((ExtendedClass *)clasp)->equality) {
- if (!((ExtendedClass *)clasp)->equality(cx, l, &rval, &cond))
+ if (EqualityOp eq = l->getClass()->ext.equality) {
+ if (!eq(cx, l, &rval, &cond))
return false;
cond = cond == EQ;
} else {
cond = (l == r) == EQ;
}
} else if (lval.isNullOrUndefined()) {
cond = EQ;
} else {
@@ -1866,17 +1864,17 @@ InlineGetProp(VMFrame &f)
NATIVE_GET(cx, obj, obj2, sprop,
f.fp->imacpc ? JSGET_NO_METHOD_BARRIER : JSGET_METHOD_BARRIER,
&rval, return false);
}
break;
}
jsid id = ATOM_TO_JSID(atom);
- if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)
+ if (JS_LIKELY(!aobj->getOps()->getProperty)
? !js_GetPropertyHelper(cx, obj, id,
f.fp->imacpc
? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
: JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER,
&rval)
: !obj->getProperty(cx, id, &rval)) {
return false;
}
@@ -1956,26 +1954,26 @@ stubs::CallProp(VMFrame &f, JSAtom *orig
*/
jsid id;
id = ATOM_TO_JSID(origAtom);
regs.sp++;
regs.sp[-1].setNull();
if (lval.isObject()) {
if (!js_GetMethod(cx, &objv.toObject(), id,
- JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)
+ JS_LIKELY(!aobj->getOps()->getProperty)
? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
: JSGET_NO_METHOD_BARRIER,
&rval)) {
THROW();
}
regs.sp[-1] = objv;
regs.sp[-2] = rval;
} else {
- JS_ASSERT(objv.toObject().map->ops->getProperty == js_GetProperty);
+ JS_ASSERT(!objv.toObject().getOps()->getProperty);
if (!js_GetPropertyHelper(cx, &objv.toObject(), id,
JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER,
&rval)) {
THROW();
}
regs.sp[-1] = lval;
regs.sp[-2] = rval;
}
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1411,17 +1411,17 @@ ValueToScript(JSContext *cx, jsval v)
JSFunction *fun;
if (!JSVAL_IS_PRIMITIVE(v)) {
JSObject *obj = JSVAL_TO_OBJECT(v);
JSClass *clasp = JS_GET_CLASS(cx, obj);
if (clasp == Jsvalify(&js_ScriptClass)) {
script = (JSScript *) JS_GetPrivate(cx, obj);
- } else if (clasp == Jsvalify(&js_GeneratorClass.base)) {
+ } else if (clasp == Jsvalify(&js_GeneratorClass)) {
JSGenerator *gen = (JSGenerator *) JS_GetPrivate(cx, obj);
fun = gen->getFloatingFrame()->fun;
script = FUN_SCRIPT(fun);
}
}
if (!script) {
fun = JS_ValueToFunction(cx, v);
@@ -2761,28 +2761,16 @@ static JSObject *
split_thisObject(JSContext *cx, JSObject *obj)
{
OBJ_TO_OUTER_OBJECT(cx, obj);
if (!obj)
return NULL;
return obj;
}
-static JSObjectOps split_objectops;
-
-static JSObjectOps *
-split_getObjectOps(JSContext *cx, JSClass *clasp)
-{
- if (!split_objectops.thisObject) {
- memcpy(&split_objectops, &js_ObjectOps, sizeof split_objectops);
- split_objectops.thisObject = split_thisObject;
- }
-
- return &split_objectops;
-}
static JSBool
split_equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
static JSObject *
split_innerObject(JSContext *cx, JSObject *obj)
{
ComplexObject *cpx;
@@ -2790,40 +2778,66 @@ split_innerObject(JSContext *cx, JSObjec
cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
if (cpx->frozen) {
JS_ASSERT(!cpx->isInner);
return obj;
}
return !cpx->isInner ? cpx->inner : obj;
}
-static JSExtendedClass split_global_class = {
- {"split_global",
- JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_HAS_PRIVATE |
- JSCLASS_GLOBAL_FLAGS | JSCLASS_IS_EXTENDED,
- split_addProperty, split_delProperty,
- split_getProperty, split_setProperty,
+static Class split_global_class = {
+ "split_global",
+ JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS,
+ Valueify(split_addProperty),
+ Valueify(split_delProperty),
+ Valueify(split_getProperty),
+ Valueify(split_setProperty),
(JSEnumerateOp)split_enumerate,
(JSResolveOp)split_resolve,
- JS_ConvertStub, split_finalize,
- split_getObjectOps, NULL, NULL, NULL, NULL, NULL,
- split_mark, NULL},
- split_equality, split_outerObject, split_innerObject,
- NULL, NULL, NULL, NULL, NULL
+ ConvertStub,
+ split_finalize,
+ NULL, /* reserved0 */
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* construct */
+ NULL, /* xdrObject */
+ NULL, /* hasInstance */
+ split_mark,
+ {
+ Valueify(split_equality),
+ split_outerObject,
+ split_innerObject,
+ NULL, /* iteratorObject */
+ NULL, /* wrappedObject */
+ },
+ {
+ NULL, /* lookupProperty */
+ NULL, /* defineProperty */
+ NULL, /* getProperty */
+ NULL, /* setProperty */
+ NULL, /* getAttributes */
+ NULL, /* setAttributes */
+ NULL, /* deleteProperty */
+ NULL, /* enumerate */
+ NULL, /* typeOf */
+ NULL, /* trace */
+ split_thisObject,
+ NULL, /* clear */
+ },
};
static JSBool
split_equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp)
{
*bp = JS_FALSE;
if (JSVAL_IS_PRIMITIVE(*v))
return JS_TRUE;
JSObject *obj2 = JSVAL_TO_OBJECT(*v);
- if (JS_GET_CLASS(cx, obj2) != &split_global_class.base)
+ if (obj2->getClass() != &split_global_class)
return JS_TRUE;
ComplexObject *cpx = (ComplexObject *) JS_GetPrivate(cx, obj2);
JS_ASSERT(!cpx->isInner);
ComplexObject *ourCpx = (ComplexObject *) JS_GetPrivate(cx, obj);
JS_ASSERT(!ourCpx->isInner);
@@ -2840,17 +2854,17 @@ split_create_outer(JSContext *cx)
cpx = (ComplexObject *) JS_malloc(cx, sizeof *obj);
if (!cpx)
return NULL;
cpx->isInner = JS_FALSE;
cpx->frozen = JS_TRUE;
cpx->inner = NULL;
cpx->outer = NULL;
- obj = JS_NewGlobalObject(cx, &split_global_class.base);
+ obj = JS_NewGlobalObject(cx, Jsvalify(&split_global_class));
if (!obj || !JS_SetParent(cx, obj, NULL)) {
JS_free(cx, cpx);
return NULL;
}
if (!JS_SetPrivate(cx, obj, cpx)) {
JS_free(cx, cpx);
return NULL;
@@ -2860,44 +2874,44 @@ split_create_outer(JSContext *cx)
}
static JSObject *
split_create_inner(JSContext *cx, JSObject *outer)
{
ComplexObject *cpx, *outercpx;
JSObject *obj;
- JS_ASSERT(JS_GET_CLASS(cx, outer) == &split_global_class.base);
+ JS_ASSERT(outer->getClass() == &split_global_class);
cpx = (ComplexObject *) JS_malloc(cx, sizeof *cpx);
if (!cpx)
return NULL;
cpx->isInner = JS_TRUE;
cpx->frozen = JS_FALSE;
cpx->inner = NULL;
cpx->outer = outer;
- obj = JS_NewGlobalObject(cx, &split_global_class.base);
+ obj = JS_NewGlobalObject(cx, Jsvalify(&split_global_class));
if (!obj || !JS_SetParent(cx, obj, NULL) || !JS_SetPrivate(cx, obj, cpx)) {
JS_free(cx, cpx);
return NULL;
}
outercpx = (ComplexObject *) JS_GetPrivate(cx, outer);
outercpx->inner = obj;
outercpx->frozen = JS_FALSE;
return obj;
}
static ComplexObject *
split_get_private(JSContext *cx, JSObject *obj)
{
do {
- if (JS_GET_CLASS(cx, obj) == &split_global_class.base)
+ if (obj->getClass() == &split_global_class)
return (ComplexObject *) JS_GetPrivate(cx, obj);
obj = JS_GetParent(cx, obj);
} while (obj);
return NULL;
}
static JSBool
@@ -3672,22 +3686,18 @@ Parent(JSContext *cx, uintN argc, jsval
return JS_FALSE;
}
JSObject *parent = JS_GetParent(cx, JSVAL_TO_OBJECT(v));
*vp = OBJECT_TO_JSVAL(parent);
/* Outerize if necessary. Embrace the ugliness! */
if (parent) {
- JSClass *clasp = JS_GET_CLASS(cx, parent);
- if (clasp->flags & JSCLASS_IS_EXTENDED) {
- JSExtendedClass *xclasp = reinterpret_cast<JSExtendedClass *>(clasp);
- if (JSObjectOp outerize = xclasp->outerObject)
- *vp = OBJECT_TO_JSVAL(outerize(cx, parent));
- }
+ if (JSObjectOp op = parent->getClass()->ext.outerObject)
+ *vp = OBJECT_TO_JSVAL(op(cx, parent));
}
return JS_TRUE;
}
#ifdef XP_UNIX
#include <fcntl.h>
--- a/js/src/trace-test/trace-test.py
+++ b/js/src/trace-test/trace-test.py
@@ -281,16 +281,17 @@ if __name__ == '__main__':
help='Enable the |valgrind| flag, if valgrind is in $PATH.')
op.add_option('--valgrind-all', dest='valgrind_all', action='store_true',
help='Run all tests with valgrind, if valgrind is in $PATH.')
(OPTIONS, args) = op.parse_args()
if len(args) < 1:
op.error('missing JS_SHELL argument')
# We need to make sure we are using backslashes on Windows.
JS, test_args = os.path.normpath(args[0]), args[1:]
+ JS = os.path.realpath(JS) # Burst through the symlinks!
if OPTIONS.retest:
OPTIONS.read_tests = OPTIONS.retest
OPTIONS.write_failures = OPTIONS.retest
test_list = []
read_all = True
--- a/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -54,16 +54,17 @@
#include "nsDependentString.h"
#include "nsAutoPtr.h"
#include "nsNetUtil.h"
#include "nsIProtocolHandler.h"
#include "nsIFileURL.h"
#include "jsapi.h"
#include "jsdbgapi.h"
+#include "jsobj.h"
#include "mozilla/FunctionTimer.h"
/* load() error msgs, XXX localize? */
#define LOAD_ERROR_NOSERVICE "Error creating IO Service."
#define LOAD_ERROR_NOURI "Error creating URI (invalid URL scheme?)"
#define LOAD_ERROR_NOSCHEME "Failed to get URI scheme. This is bad."
#define LOAD_ERROR_URI_NOT_LOCAL "Trying to load a non-local URI."
@@ -199,28 +200,23 @@ mozJSSubScriptLoader::LoadSubScript (con
}
#ifdef DEBUG_rginda
fprintf (stderr, "\n");
#endif
}
// Innerize the target_obj so that we compile the loaded script in the
// correct (inner) scope.
- JSClass *target_class = JS_GET_CLASS(cx, target_obj);
- if (target_class->flags & JSCLASS_IS_EXTENDED)
+ if (JSObjectOp op = target_obj->getClass()->ext.innerObject)
{
- JSExtendedClass *extended = (JSExtendedClass*)target_class;
- if (extended->innerObject)
- {
- target_obj = extended->innerObject(cx, target_obj);
- if (!target_obj) return NS_ERROR_FAILURE;
+ target_obj = op(cx, target_obj);
+ if (!target_obj) return NS_ERROR_FAILURE;
#ifdef DEBUG_rginda
- fprintf (stderr, "Final global: %p\n", target_obj);
+ fprintf (stderr, "Final global: %p\n", target_obj);
#endif
- }
}
/* load up the url. From here on, failures are reflected as ``custom''
* js exceptions */
PRInt32 len = -1;
PRUint32 readcount = 0; // Total amount of data read
PRUint32 lastReadCount = 0; // Amount of data read in last Read() call
nsAutoArrayPtr<char> buf;
--- a/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp
+++ b/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp
@@ -246,49 +246,55 @@ XPC_COW_WrappedObject(JSContext *cx, JSO
static JSBool
WrapFunction(JSContext *cx, JSObject *scope, JSObject *funobj, jsval *vp);
using namespace XPCWrapper;
namespace ChromeObjectWrapper {
-JSExtendedClass COWClass = {
- // JSClass (JSExtendedClass.base) initialization
- { "ChromeObjectWrapper",
- JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
+js::Class COWClass = {
+ "ChromeObjectWrapper",
+ JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 1),
- XPC_COW_AddProperty, XPC_COW_DelProperty,
- XPC_COW_GetProperty, XPC_COW_SetProperty,
- XPC_COW_Enumerate, (JSResolveOp)XPC_COW_NewResolve,
- XPC_COW_Convert, JS_FinalizeStub,
- nsnull, XPC_COW_CheckAccess,
- nsnull, nsnull,
- nsnull, nsnull,
- nsnull, nsnull
- },
+ js::Valueify(XPC_COW_AddProperty),
+ js::Valueify(XPC_COW_DelProperty),
+ js::Valueify(XPC_COW_GetProperty),
+ js::Valueify(XPC_COW_SetProperty),
+ XPC_COW_Enumerate,
+ (JSResolveOp)XPC_COW_NewResolve,
+ js::Valueify(XPC_COW_Convert),
+ JS_FinalizeStub,
+ nsnull, // reserved0
+ js::Valueify(XPC_COW_CheckAccess),
+ nsnull, // call
+ nsnull, // construct
+ nsnull, // xdrObject
+ nsnull, // hasInstance
+ nsnull, // mark
- // JSExtendedClass initialization
- XPC_COW_Equality,
- nsnull, // outerObject
- nsnull, // innerObject
- XPC_COW_Iterator,
- XPC_COW_WrappedObject,
- JSCLASS_NO_RESERVED_MEMBERS
+ // ClassExtension
+ {
+ js::Valueify(XPC_COW_Equality),
+ nsnull, // outerObject
+ nsnull, // innerObject
+ XPC_COW_Iterator,
+ XPC_COW_WrappedObject
+ }
};
JSBool
WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp)
{
if (JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(v))) {
return WrapFunction(cx, parent, JSVAL_TO_OBJECT(v), vp);
}
JSObject *wrapperObj =
- JS_NewObjectWithGivenProto(cx, &COWClass.base, NULL, parent);
+ JS_NewObjectWithGivenProto(cx, js::Jsvalify(&COWClass), NULL, parent);
if (!wrapperObj) {
return JS_FALSE;
}
*vp = OBJECT_TO_JSVAL(wrapperObj);
js::AutoValueRooter exposedProps(cx);
@@ -318,41 +324,36 @@ ThrowException(nsresult rv, JSContext *c
}
// Like GetWrappedObject, but works on other types of wrappers, too.
// See also JSObject::wrappedObject in jsobj.cpp.
// TODO Move to XPCWrapper?
static inline JSObject *
GetWrappedJSObject(JSContext *cx, JSObject *obj)
{
- JSClass *clasp = obj->getJSClass();
- if (!(clasp->flags & JSCLASS_IS_EXTENDED)) {
- return obj;
- }
-
- JSExtendedClass *xclasp = (JSExtendedClass *)clasp;
- if (!xclasp->wrappedObject) {
+ JSObjectOp op = obj->getClass()->ext.wrappedObject;
+ if (!op) {
if (XPCNativeWrapper::IsNativeWrapper(obj)) {
XPCWrappedNative *wn = XPCNativeWrapper::SafeGetWrappedNative(obj);
return wn ? wn->GetFlatJSObject() : nsnull;
}
return obj;
}
- return xclasp->wrappedObject(cx, obj);
+ return op(cx, obj);
}
// Get the (possibly nonexistent) COW off of an object
// TODO Move to XPCWrapper and share with other wrappers.
static inline
JSObject *
GetWrapper(JSObject *obj)
{
- while (obj->getJSClass() != &COWClass.base) {
+ while (obj->getClass() != &COWClass) {
obj = obj->getProto();
if (!obj) {
break;
}
}
return obj;
}
@@ -743,18 +744,17 @@ XPC_COW_Equality(JSContext *cx, JSObject
*bp = JS_FALSE;
return JS_TRUE;
}
XPCWrappedNative *me = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
obj = me->GetFlatJSObject();
test = other->GetFlatJSObject();
jsval testVal = OBJECT_TO_JSVAL(test);
- return ((JSExtendedClass *)obj->getJSClass())->
- equality(cx, obj, &testVal, bp);
+ return js::Jsvalify(obj->getClass()->ext.equality)(cx, obj, &testVal, bp);
}
static JSObject *
XPC_COW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
{
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
ThrowException(NS_ERROR_INVALID_ARG, cx);
--- a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp
+++ b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp
@@ -120,17 +120,17 @@ ThrowException(nsresult ex, JSContext *c
return JS_FALSE;
}
// Get the (possibly nonexistent) XOW off of an object
static inline
JSObject *
GetWrapper(JSObject *obj)
{
- while (obj->getJSClass() != &XPCCrossOriginWrapper::XOWClass.base) {
+ while (obj->getClass() != &XPCCrossOriginWrapper::XOWClass) {
obj = obj->getProto();
if (!obj) {
break;
}
}
return obj;
}
@@ -151,38 +151,44 @@ XPC_XOW_FunctionWrapper(JSContext *cx, J
static const PRUint32 FLAG_IS_UXPC_OBJECT = XPCWrapper::LAST_FLAG << 1;
// This flag is set on objects that have to clear their wrapped native's XOW
// cache when they get finalized.
static const PRUint32 FLAG_IS_CACHED = XPCWrapper::LAST_FLAG << 2;
namespace XPCCrossOriginWrapper {
-JSExtendedClass XOWClass = {
- // JSClass (JSExtendedClass.base) initialization
- { "XPCCrossOriginWrapper",
- JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
+js::Class XOWClass = {
+ "XPCCrossOriginWrapper",
+ JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 2),
- XPC_XOW_AddProperty, XPC_XOW_DelProperty,
- XPC_XOW_GetProperty, XPC_XOW_SetProperty,
- XPC_XOW_Enumerate, (JSResolveOp)XPC_XOW_NewResolve,
- XPC_XOW_Convert, XPC_XOW_Finalize,
- nsnull, XPC_XOW_CheckAccess,
- XPC_XOW_Call, XPC_XOW_Construct,
- nsnull, XPC_XOW_HasInstance,
- nsnull, nsnull
- },
+ js::Valueify(XPC_XOW_AddProperty),
+ js::Valueify(XPC_XOW_DelProperty),
+ js::Valueify(XPC_XOW_GetProperty),
+ js::Valueify(XPC_XOW_SetProperty),
+ XPC_XOW_Enumerate,
+ (JSResolveOp)XPC_XOW_NewResolve,
+ js::Valueify(XPC_XOW_Convert),
+ XPC_XOW_Finalize,
+ nsnull, // reserved0
+ js::Valueify(XPC_XOW_CheckAccess),
+ js::Valueify(XPC_XOW_Call),
+ js::Valueify(XPC_XOW_Construct),
+ nsnull, // xdrObject
+ js::Valueify(XPC_XOW_HasInstance),
+ nsnull, // mark
- // JSExtendedClass initialization
- XPC_XOW_Equality,
- nsnull, // outerObject
- nsnull, // innerObject
- XPC_XOW_Iterator,
- XPC_XOW_WrappedObject,
- JSCLASS_NO_RESERVED_MEMBERS
+ // ClassExtension
+ {
+ js::Valueify(XPC_XOW_Equality),
+ nsnull, // outerObject
+ nsnull, // innerObject
+ XPC_XOW_Iterator,
+ XPC_XOW_WrappedObject
+ }
};
JSBool
WrapperMoved(JSContext *cx, XPCWrappedNative *innerObj,
XPCWrappedNativeScope *newScope)
{
typedef WrappedNative2WrapperMap::Link Link;
XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
@@ -371,17 +377,17 @@ RewrapIfNeeded(JSContext *cx, JSObject *
JSObject *obj = JSVAL_TO_OBJECT(*vp);
if (JS_ObjectIsFunction(cx, obj)) {
return WrapFunction(cx, outerObj, obj, vp);
}
XPCWrappedNative *wn = nsnull;
- if (obj->getJSClass() == &XOWClass.base &&
+ if (obj->getClass() == &XOWClass &&
outerObj->getParent() != obj->getParent()) {
*vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, obj));
} else if (!(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj))) {
return JS_TRUE;
}
return WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp, wn);
}
@@ -392,17 +398,17 @@ WrapObject(JSContext *cx, JSObject *pare
NS_ASSERTION(XPCPerThreadData::IsMainThread(cx),
"Can't do this off the main thread!");
// Our argument should be a wrapped native object, but the caller may have
// passed it in as an optimization.
JSObject *wrappedObj;
if (JSVAL_IS_PRIMITIVE(*vp) ||
!(wrappedObj = JSVAL_TO_OBJECT(*vp)) ||
- wrappedObj->getJSClass() == &XOWClass.base) {
+ wrappedObj->getClass() == &XOWClass) {
return JS_TRUE;
}
if (!wn &&
!(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, wrappedObj))) {
return JS_TRUE;
}
@@ -440,30 +446,30 @@ WrapObject(JSContext *cx, JSObject *pare
parentScope = XPCWrappedNativeScope::FindInJSObjectScope(cx, parent);
}
JSObject *outerObj = nsnull;
WrappedNative2WrapperMap *map = parentScope->GetWrapperMap();
outerObj = map->Find(wrappedObj);
if (outerObj) {
- NS_ASSERTION(outerObj->getJSClass() == &XOWClass.base,
+ NS_ASSERTION(outerObj->getClass() == &XOWClass,
"What crazy object are we getting here?");
*vp = OBJECT_TO_JSVAL(outerObj);
if (wnxow) {
// NB: wnxow->GetXOW() must have returned false.
SetFlags(cx, outerObj, AddFlags(GetFlags(cx, outerObj), FLAG_IS_CACHED));
wnxow->SetXOW(outerObj);
}
return JS_TRUE;
}
- outerObj = JS_NewObjectWithGivenProto(cx, &XOWClass.base, nsnull,
+ outerObj = JS_NewObjectWithGivenProto(cx, js::Jsvalify(&XOWClass), nsnull,
parent);
if (!outerObj) {
return JS_FALSE;
}
jsval flags = INT_TO_JSVAL(wnxow ? FLAG_IS_CACHED : 0);
if (!JS_SetReservedSlot(cx, outerObj, sWrappedObjSlot, *vp) ||
!JS_SetReservedSlot(cx, outerObj, sFlagsSlot, flags) ||
@@ -585,24 +591,24 @@ WrapSameOriginProp(JSContext *cx, JSObje
{
// Don't call RewrapIfNeeded for same origin properties. We only
// need to wrap window, document and location.
if (JSVAL_IS_PRIMITIVE(*vp)) {
return JS_TRUE;
}
JSObject *wrappedObj = JSVAL_TO_OBJECT(*vp);
- JSClass *clasp = wrappedObj->getJSClass();
+ js::Class *clasp = wrappedObj->getClass();
if (ClassNeedsXOW(clasp->name)) {
return WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp);
}
// Check if wrappedObj is an XOW. If so, verify that it's from the
// right scope.
- if (clasp == &XOWClass.base &&
+ if (clasp == &XOWClass &&
wrappedObj->getParent() != outerObj->getParent()) {
*vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, wrappedObj));
return WrapObject(cx, outerObj->getParent(), vp);
}
return JS_TRUE;
}
@@ -615,17 +621,17 @@ XPC_XOW_AddProperty(JSContext *cx, JSObj
obj = GetWrapper(obj);
jsval resolving;
if (!JS_GetReservedSlot(cx, obj, sFlagsSlot, &resolving)) {
return JS_FALSE;
}
if (!JSVAL_IS_PRIMITIVE(*vp)) {
JSObject *addedObj = JSVAL_TO_OBJECT(*vp);
- if (addedObj->getJSClass() == &XOWClass.base &&
+ if (addedObj->getClass() == &XOWClass &&
addedObj->getParent() != obj->getParent()) {
*vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, addedObj));
if (!WrapObject(cx, obj->getParent(), vp, nsnull)) {
return JS_FALSE;
}
}
}
@@ -837,17 +843,17 @@ XPC_XOW_Enumerate(JSContext *cx, JSObjec
// UXPCObject (which is just a XOW for the same object). This causes the JS
// engine to do all of its work on another object, not polluting the main
// object. However, if the get results in calling a setter, the engine still
// uses the regular object as 'this', ensuring that the UXPCObject doesn't
// leak to script.
static JSObject *
GetUXPCObject(JSContext *cx, JSObject *obj)
{
- NS_ASSERTION(obj->getJSClass() == &XOWClass.base, "wrong object");
+ NS_ASSERTION(obj->getClass() == &XOWClass, "wrong object");
jsval v;
if (!JS_GetReservedSlot(cx, obj, sFlagsSlot, &v)) {
return nsnull;
}
if (HAS_FLAGS(v, FLAG_IS_UXPC_OBJECT)) {
return obj;
@@ -857,17 +863,18 @@ GetUXPCObject(JSContext *cx, JSObject *o
return nsnull;
}
if (JSVAL_IS_OBJECT(v)) {
return JSVAL_TO_OBJECT(v);
}
JSObject *uxpco =
- JS_NewObjectWithGivenProto(cx, &XOWClass.base, nsnull, obj->getParent());
+ JS_NewObjectWithGivenProto(cx, js::Jsvalify(&XOWClass), nsnull,
+ obj->getParent());
if (!uxpco) {
return nsnull;
}
js::AutoObjectRooter tvr(cx, uxpco);
jsval wrappedObj, parentScope;
if (!JS_GetReservedSlot(cx, obj, sWrappedObjSlot, &wrappedObj) ||
@@ -1176,17 +1183,17 @@ XPC_XOW_Equality(JSContext *cx, JSObject
// Convert both sides to XPCWrappedNative and see if they match.
if (JSVAL_IS_PRIMITIVE(v)) {
*bp = JS_FALSE;
return JS_TRUE;
}
JSObject *test = JSVAL_TO_OBJECT(v);
- if (test->getJSClass() == &XOWClass.base) {
+ if (test->getClass() == &XOWClass) {
if (!JS_GetReservedSlot(cx, test, sWrappedObjSlot, &v)) {
return JS_FALSE;
}
if (JSVAL_IS_PRIMITIVE(v)) {
*bp = JS_FALSE;
return JS_TRUE;
}
@@ -1204,18 +1211,17 @@ XPC_XOW_Equality(JSContext *cx, JSObject
*bp = JS_FALSE;
return JS_TRUE;
}
XPCWrappedNative *me = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
obj = me->GetFlatJSObject();
test = other->GetFlatJSObject();
jsval testVal = OBJECT_TO_JSVAL(test);
- return ((JSExtendedClass *)obj->getJSClass())->
- equality(cx, obj, &testVal, bp);
+ return js::Jsvalify(obj->getClass()->ext.equality)(cx, obj, &testVal, bp);
}
static JSObject *
XPC_XOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
{
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
ThrowException(NS_ERROR_INVALID_ARG, cx);
@@ -1235,17 +1241,17 @@ XPC_XOW_Iterator(JSContext *cx, JSObject
ThrowException(rv, cx);
return nsnull;
}
ThrowException(NS_ERROR_FAILURE, cx);
return nsnull;
}
- JSObject *wrapperIter = JS_NewObject(cx, &XOWClass.base, nsnull,
+ JSObject *wrapperIter = JS_NewObject(cx, js::Jsvalify(&XOWClass), nsnull,
JS_GetGlobalForObject(cx, obj));
if (!wrapperIter) {
return nsnull;
}
js::AutoObjectRooter tvr(cx, wrapperIter);
// Initialize our XOW.
--- a/js/src/xpconnect/src/XPCNativeWrapper.cpp
+++ b/js/src/xpconnect/src/XPCNativeWrapper.cpp
@@ -104,66 +104,78 @@ using namespace XPCWrapper;
// not have expando properties set on implicit native wrappers.
static const PRUint32 FLAG_EXPLICIT = XPCWrapper::LAST_FLAG << 1;
namespace XPCNativeWrapper { namespace internal {
// JS class for XPCNativeWrapper (and this doubles as the constructor
// for XPCNativeWrapper for the moment too...)
-JSExtendedClass NW_NoCall_Class = {
- // JSClass (JSExtendedClass.base) initialization
- { "XPCNativeWrapper",
+js::Class NW_NoCall_Class = {
+ "XPCNativeWrapper",
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
// Our one reserved slot holds a jsint of flag bits
JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1) |
- JSCLASS_MARK_IS_TRACE | JSCLASS_IS_EXTENDED | JSCLASS_CONSTRUCT_PROTOTYPE,
- XPC_NW_AddProperty, XPC_NW_DelProperty,
- XPC_NW_GetProperty, XPC_NW_SetProperty,
- XPC_NW_Enumerate, (JSResolveOp)XPC_NW_NewResolve,
- XPC_NW_Convert, XPC_NW_Finalize,
- nsnull, XPC_NW_CheckAccess,
- nsnull, XPC_NW_Construct,
- nsnull, XPC_NW_HasInstance,
- JS_CLASS_TRACE(XPC_NW_Trace), nsnull
- },
+ JSCLASS_MARK_IS_TRACE | JSCLASS_CONSTRUCT_PROTOTYPE,
+ js::Valueify(XPC_NW_AddProperty),
+ js::Valueify(XPC_NW_DelProperty),
+ js::Valueify(XPC_NW_GetProperty),
+ js::Valueify(XPC_NW_SetProperty),
+ XPC_NW_Enumerate,
+ (JSResolveOp)XPC_NW_NewResolve,
+ js::Valueify(XPC_NW_Convert),
+ XPC_NW_Finalize,
+ nsnull, // reserved0
+ js::Valueify(XPC_NW_CheckAccess),
+ nsnull, // call
+ js::Valueify(XPC_NW_Construct),
+ nsnull, // xdrObject
+ js::Valueify(XPC_NW_HasInstance),
+ JS_CLASS_TRACE(XPC_NW_Trace),
- // JSExtendedClass initialization
- XPC_NW_Equality,
- nsnull, // outerObject
- nsnull, // innerObject
- XPC_NW_Iterator,
- nsnull, // wrappedObject
- JSCLASS_NO_RESERVED_MEMBERS
+ // ClassExtension
+ {
+ js::Valueify(XPC_NW_Equality),
+ nsnull, // outerObject
+ nsnull, // innerObject
+ XPC_NW_Iterator,
+ nsnull, // wrappedObject
+ }
};
-JSExtendedClass NW_Call_Class = {
- // JSClass (JSExtendedClass.base) initialization
- { "XPCNativeWrapper",
+js::Class NW_Call_Class = {
+ "XPCNativeWrapper",
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
// Our one reserved slot holds a jsint of flag bits
JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1) |
- JSCLASS_MARK_IS_TRACE | JSCLASS_IS_EXTENDED | JSCLASS_CONSTRUCT_PROTOTYPE,
- XPC_NW_AddProperty, XPC_NW_DelProperty,
- XPC_NW_GetProperty, XPC_NW_SetProperty,
- XPC_NW_Enumerate, (JSResolveOp)XPC_NW_NewResolve,
- XPC_NW_Convert, XPC_NW_Finalize,
- nsnull, XPC_NW_CheckAccess,
- XPC_NW_Call, XPC_NW_Construct,
- nsnull, XPC_NW_HasInstance,
- JS_CLASS_TRACE(XPC_NW_Trace), nsnull
- },
+ JSCLASS_MARK_IS_TRACE | JSCLASS_CONSTRUCT_PROTOTYPE,
+ js::Valueify(XPC_NW_AddProperty),
+ js::Valueify(XPC_NW_DelProperty),
+ js::Valueify(XPC_NW_GetProperty),
+ js::Valueify(XPC_NW_SetProperty),
+ XPC_NW_Enumerate,
+ (JSResolveOp)XPC_NW_NewResolve,
+ js::Valueify(XPC_NW_Convert),
+ XPC_NW_Finalize,
+ nsnull, // reserved0
+ js::Valueify(XPC_NW_CheckAccess),
+ js::Valueify(XPC_NW_Call),
+ js::Valueify(XPC_NW_Construct),
+ nsnull, // xdrObject
+ js::Valueify(XPC_NW_HasInstance),
+ JS_CLASS_TRACE(XPC_NW_Trace),
- // JSExtendedClass initialization
- XPC_NW_Equality,
- nsnull, // outerObject
- nsnull, // innerObject
- XPC_NW_Iterator,
- nsnull, // wrappedObject
- JSCLASS_NO_RESERVED_MEMBERS
+ // ClassExtension
+ {
+ js::Valueify(XPC_NW_Equality),
+ nsnull, // outerObject
+ nsnull, // innerObject
+ XPC_NW_Iterator,
+ nsnull, // wrappedObject
+ }
};
} // namespace internal
JSBool
GetWrappedNative(JSContext *cx, JSObject *obj,
XPCWrappedNative **aWrappedNative)
{
@@ -1023,17 +1035,18 @@ static JSFunctionSpec static_functions[]
};
// static
PRBool
XPCNativeWrapper::AttachNewConstructorObject(XPCCallContext &ccx,
JSObject *aGlobalObject)
{
JSObject *class_obj =
- ::JS_InitClass(ccx, aGlobalObject, nsnull, &internal::NW_Call_Class.base,
+ ::JS_InitClass(ccx, aGlobalObject, nsnull,
+ js::Jsvalify(&internal::NW_Call_Class),
XPCNativeWrapperCtor, 0, nsnull, nsnull,
nsnull, static_functions);
if (!class_obj) {
NS_WARNING("can't initialize the XPCNativeWrapper class");
return PR_FALSE;
}
// Make sure our prototype chain is empty and that people can't mess
@@ -1041,17 +1054,17 @@ XPCNativeWrapper::AttachNewConstructorOb
::JS_SetPrototype(ccx, class_obj, nsnull);
if (!::JS_SealObject(ccx, class_obj, JS_FALSE)) {
NS_WARNING("Failed to seal XPCNativeWrapper.prototype");
return PR_FALSE;
}
JSBool found;
return ::JS_SetPropertyAttributes(ccx, aGlobalObject,
- internal::NW_Call_Class.base.name,
+ internal::NW_Call_Class.name,
JSPROP_READONLY | JSPROP_PERMANENT,
&found);
}
// static
JSObject *
XPCNativeWrapper::GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper,
JSObject *scope, nsIPrincipal *aObjectPrincipal)
--- a/js/src/xpconnect/src/XPCNativeWrapper.h
+++ b/js/src/xpconnect/src/XPCNativeWrapper.h
@@ -40,40 +40,40 @@
#include "nscore.h"
#include "jsapi.h"
class nsIPrincipal;
namespace XPCNativeWrapper {
namespace internal {
- extern JSExtendedClass NW_NoCall_Class;
- extern JSExtendedClass NW_Call_Class;
+extern js::Class NW_NoCall_Class;
+extern js::Class NW_Call_Class;
}
PRBool
AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject);
JSObject *
GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper,
JSObject *scope, nsIPrincipal *aObjectPrincipal);
JSBool
CreateExplicitWrapper(JSContext *cx, XPCWrappedNative *wrapper, jsval *rval);
inline PRBool
-IsNativeWrapperClass(JSClass *clazz)
+IsNativeWrapperClass(js::Class *clazz)
{
- return clazz == &internal::NW_NoCall_Class.base ||
- clazz == &internal::NW_Call_Class.base;
+ return clazz == &internal::NW_NoCall_Class ||
+ clazz == &internal::NW_Call_Class;
}
inline PRBool
IsNativeWrapper(JSObject *obj)
{
- return IsNativeWrapperClass(obj->getJSClass());
+ return IsNativeWrapperClass(obj->getClass());
}
JSBool
GetWrappedNative(JSContext *cx, JSObject *obj,
XPCWrappedNative **aWrappedNative);
// NB: Use the following carefully.
inline XPCWrappedNative *
@@ -81,16 +81,16 @@ SafeGetWrappedNative(JSObject *obj)
{
return static_cast<XPCWrappedNative *>(xpc_GetJSPrivate(obj));
}
inline JSClass *
GetJSClass(bool call)
{
return call
- ? &internal::NW_Call_Class.base
- : &internal::NW_NoCall_Class.base;
+ ? js::Jsvalify(&internal::NW_Call_Class)
+ : js::Jsvalify(&internal::NW_NoCall_Class);
}
void
ClearWrappedNativeScopes(JSContext* cx, XPCWrappedNative* wrapper);
}
--- a/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp
+++ b/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp
@@ -228,17 +228,17 @@ FindObjectPrincipals(JSContext *cx, JSOb
// The wrapper owns the principal now.
return objPrincipal.forget().get();
}
static inline JSObject *
FindSafeObject(JSObject *obj)
{
- while (obj->getJSClass() != &SJOWClass.base) {
+ while (obj->getClass() != &SJOWClass) {
obj = obj->getProto();
if (!obj) {
break;
}
}
return obj;
@@ -248,37 +248,44 @@ static JSBool
XPC_SJOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
namespace XPCSafeJSObjectWrapper {
// JS class for XPCSafeJSObjectWrapper (and this doubles as the
// constructor for XPCSafeJSObjectWrapper for the moment too...)
-JSExtendedClass SJOWClass = {
- // JSClass (JSExtendedClass.base) initialization
- { "XPCSafeJSObjectWrapper",
- JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
+js::Class SJOWClass = {
+ "XPCSafeJSObjectWrapper",
+ JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_RESERVED_SLOTS(sSJOWSlots),
- XPC_SJOW_AddProperty, XPC_SJOW_DelProperty,
- XPC_SJOW_GetProperty, XPC_SJOW_SetProperty,
- XPC_SJOW_Enumerate, (JSResolveOp)XPC_SJOW_NewResolve,
- XPC_SJOW_Convert, XPC_SJOW_Finalize,
- nsnull, XPC_SJOW_CheckAccess,
- XPC_SJOW_Call, XPC_SJOW_Create,
- nsnull, nsnull,
- nsnull, nsnull
- },
- // JSExtendedClass initialization
- XPC_SJOW_Equality,
- nsnull, // outerObject
- nsnull, // innerObject
- XPC_SJOW_Iterator,
- XPC_SJOW_WrappedObject,
- JSCLASS_NO_RESERVED_MEMBERS
+ js::Valueify(XPC_SJOW_AddProperty),
+ js::Valueify(XPC_SJOW_DelProperty),
+ js::Valueify(XPC_SJOW_GetProperty),
+ js::Valueify(XPC_SJOW_SetProperty),
+ XPC_SJOW_Enumerate,
+ (JSResolveOp)XPC_SJOW_NewResolve,
+ js::Valueify(XPC_SJOW_Convert),
+ XPC_SJOW_Finalize,
+ nsnull, // reserved0
+ js::Valueify(XPC_SJOW_CheckAccess),
+ js::Valueify(XPC_SJOW_Call),
+ js::Valueify(XPC_SJOW_Create),
+ nsnull, // xdrObject
+ nsnull, // hasInstance
+ nsnull, // mark
+
+ // ClassExtension
+ {
+ js::Valueify(XPC_SJOW_Equality),
+ nsnull, // outerObject
+ nsnull, // innerObject
+ XPC_SJOW_Iterator,
+ XPC_SJOW_WrappedObject
+ }
};
JSBool
WrapObject(JSContext *cx, JSObject *scope, jsval v, jsval *vp)
{
// This might be redundant if called from XPC_SJOW_Construct, but it should
// be cheap in that case.
JSObject *objToWrap = UnsafeUnwrapSecurityWrapper(cx, JSVAL_TO_OBJECT(v));
@@ -313,17 +320,17 @@ WrapObject(JSContext *cx, JSObject *scop
}
SLIM_LOG_WILL_MORPH(cx, objToWrap);
if (IS_SLIM_WRAPPER(objToWrap) && !MorphSlimWrapper(cx, objToWrap)) {
return ThrowException(NS_ERROR_FAILURE, cx);
}
JSObject *wrapperObj =
- JS_NewObjectWithGivenProto(cx, &SJOWClass.base, nsnull, scope);
+ JS_NewObjectWithGivenProto(cx, js::Jsvalify(&SJOWClass), nsnull, scope);
if (!wrapperObj) {
// JS_NewObjectWithGivenProto already threw.
return JS_FALSE;
}
*vp = OBJECT_TO_JSVAL(wrapperObj);
if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot,
@@ -341,17 +348,17 @@ AttachNewConstructorObject(XPCCallContex
// Initialize sEvalNative the first time we attach a constructor.
// NB: This always happens before any cross origin wrappers are
// created, so it's OK to do this here.
if (!XPCWrapper::FindEval(ccx, aGlobalObject)) {
return PR_FALSE;
}
JSObject *class_obj =
- ::JS_InitClass(ccx, aGlobalObject, nsnull, &SJOWClass.base,
+ ::JS_InitClass(ccx, aGlobalObject, nsnull, js::Jsvalify(&SJOWClass),
XPC_SJOW_Construct, 0, nsnull, nsnull, nsnull, nsnull);
if (!class_obj) {
NS_WARNING("can't initialize the XPCSafeJSObjectWrapper class");
return PR_FALSE;
}
if (!::JS_DefineFunction(ccx, class_obj, "toString", XPC_SJOW_toString,
0, 0)) {
@@ -363,17 +370,17 @@ AttachNewConstructorObject(XPCCallContex
::JS_SetPrototype(ccx, class_obj, nsnull);
if (!::JS_SealObject(ccx, class_obj, JS_FALSE)) {
NS_WARNING("Failed to seal XPCSafeJSObjectWrapper.prototype");
return PR_FALSE;
}
JSBool found;
return ::JS_SetPropertyAttributes(ccx, aGlobalObject,
- SJOWClass.base.name,
+ SJOWClass.name,
JSPROP_READONLY | JSPROP_PERMANENT,
&found);
}
JSObject *
GetUnsafeObject(JSContext *cx, JSObject *obj)
{
obj = FindSafeObject(obj);
@@ -441,17 +448,17 @@ WrapJSValue(JSContext *cx, JSObject *obj
if (!RewrapObject(cx, obj->getParent(), JSVAL_TO_OBJECT(val), SJOW,
rval)) {
return JS_FALSE;
}
// Construct a new safe wrapper. Note that it doesn't matter what
// parent we pass in here, the construct hook will ensure we get
// the right parent for the wrapper.
JSObject *safeObj = JSVAL_TO_OBJECT(*rval);
- if (safeObj->getJSClass() == &SJOWClass.base &&
+ if (safeObj->getClass() == &SJOWClass &&
JS_GetGlobalForObject(cx, obj) != JS_GetGlobalForObject(cx, safeObj)) {
// Check to see if the new object we just wrapped is accessible
// from the unsafe object we got the new object through. If not,
// force the new wrapper to use the principal of the unsafe
// object we got the new object from.
nsCOMPtr<nsIPrincipal> srcObjPrincipal;
nsCOMPtr<nsIPrincipal> subjPrincipal;
nsCOMPtr<nsIPrincipal> valObjPrincipal;
@@ -1025,17 +1032,17 @@ XPC_SJOW_Iterator(JSContext *cx, JSObjec
// Check that the caller can access the unsafe object.
if (!CanCallerAccess(cx, obj, unsafeObj)) {
// CanCallerAccess() already threw for us.
return nsnull;
}
// Create our dummy SJOW.
JSObject *wrapperIter =
- JS_NewObjectWithGivenProto(cx, &SJOWClass.base, nsnull,
+ JS_NewObjectWithGivenProto(cx, js::Jsvalify(&SJOWClass), nsnull,
JS_GetGlobalForObject(cx, obj));
if (!wrapperIter) {
return nsnull;
}
if (!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sWrappedObjSlot,
OBJECT_TO_JSVAL(unsafeObj)) ||
!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sFlagsSlot,
--- a/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp
+++ b/js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp
@@ -93,52 +93,58 @@ ThrowException(nsresult rv, JSContext *c
{
return DoThrowException(rv, cx);
}
static const char prefix[] = "chrome://global/";
namespace SystemOnlyWrapper {
-JSExtendedClass SOWClass = {
- // JSClass (JSExtendedClass.base) initialization
- { "SystemOnlyWrapper",
- JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
+js::Class SOWClass = {
+ "SystemOnlyWrapper",
+ JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots),
- XPC_SOW_AddProperty, XPC_SOW_DelProperty,
- XPC_SOW_GetProperty, XPC_SOW_SetProperty,
- XPC_SOW_Enumerate, (JSResolveOp)XPC_SOW_NewResolve,
- XPC_SOW_Convert, nsnull,
- nsnull, XPC_SOW_CheckAccess,
- nsnull, nsnull,
- nsnull, XPC_SOW_HasInstance,
- nsnull, nsnull
- },
+ js::Valueify(XPC_SOW_AddProperty),
+ js::Valueify(XPC_SOW_DelProperty),
+ js::Valueify(XPC_SOW_GetProperty),
+ js::Valueify(XPC_SOW_SetProperty),
+ XPC_SOW_Enumerate,
+ (JSResolveOp)XPC_SOW_NewResolve,
+ js::Valueify(XPC_SOW_Convert),
+ nsnull, // finalize
+ nsnull, // reserved0
+ js::Valueify(XPC_SOW_CheckAccess),
+ nsnull, // call
+ nsnull, // construct
+ nsnull, // xdrObject
+ js::Valueify(XPC_SOW_HasInstance),
+ nsnull, // mark
- // JSExtendedClass initialization
- XPC_SOW_Equality,
- nsnull, // outerObject
- nsnull, // innerObject
- XPC_SOW_Iterator,
- XPC_SOW_WrappedObject,
- JSCLASS_NO_RESERVED_MEMBERS
+ // ClassExtension
+ {
+ js::Valueify(XPC_SOW_Equality),
+ nsnull, // outerObject
+ nsnull, // innerObject
+ XPC_SOW_Iterator,
+ XPC_SOW_WrappedObject
+ }
};
JSBool
WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp)
{
// Slim wrappers don't expect to be wrapped, so morph them to fat wrappers
// if we're about to wrap one.
JSObject *innerObj = JSVAL_TO_OBJECT(v);
if (IS_SLIM_WRAPPER(innerObj) && !MorphSlimWrapper(cx, innerObj)) {
return ThrowException(NS_ERROR_FAILURE, cx);
}
JSObject *wrapperObj =
- JS_NewObjectWithGivenProto(cx, &SOWClass.base, NULL, parent);
+ JS_NewObjectWithGivenProto(cx, js::Jsvalify(&SOWClass), NULL, parent);
if (!wrapperObj) {
return JS_FALSE;
}
*vp = OBJECT_TO_JSVAL(wrapperObj);
js::AutoObjectRooter tvr(cx, wrapperObj);
if (!JS_SetReservedSlot(cx, wrapperObj, sWrappedObjSlot, v) ||
@@ -149,19 +155,19 @@ WrapObject(JSContext *cx, JSObject *pare
return JS_TRUE;
}
JSBool
MakeSOW(JSContext *cx, JSObject *obj)
{
#ifdef DEBUG
{
- JSClass *clasp = obj->getJSClass();
- NS_ASSERTION(clasp != &SystemOnlyWrapper::SOWClass.base &&
- clasp != &XPCCrossOriginWrapper::XOWClass.base,
+ js::Class *clasp = obj->getClass();
+ NS_ASSERTION(clasp != &SystemOnlyWrapper::SOWClass &&
+ clasp != &XPCCrossOriginWrapper::XOWClass,
"bad call");
}
#endif
jsval flags;
return JS_GetReservedSlot(cx, obj, sFlagsSlot, &flags) &&
JS_SetReservedSlot(cx, obj, sFlagsSlot,
INT_TO_JSVAL(JSVAL_TO_INT(flags) | FLAG_SOW));
@@ -263,35 +269,27 @@ CheckFilename(JSContext *cx, jsid id, JS
using namespace SystemOnlyWrapper;
// Like GetWrappedObject, but works on other types of wrappers, too.
// TODO Move to XPCWrapper?
static inline JSObject *
GetWrappedJSObject(JSContext *cx, JSObject *obj)
{
- JSClass *clasp = obj->getJSClass();
- if (!(clasp->flags & JSCLASS_IS_EXTENDED)) {
- return obj;
- }
-
- JSExtendedClass *xclasp = (JSExtendedClass *)clasp;
- if (!xclasp->wrappedObject) {
- return obj;
- }
-
- return xclasp->wrappedObject(cx, obj);
+ if (JSObjectOp op = obj->getClass()->ext.wrappedObject)
+ return op(cx, obj);
+ return obj;
}
// Get the (possibly nonexistent) SOW off of an object
static inline
JSObject *
GetWrapper(JSObject *obj)
{
- while (obj->getJSClass() != &SOWClass.base) {
+ while (obj->getClass() != &SOWClass) {
obj = obj->getProto();
if (!obj) {
break;
}
}
return obj;
}
@@ -400,17 +398,17 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObj
return JS_FALSE;
}
obj = JSVAL_TO_OBJECT(v);
}
return XPC_SOW_WrapFunction(cx, wrapperObj, obj, vp);
}
- if (obj->getJSClass() == &SOWClass.base) {
+ if (obj->getClass() == &SOWClass) {
// We are extra careful about content-polluted wrappers here. I don't know
// if it's possible to reach them through objects that we wrap, but figuring
// that out is more expensive (and harder) than simply checking and
// rewrapping here.
if (wrapperObj->getParent() == obj->getParent()) {
// Already wrapped.
return JS_TRUE;
}
@@ -425,17 +423,17 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObj
}
return WrapObject(cx, wrapperObj->getParent(), v, vp);
}
static JSBool
XPC_SOW_AddProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
- NS_ASSERTION(obj->getJSClass() == &SOWClass.base, "Wrong object");
+ NS_ASSERTION(obj->getClass() == &SOWClass, "Wrong object");
jsval resolving;
if (!JS_GetReservedSlot(cx, obj, sFlagsSlot, &resolving)) {
return JS_FALSE;
}
if (HAS_FLAGS(resolving, FLAG_RESOLVING)) {
// Allow us to define a property on ourselves.
@@ -648,49 +646,42 @@ XPC_SOW_Equality(JSContext *cx, JSObject
JSObject *lhs = GetWrappedObject(cx, obj);
JSObject *rhs = GetWrappedJSObject(cx, JSVAL_TO_OBJECT(v));
if (lhs == rhs) {
*bp = JS_TRUE;
return JS_TRUE;
}
if (lhs) {
- // Delegate to our wrapped object if we can.
- JSClass *clasp = lhs->getJSClass();
- if (clasp->flags & JSCLASS_IS_EXTENDED) {
- JSExtendedClass *xclasp = (JSExtendedClass *) clasp;
- // NB: JSExtendedClass.equality is a required field.
+ if (JSEqualityOp op = js::Jsvalify(lhs->getClass()->ext.equality)) {
jsval rhsVal = OBJECT_TO_JSVAL(rhs);
- return xclasp->equality(cx, lhs, &rhsVal, bp);
+ return op(cx, lhs, &rhsVal, bp);
}
}
// We know rhs is non-null.
- JSClass *clasp = rhs->getJSClass();
- if (clasp->flags & JSCLASS_IS_EXTENDED) {
- JSExtendedClass *xclasp = (JSExtendedClass *) clasp;
- // NB: JSExtendedClass.equality is a required field.
+ if (JSEqualityOp op = js::Jsvalify(rhs->getClass()->ext.equality)) {
jsval lhsVal = OBJECT_TO_JSVAL(lhs);
- return xclasp->equality(cx, rhs, &lhsVal, bp);
+ return op(cx, rhs, &lhsVal, bp);
}
*bp = JS_FALSE;
return JS_TRUE;
}
static JSObject *
XPC_SOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
{
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
ThrowException(NS_ERROR_INVALID_ARG, cx);
return nsnull;
}
- JSObject *wrapperIter = JS_NewObject(cx, &SOWClass.base, nsnull,
+ JSObject *wrapperIter = JS_NewObject(cx, js::Jsvalify(&SOWClass), nsnull,
JS_GetGlobalForObject(cx, obj));
if (!wrapperIter) {
return nsnull;
}
js::AutoObjectRooter tvr(cx, wrapperIter);
// Initialize our SOW.
--- a/js/src/xpconnect/src/XPCWrapper.cpp
+++ b/js/src/xpconnect/src/XPCWrapper.cpp
@@ -55,48 +55,48 @@ const PRUint32 FLAG_SOW = 0x2;
const PRUint32 LAST_FLAG = FLAG_SOW;
const PRUint32 sSecMgrSetProp = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
const PRUint32 sSecMgrGetProp = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
JSObject *
Unwrap(JSContext *cx, JSObject *wrapper)
{
- JSClass *clasp = wrapper->getJSClass();
- if (clasp == &XPCCrossOriginWrapper::XOWClass.base) {
+ js::Class *clasp = wrapper->getClass();
+ if (clasp == &XPCCrossOriginWrapper::XOWClass) {
return UnwrapXOW(cx, wrapper);
}
if (XPCNativeWrapper::IsNativeWrapperClass(clasp)) {
XPCWrappedNative *wrappedObj;
if (!XPCNativeWrapper::GetWrappedNative(cx, wrapper, &wrappedObj) ||
!wrappedObj) {
return nsnull;
}
return wrappedObj->GetFlatJSObject();
}
- if (clasp == &XPCSafeJSObjectWrapper::SJOWClass.base) {
+ if (clasp == &XPCSafeJSObjectWrapper::SJOWClass) {
JSObject *wrappedObj =
XPCSafeJSObjectWrapper::GetUnsafeObject(cx, wrapper);
if (NS_FAILED(XPCCrossOriginWrapper::CanAccessWrapper(cx, nsnull, wrappedObj, nsnull))) {
JS_ClearPendingException(cx);
return nsnull;
}
return wrappedObj;
}
- if (clasp == &SystemOnlyWrapper::SOWClass.base) {
+ if (clasp == &SystemOnlyWrapper::SOWClass) {
return UnwrapSOW(cx, wrapper);
}
- if (clasp == &ChromeObjectWrapper::COWClass.base) {
+ if (clasp == &ChromeObjectWrapper::COWClass) {
return UnwrapCOW(cx, wrapper);
}
return nsnull;
}
static void
IteratorFinalize(JSContext *cx, JSObject *obj)
@@ -155,32 +155,43 @@ IteratorNext(JSContext *cx, uintN argc,
}
static JSObject *
IteratorIterator(JSContext *, JSObject *obj, JSBool)
{
return obj;
}
-static JSExtendedClass IteratorClass = {
- { "Wrapper iterator",
- JSCLASS_HAS_RESERVED_SLOTS(3) | JSCLASS_IS_EXTENDED,
- JS_PropertyStub, JS_PropertyStub,
- JS_PropertyStub, JS_PropertyStub,
- JS_EnumerateStub, JS_ResolveStub,
- JS_ConvertStub, IteratorFinalize,
+static js::Class IteratorClass = {
+ "Wrapper iterator",
+ JSCLASS_HAS_RESERVED_SLOTS(3),
+ js::PropertyStub, // addProperty
+ js::PropertyStub, // delProperty
+ js::PropertyStub, // getProperty
+ js::PropertyStub, // setProperty
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ js::ConvertStub,
+ IteratorFinalize,
+ nsnull, // reserved0
+ nsnull, // checkAccess
+ nsnull, // call
+ nsnull, // construct
+ nsnull, // xdrObject
+ nsnull, // hasInstance
+ nsnull, // mark
- JSCLASS_NO_OPTIONAL_MEMBERS
- },
-
- nsnull, // equality
- nsnull, nsnull, // innerObject/outerObject
- IteratorIterator,
- nsnull, // wrappedObject
- JSCLASS_NO_RESERVED_MEMBERS
+ // ClassExtension
+ {
+ nsnull, // equality
+ nsnull, // outerObject
+ nsnull, // innerObject
+ IteratorIterator,
+ nsnull, // wrappedObject
+ }
};
JSBool
RewrapObject(JSContext *cx, JSObject *scope, JSObject *obj, WrapperType hint,
jsval *vp)
{
obj = UnsafeUnwrapSecurityWrapper(cx, obj);
if (!obj) {
@@ -326,17 +337,17 @@ CreateIteratorObj(JSContext *cx, JSObjec
{
// This is rather ugly: we want to use the trick seen in Enumerate,
// where we use our wrapper's resolve hook to determine if we should
// enumerate a given property. However, we don't want to pollute the
// identifiers with a next method, so we create an object that
// delegates (via the __proto__ link) to the wrapper.
JSObject *iterObj =
- JS_NewObjectWithGivenProto(cx, &IteratorClass.base, tempWrapper, wrapperObj);
+ JS_NewObjectWithGivenProto(cx, js::Jsvalify(&IteratorClass), tempWrapper, wrapperObj);
if (!iterObj) {
return nsnull;
}
js::AutoObjectRooter tvr(cx, iterObj);
// Do this sooner rather than later to avoid complications in
// IteratorFinalize.
@@ -389,17 +400,17 @@ SimpleEnumerate(JSContext *cx, JSObject
return JS_TRUE;
}
JSObject *
CreateSimpleIterator(JSContext *cx, JSObject *scope, JSBool keysonly,
JSObject *propertyContainer)
{
- JSObject *iterObj = JS_NewObjectWithGivenProto(cx, &IteratorClass.base,
+ JSObject *iterObj = JS_NewObjectWithGivenProto(cx, js::Jsvalify(&IteratorClass),
propertyContainer, scope);
if (!iterObj) {
return nsnull;
}
js::AutoObjectRooter tvr(cx, iterObj);
if (!propertyContainer) {
if (!JS_SetReservedSlot(cx, iterObj, 0, PRIVATE_TO_JSVAL(nsnull)) ||
--- a/js/src/xpconnect/src/XPCWrapper.h
+++ b/js/src/xpconnect/src/XPCWrapper.h
@@ -157,20 +157,20 @@ MakeSOW(JSContext *cx, JSObject *obj);
JSBool
AllowedToAct(JSContext *cx, jsid id);
JSBool
CheckFilename(JSContext *cx, jsid id, JSStackFrame *fp);
}
-namespace ChromeObjectWrapper { extern JSExtendedClass COWClass; }
-namespace XPCSafeJSObjectWrapper { extern JSExtendedClass SJOWClass; }
-namespace SystemOnlyWrapper { extern JSExtendedClass SOWClass; }
-namespace XPCCrossOriginWrapper { extern JSExtendedClass XOWClass; }
+namespace ChromeObjectWrapper { extern js::Class COWClass; }
+namespace XPCSafeJSObjectWrapper { extern js::Class SJOWClass; }
+namespace SystemOnlyWrapper { extern js::Class SOWClass; }
+namespace XPCCrossOriginWrapper { extern js::Class XOWClass; }
extern nsIScriptSecurityManager *gScriptSecurityManager;
// This namespace wraps some common functionality between the three existing
// wrappers. Its main purpose is to allow XPCCrossOriginWrapper to act both
// as an XPCSafeJSObjectWrapper and as an XPCNativeWrapper when required to
// do so (the decision is based on the principals of the wrapper and wrapped
// objects).
@@ -316,19 +316,17 @@ MaybePreserveWrapper(JSContext *cx, XPCW
ci->PreserveWrapper(wn->Native());
}
}
}
inline JSBool
IsSecurityWrapper(JSObject *wrapper)
{
- JSClass *clasp = wrapper->getJSClass();
- return (clasp->flags & JSCLASS_IS_EXTENDED) &&
- ((JSExtendedClass*)clasp)->wrappedObject;
+ return !!wrapper->getClass()->ext.wrappedObject;
}
/**
* Given an arbitrary object, Unwrap will return the wrapped object if the
* passed-in object is a wrapper that Unwrap knows about *and* the
* currently running code has permission to access both the wrapper and
* wrapped object.
*
@@ -338,19 +336,19 @@ IsSecurityWrapper(JSObject *wrapper)
*/
JSObject *
Unwrap(JSContext *cx, JSObject *wrapper);
/**
* Unwraps objects whose class is |xclasp|.
*/
inline JSObject *
-UnwrapGeneric(JSContext *cx, const JSExtendedClass *xclasp, JSObject *wrapper)
+UnwrapGeneric(JSContext *cx, const js::Class *xclasp, JSObject *wrapper)
{
- if (wrapper->getJSClass() != &xclasp->base) {
+ if (wrapper->getClass() != xclasp) {
return nsnull;
}
jsval v;
if (!JS_GetReservedSlot(cx, wrapper, XPCWrapper::sWrappedObjSlot, &v)) {
JS_ClearPendingException(cx);
return nsnull;
}
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -622,30 +622,30 @@ nsXPConnect::IsGray(void *thing)
NS_IMETHODIMP
nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
{
JSContext *cx = mCycleCollectionContext->GetJSContext();
uint32 traceKind = js_GetGCThingTraceKind(p);
JSObject *obj;
- JSClass *clazz;
+ js::Class *clazz;
// We do not want to add wrappers to the cycle collector if they're not
// explicitly marked as main thread only, because the cycle collector isn't
// able to deal with objects that might be used off of the main thread. We
// do want to explicitly mark them for cycle collection if the wrapper has
// an external reference, because the wrapper would mark the JS object if
// we did add the wrapper to the cycle collector.
JSBool dontTraverse = PR_FALSE;
JSBool markJSObject = PR_FALSE;
if(traceKind == JSTRACE_OBJECT)
{
obj = static_cast<JSObject*>(p);
- clazz = obj->getJSClass();
+ clazz = obj->getClass();
if(clazz == &XPC_WN_Tearoff_JSClass)
{
XPCWrappedNative *wrapper =
(XPCWrappedNative*)xpc_GetJSPrivate(obj->getParent());
dontTraverse = WrapperIsNotMainThreadOnly(wrapper);
}
else if(IS_WRAPPER_CLASS(clazz) && IS_WN_WRAPPER_OBJECT(obj))
@@ -684,17 +684,17 @@ nsXPConnect::Traverse(void *p, nsCycleCo
type = !markJSObject && IsGray(p) ? GCUnmarked : GCMarked;
}
if (cb.WantDebugInfo()) {
char name[72];
if(traceKind == JSTRACE_OBJECT)
{
JSObject *obj = static_cast<JSObject*>(p);
- JSClass *clazz = obj->getJSClass();
+ js::Class *clazz = obj->getClass();
if(XPCNativeWrapper::IsNativeWrapperClass(clazz))
{
XPCWrappedNative* wn;
if(XPCNativeWrapper::GetWrappedNative(cx, obj, &wn) && wn)
{
XPCNativeScriptableInfo* si = wn->GetScriptableInfo();
if(si)
{
@@ -744,31 +744,31 @@ nsXPConnect::Traverse(void *p, nsCycleCo
(XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
si = p->GetScriptableInfo();
}
if(si)
{
JS_snprintf(name, sizeof(name), "JS Object (%s - %s)",
clazz->name, si->GetJSClass()->name);
}
- else if(clazz == Jsvalify(&js_ScriptClass))
+ else if(clazz == &js_ScriptClass)
{
JSScript* script = (JSScript*) xpc_GetJSPrivate(obj);
if(script->filename)
{
JS_snprintf(name, sizeof(name),
"JS Object (Script - %s)",
script->filename);
}
else
{
JS_snprintf(name, sizeof(name), "JS Object (Script)");
}
}
- else if(clazz == Jsvalify(&js_FunctionClass))
+ else if(clazz == &js_FunctionClass)
{
JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj);
JSString* str = JS_GetFunctionId(fun);
if(str)
{
NS_ConvertUTF16toUTF8
fname(reinterpret_cast<const PRUnichar*>(JS_GetStringChars(str)));
JS_snprintf(name, sizeof(name),
@@ -1011,19 +1011,16 @@ nsXPConnect::InitClasses(JSContext * aJS
// Nest frame chain save/restore in request created by XPCCallContext.
XPCCallContext ccx(NATIVE_CALLER, aJSContext);
if(!ccx.IsValid())
return UnexpectedFailure(NS_ERROR_FAILURE);
SaveFrame sf(aJSContext);
xpc_InitJSxIDClassObjects();
- if(!xpc_InitWrappedNativeJSOps())
- return UnexpectedFailure(NS_ERROR_FAILURE);
-
XPCWrappedNativeScope* scope =
XPCWrappedNativeScope::GetNewOrUsed(ccx, aGlobalJSObj);
if(!scope)
return UnexpectedFailure(NS_ERROR_FAILURE);
scope->RemoveWrappedNativeProtos();
@@ -1912,17 +1909,17 @@ nsXPConnect::RestoreWrappedNativePrototy
if(!aClassInfo || !aPrototype)
return UnexpectedFailure(NS_ERROR_INVALID_ARG);
JSObject *protoJSObject;
nsresult rv = aPrototype->GetJSObject(&protoJSObject);
if(NS_FAILED(rv))
return UnexpectedFailure(rv);
- if(!IS_PROTO_CLASS(protoJSObject->getJSClass()))
+ if(!IS_PROTO_CLASS(protoJSObject->getClass()))
return UnexpectedFailure(NS_ERROR_INVALID_ARG);
XPCWrappedNativeScope* scope =
XPCWrappedNativeScope::FindInJSObjectScope(ccx, aScope);
if(!scope)
return UnexpectedFailure(NS_ERROR_FAILURE);
XPCWrappedNativeProto *proto =
--- a/js/src/xpconnect/src/xpcJSWeakReference.cpp
+++ b/js/src/xpconnect/src/xpcJSWeakReference.cpp
@@ -129,18 +129,18 @@ xpcJSWeakReference::Get()
// Most users of XPCWrappedJS don't need to worry about
// re-wrapping because things are implicitly rewrapped by
// xpcconvert. However, because we're doing this directly
// through the native call context, we need to call
// nsXPConnect::GetWrapperForObject. But it takes a lot of
// arguments! It turns out that the thisObject hook on XPConnect
// objects does the right thing though, so...
- if (obj->map->ops->thisObject &&
- !(obj = obj->map->ops->thisObject(cx, obj)))
+ if (obj->getOps()->thisObject &&
+ !(obj = obj->getOps()->thisObject(cx, obj)))
{
return NS_ERROR_FAILURE;
}
*retval = OBJECT_TO_JSVAL(obj);
}
}
--- a/js/src/xpconnect/src/xpccomponents.cpp
+++ b/js/src/xpconnect/src/xpccomponents.cpp
@@ -3112,17 +3112,17 @@ static JSBool
sandbox_setProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
if (!JSVAL_IS_OBJECT(*vp)) {
return JS_TRUE;
}
JSObject *pobj = JSVAL_TO_OBJECT(*vp);
if (pobj) {
- if (pobj->getJSClass() == &XPCCrossOriginWrapper::XOWClass.base &&
+ if (pobj->getClass() == &XPCCrossOriginWrapper::XOWClass &&
!XPCWrapper::RewrapObject(cx, obj, pobj,
XPCWrapper::XPCNW_EXPLICIT, vp)) {
return JS_FALSE;
}
}
return JS_SetPrototype(cx, obj, JSVAL_TO_OBJECT(*vp));
}
@@ -3820,23 +3820,19 @@ nsXPCComponents_Utils::GetGlobalForObjec
// first argument must be an object
if(JSVAL_IS_PRIMITIVE(argv[0]))
return NS_ERROR_XPC_BAD_CONVERT_JS;
JSObject *obj = JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(argv[0]));
*rval = OBJECT_TO_JSVAL(obj);
- // Outerize if necessary. Embrace the ugliness!
- JSClass *clasp = JS_GetClass(cx, obj);
- if (clasp->flags & JSCLASS_IS_EXTENDED) {
- JSExtendedClass *xclasp = reinterpret_cast<JSExtendedClass *>(clasp);
- if (JSObjectOp outerize = xclasp->outerObject)
+ // Outerize if necessary.
+ if (JSObjectOp outerize = obj->getClass()->ext.outerObject)
*rval = OBJECT_TO_JSVAL(outerize(cx, obj));
- }
cc->SetReturnValueWasSet(PR_TRUE);
return NS_OK;
}
#ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
/* string canCreateWrapper (in nsIIDPtr iid); */
NS_IMETHODIMP
--- a/js/src/xpconnect/src/xpcconvert.cpp
+++ b/js/src/xpconnect/src/xpcconvert.cpp
@@ -596,17 +596,16 @@ XPCConvert::JSData2Native(XPCCallContext
{
return JS_FALSE;
}
#ifdef DEBUG
const jschar* chars=nsnull;
if(nsnull!=(chars = JS_GetStringCharsZ(cx, str)))
{
NS_ASSERTION((! ILLEGAL_RANGE(chars[0])),"U+0080/U+0100 - U+FFFF data lost");
- return JS_FALSE;
}
#endif // DEBUG
*((char*)d) = bytes[0];
break;
}
case nsXPTType::T_WCHAR :
{
const jschar* chars=nsnull;
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -1262,60 +1262,102 @@ private:
* Core classes for wrapped native objects for use from JavaScript...
*
****************************************************************************
***************************************************************************/
// These are the various JSClasses and callbacks whose use that required
// visibility from more than one .cpp file.
-extern JSExtendedClass XPC_WN_NoHelper_JSClass;
-extern JSClass XPC_WN_NoMods_WithCall_Proto_JSClass;
-extern JSClass XPC_WN_NoMods_NoCall_Proto_JSClass;
-extern JSClass XPC_WN_ModsAllowed_WithCall_Proto_JSClass;
-extern JSClass XPC_WN_ModsAllowed_NoCall_Proto_JSClass;
-extern JSClass XPC_WN_Tearoff_JSClass;
-extern JSClass XPC_WN_NoHelper_Proto_JSClass;
+extern js::Class XPC_WN_NoHelper_JSClass;
+extern js::Class XPC_WN_NoMods_WithCall_Proto_JSClass;
+extern js::Class XPC_WN_NoMods_NoCall_Proto_JSClass;
+extern js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass;
+extern js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass;
+extern js::Class XPC_WN_Tearoff_JSClass;
+extern js::Class XPC_WN_NoHelper_Proto_JSClass;
extern JSBool
XPC_WN_Equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
-extern JSObjectOps *
-XPC_WN_Proto_GetObjectOps(JSContext *cx, JSClass *clazz);
-
extern JSBool
XPC_WN_CallMethod(JSContext *cx, JSObject *obj,
uintN argc, jsval *argv, jsval *vp);
extern JSBool
XPC_WN_GetterSetter(JSContext *cx, JSObject *obj,
uintN argc, jsval *argv, jsval *vp);
extern JSBool
-xpc_InitWrappedNativeJSOps();
+XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp);
+
+extern JSType
+XPC_WN_JSOp_TypeOf_Object(JSContext *cx, JSObject *obj);
+
+extern JSType
+XPC_WN_JSOp_TypeOf_Function(JSContext *cx, JSObject *obj);
+
+extern void
+XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj);
+
+extern JSObject*
+XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj);
+
+// Macros to initialize Object or Function like XPC_WN classes
+#define XPC_WN_WithCall_ObjectOps \
+ { \
+ nsnull, /* lookupProperty */ \
+ nsnull, /* defineProperty */ \
+ nsnull, /* getProperty */ \
+ nsnull, /* setProperty */ \
+ nsnull, /* getAttributes */ \
+ nsnull, /* setAttributes */ \
+ nsnull, /* deleteProperty */ \
+ js::Valueify(XPC_WN_JSOp_Enumerate), \
+ XPC_WN_JSOp_TypeOf_Function, \
+ nsnull, /* trace */ \
+ XPC_WN_JSOp_ThisObject, \
+ XPC_WN_JSOp_Clear \
+ }
+
+#define XPC_WN_NoCall_ObjectOps \
+ { \
+ nsnull, /* lookupProperty */ \
+ nsnull, /* defineProperty */ \
+ nsnull, /* getProperty */ \
+ nsnull, /* setProperty */ \
+ nsnull, /* getAttributes */ \
+ nsnull, /* setAttributes */ \
+ nsnull, /* deleteProperty */ \
+ js::Valueify(XPC_WN_JSOp_Enumerate), \
+ XPC_WN_JSOp_TypeOf_Object, \
+ nsnull, /* trace */ \
+ XPC_WN_JSOp_ThisObject, \
+ XPC_WN_JSOp_Clear \
+ }
// Maybe this macro should check for class->enumerate ==
// XPC_WN_Shared_Proto_Enumerate or something rather than checking for
// 4 classes?
#define IS_PROTO_CLASS(clazz) \
- ((clazz) == &XPC_WN_NoMods_WithCall_Proto_JSClass || \
- (clazz) == &XPC_WN_NoMods_NoCall_Proto_JSClass || \
- (clazz) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || \
- (clazz) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass)
+ ((clazz) == &XPC_WN_NoMods_WithCall_Proto_JSClass || \
+ (clazz) == &XPC_WN_NoMods_NoCall_Proto_JSClass || \
+ (clazz) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || \
+ (clazz) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass)
// NOTE!!!
//
// If this ever changes,
// nsScriptSecurityManager::doGetObjectPrincipal() *must* be updated
// also!
//
// NOTE!!!
#define IS_WRAPPER_CLASS(clazz) \
- (((clazz)->flags & JSCLASS_IS_EXTENDED) && \
- reinterpret_cast<JSExtendedClass*>(clazz)->equality == XPC_WN_Equality)
+ (clazz->ext.equality == js::Valueify(XPC_WN_Equality))
inline JSBool
DebugCheckWrapperClass(JSObject* obj)
{
NS_ASSERTION(IS_WRAPPER_CLASS(obj->getClass()),
"Forgot to check if this is a wrapper?");
return JS_TRUE;
}
@@ -1910,28 +1952,30 @@ public:
// XPCNativeScriptableShared is used to hold the JSClass and the
// associated scriptable flags for XPCWrappedNatives. These are shared across
// the runtime and are garbage collected by xpconnect. We *used* to just store
// this inside the XPCNativeScriptableInfo (usually owned by instances of
// XPCWrappedNativeProto. This had two problems... It was wasteful, and it
// was a big problem when wrappers are reparented to different scopes (and
// thus different protos (the DOM does this).
-struct XPCNativeScriptableSharedJSClass : public JSExtendedClass
+struct XPCNativeScriptableSharedJSClass
{
+ js::Class base;
PRUint32 interfacesBitmap;
};
class XPCNativeScriptableShared
{
public:
const XPCNativeScriptableFlags& GetFlags() const {return mFlags;}
PRUint32 GetInterfacesBitmap() const
{return mJSClass.interfacesBitmap;}
- JSClass* GetJSClass() {return &mJSClass.base;}
+ JSClass* GetJSClass()
+ {return js::Jsvalify(&mJSClass.base);}
JSClass* GetSlimJSClass()
{if(mCanBeSlim) return GetJSClass(); return nsnull;}
XPCNativeScriptableShared(JSUint32 aFlags, char* aName,
PRUint32 interfacesBitmap)
: mFlags(aFlags),
mCanBeSlim(JS_FALSE)
{memset(&mJSClass, 0, sizeof(mJSClass));
--- a/js/src/xpconnect/src/xpcquickstubs.cpp
+++ b/js/src/xpconnect/src/xpcquickstubs.cpp
@@ -291,17 +291,17 @@ LookupGetterOrSetter(JSContext *cx, JSBo
// ensuring that we have an XPConnect prototype object ensures that
// we are only going to expose quickstubbed properties to script.
// Also be careful not to overwrite existing properties!
const char *name = JSVAL_IS_STRING(idval)
? JS_GetStringBytes(JSVAL_TO_STRING(idval))
: nsnull;
if(!name ||
- !IS_PROTO_CLASS(desc.obj->getJSClass()) ||
+ !IS_PROTO_CLASS(desc.obj->getClass()) ||
(desc.attrs & (JSPROP_GETTER | JSPROP_SETTER)) ||
!(desc.getter || desc.setter) ||
desc.setter == desc.obj->getJSClass()->setProperty)
{
JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
@@ -358,17 +358,17 @@ DefineGetterOrSetter(JSContext *cx, uint
&found, &getter, &setter)))
return JS_FALSE;
// The property didn't exist, already has a getter or setter, or is not
// our property, then just forward now.
if(!obj2 ||
(attrs & (JSPROP_GETTER | JSPROP_SETTER)) ||
!(getter || setter) ||
- !IS_PROTO_CLASS(obj2->getJSClass()))
+ !IS_PROTO_CLASS(obj2->getClass()))
return forward(cx, argc, vp);
// Reify the getter and setter...
if(!ReifyPropertyOps(cx, obj, id, interned_id, name, getter, setter,
nsnull, nsnull))
return JS_FALSE;
return forward(cx, argc, vp);
@@ -499,18 +499,18 @@ GetMemberInfo(JSObject *obj,
{
// Get the interface name. From DefinePropertyIfFound (in
// xpcwrappednativejsops.cpp) and XPCThrower::Verbosify.
//
// We could instead make the quick stub could pass in its interface name,
// but this code often produces a more specific error message, e.g.
*ifaceName = "Unknown";
- NS_ASSERTION(IS_WRAPPER_CLASS(obj->getJSClass()) ||
- obj->getJSClass() == &XPC_WN_Tearoff_JSClass,
+ NS_ASSERTION(IS_WRAPPER_CLASS(obj->getClass()) ||
+ obj->getClass() == &XPC_WN_Tearoff_JSClass,
"obj must be a wrapper");
XPCWrappedNativeProto *proto;
if(IS_SLIM_WRAPPER(obj))
{
proto = GetSlimWrapperProto(obj);
}
else
{
--- a/js/src/xpconnect/src/xpcwrappednative.cpp
+++ b/js/src/xpconnect/src/xpcwrappednative.cpp
@@ -1119,17 +1119,19 @@ XPCWrappedNative::Init(XPCCallContext& c
if(HasProto() && !HasSharedProto())
GetProto()->SetScriptableInfo(mScriptableInfo);
}
}
XPCNativeScriptableInfo* si = mScriptableInfo;
// create our flatJSObject
- JSClass* jsclazz = si ? si->GetJSClass() : &XPC_WN_NoHelper_JSClass.base;
+ js::Class* jsclazz = si
+ ? js::Valueify(si->GetJSClass())
+ : &XPC_WN_NoHelper_JSClass;
if(isGlobal)
{
// Resolving a global object's class can cause us to create a global's
// JS class without the proper global flags. Notice that here and fix
// the problem.
if(!(jsclazz->flags & JSCLASS_IS_GLOBAL))
jsclazz->flags |= JSCLASS_GLOBAL_FLAGS;
@@ -1153,18 +1155,18 @@ XPCWrappedNative::Init(XPCCallContext& c
JSObject* protoJSObject = HasProto() ?
GetProto()->GetJSProtoObject() :
GetScope()->GetPrototypeNoHelper(ccx);
if (!protoJSObject) {
return JS_FALSE;
}
- mFlatJSObject = xpc_NewSystemInheritingJSObject(ccx, jsclazz, protoJSObject,
- parent);
+ mFlatJSObject = xpc_NewSystemInheritingJSObject(ccx, js::Jsvalify(jsclazz),
+ protoJSObject, parent);
if(!mFlatJSObject)
return JS_FALSE;
return FinishInit(ccx);
}
JSBool
XPCWrappedNative::Init(XPCCallContext &ccx, JSObject *existingJSObject)
@@ -1678,17 +1680,17 @@ XPCWrappedNative::GetWrappedNativeOfJSOb
// If we were passed a function object then we need to find the correct
// wrapper out of those that might be in the callee obj's proto chain.
if(funobj)
{
JSObject* funObjParent = funobj->getParent();
NS_ASSERTION(funObjParent, "funobj has no parent");
- JSClass* funObjParentClass = funObjParent->getJSClass();
+ js::Class* funObjParentClass = funObjParent->getClass();
if(IS_PROTO_CLASS(funObjParentClass))
{
NS_ASSERTION(funObjParent->getParent(), "funobj's parent (proto) is global");
proto = (XPCWrappedNativeProto*) xpc_GetJSPrivate(funObjParent);
if(proto)
protoClassInfo = proto->GetClassInfo();
}
@@ -1708,18 +1710,18 @@ XPCWrappedNative::GetWrappedNativeOfJSOb
NS_ERROR("function object has parent of unknown class!");
return nsnull;
}
}
for(cur = obj; cur; cur = cur->getProto())
{
// this is on two lines to make the compiler happy given the goto.
- JSClass* clazz;
- clazz = cur->getJSClass();
+ js::Class* clazz;
+ clazz = cur->getClass();
if(IS_WRAPPER_CLASS(clazz))
{
return_wrapper:
JSBool isWN = IS_WN_WRAPPER_OBJECT(cur);
XPCWrappedNative* wrapper =
isWN ? (XPCWrappedNative*) xpc_GetJSPrivate(cur) : nsnull;
if(proto)
@@ -1766,22 +1768,19 @@ return_tearoff:
if((unsafeObj = XPCWrapper::Unwrap(cx, cur)))
return GetWrappedNativeOfJSObject(cx, unsafeObj, funobj, pobj2,
pTearOff);
}
// If we didn't find a wrapper using the given funobj and obj, try
// again with obj's outer object, if it's got one.
- JSClass *clazz = obj->getJSClass();
-
- if((clazz->flags & JSCLASS_IS_EXTENDED) &&
- ((JSExtendedClass*)clazz)->outerObject)
+ if(JSObjectOp op = obj->getClass()->ext.outerObject)
{
- JSObject *outer = ((JSExtendedClass*)clazz)->outerObject(cx, obj);
+ JSObject *outer = op(cx, obj);
if(outer && outer != obj)
return GetWrappedNativeOfJSObject(cx, outer, funobj, pobj2,
pTearOff);
}
if(pobj2)
*pobj2 = nsnull;
return nsnull;
@@ -2113,17 +2112,17 @@ XPCWrappedNative::InitTearOff(XPCCallCon
JSBool
XPCWrappedNative::InitTearOffJSObject(XPCCallContext& ccx,
XPCWrappedNativeTearOff* to)
{
// This is only called while locked (during XPCWrappedNative::FindTearOff).
JSObject* obj =
- xpc_NewSystemInheritingJSObject(ccx, &XPC_WN_Tearoff_JSClass,
+ xpc_NewSystemInheritingJSObject(ccx, js::Jsvalify(&XPC_WN_Tearoff_JSClass),
GetScope()->GetPrototypeJSObject(),
mFlatJSObject);
if(!obj || !JS_SetPrivate(ccx, obj, to))
return JS_FALSE;
to->SetJSObject(obj);
return JS_TRUE;
--- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp
@@ -808,17 +808,17 @@ XPC_WN_Equality(JSContext *cx, JSObject
XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
if(si && si->GetFlags().WantEquality())
{
nsresult rv = si->GetCallback()->Equality(wrapper, cx, obj, v, bp);
if(NS_FAILED(rv))
return Throw(rv, cx);
if(!*bp && !JSVAL_IS_PRIMITIVE(v) &&
- JSVAL_TO_OBJECT(v)->getJSClass() == &XPCSafeJSObjectWrapper::SJOWClass.base)
+ JSVAL_TO_OBJECT(v)->getClass() == &XPCSafeJSObjectWrapper::SJOWClass)
{
v = OBJECT_TO_JSVAL(XPCSafeJSObjectWrapper::GetUnsafeObject(cx, JSVAL_TO_OBJECT(v)));
rv = si->GetCallback()->Equality(wrapper, cx, obj, v, bp);
if(NS_FAILED(rv))
return Throw(rv, cx);
}
}
@@ -907,51 +907,66 @@ XPC_WN_InnerObject(JSContext *cx, JSObje
}
obj = newThis;
}
return obj;
}
-JSObjectOps *XPC_WN_GetObjectOpsNoCall(JSContext *cx, JSClass *clazz);
-
-JSExtendedClass XPC_WN_NoHelper_JSClass = {
- {
- "XPCWrappedNative_NoHelper", // name;
- WRAPPER_SLOTS |
- JSCLASS_PRIVATE_IS_NSISUPPORTS |
- JSCLASS_MARK_IS_TRACE |
- JSCLASS_IS_EXTENDED, // flags;
-
- /* Mandatory non-null function pointer members. */
- XPC_WN_OnlyIWrite_PropertyStub, // addProperty;
- XPC_WN_CannotModifyPropertyStub,// delProperty;
- JS_PropertyStub, // getProperty;
- XPC_WN_OnlyIWrite_PropertyStub, // setProperty;
+js::Class XPC_WN_NoHelper_JSClass = {
+ "XPCWrappedNative_NoHelper", // name;
+ WRAPPER_SLOTS |
+ JSCLASS_PRIVATE_IS_NSISUPPORTS |
+ JSCLASS_MARK_IS_TRACE, // flags;
- XPC_WN_Shared_Enumerate, // enumerate;
- XPC_WN_NoHelper_Resolve, // resolve;
- XPC_WN_Shared_Convert, // convert;
- XPC_WN_NoHelper_Finalize, // finalize;
+ /* Mandatory non-null function pointer members. */
+ js::Valueify(XPC_WN_OnlyIWrite_PropertyStub), // addProperty
+ js::Valueify(XPC_WN_CannotModifyPropertyStub),// delProperty
+ js::PropertyStub, // getProperty
+ js::Valueify(XPC_WN_OnlyIWrite_PropertyStub), // setProperty
+
+ XPC_WN_Shared_Enumerate, // enumerate
+ XPC_WN_NoHelper_Resolve, // resolve
+ js::Valueify(XPC_WN_Shared_Convert), // convert
+ XPC_WN_NoHelper_Finalize, // finalize
+
+ /* Optionally non-null members start here. */
+ nsnull, // reserved0
+ nsnull, // checkAccess
+ nsnull, // call
+ nsnull, // construct
+ nsnull, // xdrObject;
+ nsnull, // hasInstance
+ JS_CLASS_TRACE(XPC_WN_Shared_Trace), // mark/trace
- /* Optionally non-null members start here. */
- XPC_WN_GetObjectOpsNoCall, // getObjectOps;
- nsnull, // checkAccess;
- nsnull, // call;
- nsnull, // construct;
- nsnull, // xdrObject;
- nsnull, // hasInstance;
- JS_CLASS_TRACE(XPC_WN_Shared_Trace), // mark/trace;
- nsnull // spare;
+ // ClassExtension
+ {
+ js::Valueify(XPC_WN_Equality),
+ XPC_WN_OuterObject,
+ XPC_WN_InnerObject,
+ nsnull, // iteratorObject
+ nsnull, // wrappedObject
},
- XPC_WN_Equality,
- XPC_WN_OuterObject,
- XPC_WN_InnerObject,
- nsnull,nsnull,nsnull,nsnull,nsnull
+
+ // ObjectOps
+ {
+ nsnull, // lookupProperty
+ nsnull, // defineProperty
+ nsnull, // getProperty
+ nsnull, // setProperty
+ nsnull, // getAttributes
+ nsnull, // setAttributes
+ nsnull, // deleteProperty
+ js::Valueify(XPC_WN_JSOp_Enumerate),
+ XPC_WN_JSOp_TypeOf_Object,
+ nsnull, // trace
+ XPC_WN_JSOp_ThisObject,
+ XPC_WN_JSOp_Clear
+ }
};
/***************************************************************************/
static JSBool
XPC_WN_MaybeResolvingPropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
@@ -1233,21 +1248,16 @@ XPC_WN_Helper_NewResolve(JSContext *cx,
}
}
return retval;
}
/***************************************************************************/
-extern JS_IMPORT_DATA(JSObjectOps) js_ObjectOps;
-
-static JSObjectOps XPC_WN_WithCall_JSOps;
-static JSObjectOps XPC_WN_NoCall_JSOps;
-
/*
Here are the enumerator cases:
set jsclass enumerate to stub (unless noted otherwise)
if( helper wants new enumerate )
if( DONT_ENUM_STATICS )
forward to scriptable enumerate
@@ -1273,28 +1283,28 @@ static JSObjectOps XPC_WN_NoCall_JSOps;
else //... if( helper wants NO enumerate )
if( DONT_ENUM_STATICS )
use enumerate stub - don't use this JSOp thing at all
else
do shared enumerate - don't use this JSOp thing at all
*/
-static JSBool
+JSBool
XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
jsval *statep, jsid *idp)
{
- JSClass *clazz = obj->getJSClass();
- if(!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base)
+ js::Class *clazz = obj->getClass();
+ if(!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass)
{
// obj must be a prototype object or a wrapper w/o a
- // helper. Short circuit this call to
- // js_ObjectOps.enumerate().
+ // helper. Short circuit this call to the default
+ // implementation.
- return js_ObjectOps.enumerate(cx, obj, enum_op, js::Valueify(statep), idp);
+ return js_Enumerate(cx, obj, enum_op, js::Valueify(statep), idp);
}
MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@@ -1351,38 +1361,38 @@ XPC_WN_JSOp_Enumerate(JSContext *cx, JSO
if(NS_FAILED(rv) || !retval)
*statep = JSVAL_NULL;
if(NS_FAILED(rv))
return Throw(rv, cx);
if(!retval)
return JS_FALSE;
- // Then fall through and call js_ObjectOps.enumerate...
+ // Then fall through and call the default implementation...
}
}
// else call js_ObjectOps.enumerate...
- return js_ObjectOps.enumerate(cx, obj, enum_op, js::Valueify(statep), idp);
+ return js_Enumerate(cx, obj, enum_op, js::Valueify(statep), idp);
}
-static JSType
+JSType
XPC_WN_JSOp_TypeOf_Object(JSContext *cx, JSObject *obj)
{
return JSTYPE_OBJECT;
}
-static JSType
+JSType
XPC_WN_JSOp_TypeOf_Function(JSContext *cx, JSObject *obj)
{
return JSTYPE_FUNCTION;
}
-static void
+void
XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj)
{
// We're likely to enter this JSOp with a wrapper prototype
// object. In that case we won't find a wrapper, so we'll just
// call into js_ObjectOps.clear(), which is exactly what we want.
// If our scope is cleared, make sure we clear the scope of our
// native wrapper as well.
@@ -1391,18 +1401,16 @@ XPC_WN_JSOp_Clear(JSContext *cx, JSObjec
if(wrapper && wrapper->IsValid())
{
XPCNativeWrapper::ClearWrappedNativeScopes(cx, wrapper);
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
xpc->UpdateXOWs(cx, wrapper, nsIXPConnect::XPC_XOW_CLEARSCOPE);
}
-
- js_ObjectOps.clear(cx, obj);
}
namespace {
NS_STACK_CLASS class AutoPopJSContext
{
public:
AutoPopJSContext(XPCJSContextStack *stack)
@@ -1431,17 +1439,17 @@ public:
private:
JSContext *mCx;
XPCJSContextStack *mStack;
};
} // namespace
-static JSObject*
+JSObject*
XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj)
{
// None of the wrappers we could potentially hand out are threadsafe so
// just hand out the given object.
if(!XPCPerThreadData::IsMainThread(cx))
return obj;
OBJ_TO_OUTER_OBJECT(cx, obj);
@@ -1528,47 +1536,16 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS
XPCThrower::Throw(rv, cx);
return nsnull;
}
}
return JSVAL_TO_OBJECT(retval.jsval_value());
}
-JSObjectOps *
-XPC_WN_GetObjectOpsNoCall(JSContext *cx, JSClass *clazz)
-{
- return &XPC_WN_NoCall_JSOps;
-}
-
-JSObjectOps *
-XPC_WN_GetObjectOpsWithCall(JSContext *cx, JSClass *clazz)
-{
- return &XPC_WN_WithCall_JSOps;
-}
-
-JSBool xpc_InitWrappedNativeJSOps()
-{
- if(!XPC_WN_NoCall_JSOps.lookupProperty)
- {
- memcpy(&XPC_WN_NoCall_JSOps, &js_ObjectOps, sizeof(JSObjectOps));
- XPC_WN_NoCall_JSOps.enumerate = js::Valueify(XPC_WN_JSOp_Enumerate);
- XPC_WN_NoCall_JSOps.typeOf = XPC_WN_JSOp_TypeOf_Object;
- XPC_WN_NoCall_JSOps.clear = XPC_WN_JSOp_Clear;
- XPC_WN_NoCall_JSOps.thisObject = XPC_WN_JSOp_ThisObject;
-
- memcpy(&XPC_WN_WithCall_JSOps, &js_ObjectOps, sizeof(JSObjectOps));
- XPC_WN_WithCall_JSOps.enumerate = js::Valueify(XPC_WN_JSOp_Enumerate);
- XPC_WN_WithCall_JSOps.typeOf = XPC_WN_JSOp_TypeOf_Function;
- XPC_WN_WithCall_JSOps.clear = XPC_WN_JSOp_Clear;
- XPC_WN_WithCall_JSOps.thisObject = XPC_WN_JSOp_ThisObject;
- }
- return JS_TRUE;
-}
-
/***************************************************************************/
// static
XPCNativeScriptableInfo*
XPCNativeScriptableInfo::Construct(XPCCallContext& ccx,
JSBool isGlobal,
const XPCNativeScriptableCreateInfo* sci)
{
@@ -1609,117 +1586,122 @@ XPCNativeScriptableInfo::Construct(XPCCa
void
XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal)
{
NS_ASSERTION(mJSClass.base.name, "bad state!");
mJSClass.base.flags = WRAPPER_SLOTS |
JSCLASS_PRIVATE_IS_NSISUPPORTS |
JSCLASS_NEW_RESOLVE |
- JSCLASS_MARK_IS_TRACE |
- JSCLASS_IS_EXTENDED;
+ JSCLASS_MARK_IS_TRACE;
if(isGlobal)
mJSClass.base.flags |= JSCLASS_GLOBAL_FLAGS;
+ JSPropertyOp addProperty;
if(mFlags.WantAddProperty())
- mJSClass.base.addProperty = XPC_WN_Helper_AddProperty;
+ addProperty = XPC_WN_Helper_AddProperty;
else if(mFlags.UseJSStubForAddProperty())
- mJSClass.base.addProperty = JS_PropertyStub;
+ addProperty = JS_PropertyStub;
else if(mFlags.AllowPropModsDuringResolve())
- mJSClass.base.addProperty = XPC_WN_MaybeResolvingPropertyStub;
+ addProperty = XPC_WN_MaybeResolvingPropertyStub;
else
- mJSClass.base.addProperty = XPC_WN_CannotModifyPropertyStub;
+ addProperty = XPC_WN_CannotModifyPropertyStub;
+ mJSClass.base.addProperty = js::Valueify(addProperty);
+ JSPropertyOp delProperty;
if(mFlags.WantDelProperty())
- mJSClass.base.delProperty = XPC_WN_Helper_DelProperty;
+ delProperty = XPC_WN_Helper_DelProperty;
else if(mFlags.UseJSStubForDelProperty())
- mJSClass.base.delProperty = JS_PropertyStub;
+ delProperty = JS_PropertyStub;
else if(mFlags.AllowPropModsDuringResolve())
- mJSClass.base.delProperty = XPC_WN_MaybeResolvingPropertyStub;
+ delProperty = XPC_WN_MaybeResolvingPropertyStub;
else
- mJSClass.base.delProperty = XPC_WN_CannotModifyPropertyStub;
+ delProperty = XPC_WN_CannotModifyPropertyStub;
+ mJSClass.base.delProperty = js::Valueify(delProperty);
if(mFlags.WantGetProperty())
- mJSClass.base.getProperty = XPC_WN_Helper_GetProperty;
+ mJSClass.base.getProperty = js::Valueify(XPC_WN_Helper_GetProperty);
else
- mJSClass.base.getProperty = JS_PropertyStub;
+ mJSClass.base.getProperty = js::PropertyStub;
+ JSPropertyOp setProperty;
if(mFlags.WantSetProperty())
- mJSClass.base.setProperty = XPC_WN_Helper_SetProperty;
+ setProperty = XPC_WN_Helper_SetProperty;
else if(mFlags.UseJSStubForSetProperty())
- mJSClass.base.setProperty = JS_PropertyStub;
+ setProperty = JS_PropertyStub;
else if(mFlags.AllowPropModsDuringResolve())
- mJSClass.base.setProperty = XPC_WN_MaybeResolvingPropertyStub;
+ setProperty = XPC_WN_MaybeResolvingPropertyStub;
else
- mJSClass.base.setProperty = XPC_WN_CannotModifyPropertyStub;
+ setProperty = XPC_WN_CannotModifyPropertyStub;
+ mJSClass.base.setProperty = js::Valueify(setProperty);
// We figure out most of the enumerate strategy at call time.
if(mFlags.WantNewEnumerate() || mFlags.WantEnumerate() ||
mFlags.DontEnumStaticProps())
- mJSClass.base.enumerate = JS_EnumerateStub;
+ mJSClass.base.enumerate = js::EnumerateStub;
else
mJSClass.base.enumerate = XPC_WN_Shared_Enumerate;
// We have to figure out resolve strategy at call time
mJSClass.base.resolve = (JSResolveOp) XPC_WN_Helper_NewResolve;
if(mFlags.WantConvert())
- mJSClass.base.convert = XPC_WN_Helper_Convert;
+ mJSClass.base.convert = js::Valueify(XPC_WN_Helper_Convert);
else
- mJSClass.base.convert = XPC_WN_Shared_Convert;
+ mJSClass.base.convert = js::Valueify(XPC_WN_Shared_Convert);
if(mFlags.WantFinalize())
mJSClass.base.finalize = XPC_WN_Helper_Finalize;
else
mJSClass.base.finalize = XPC_WN_NoHelper_Finalize;
// We let the rest default to nsnull unless the helper wants them...
if(mFlags.WantCheckAccess())
- mJSClass.base.checkAccess = XPC_WN_Helper_CheckAccess;
+ mJSClass.base.checkAccess = js::Valueify(XPC_WN_Helper_CheckAccess);
- // Note that we *must* set
- // mJSClass.base.getObjectOps = XPC_WN_GetObjectOpsNoCall
- // or
- // mJSClass.base.getObjectOps = XPC_WN_GetObjectOpsWithCall
- // (even for the cases were it does not do much) because with these
- // dynamically generated JSClasses, the code in
- // XPCWrappedNative::GetWrappedNativeOfJSObject() needs to look for
- // that this callback pointer in order to identify that a given
+ // Note that we *must* set the ObjectOps (even for the cases were it does
+ // not do much) because with these dynamically generated JSClasses, the
+ // code in XPCWrappedNative::GetWrappedNativeOfJSObject() needs to look
+ // for that these callback pointers in order to identify that a given
// JSObject represents a wrapper.
+ js::ObjectOps *ops = &mJSClass.base.ops;
+ ops->enumerate = js::Valueify(XPC_WN_JSOp_Enumerate);
+ ops->clear = XPC_WN_JSOp_Clear;
+ ops->thisObject = XPC_WN_JSOp_ThisObject;
if(mFlags.WantCall() || mFlags.WantConstruct())
{
- mJSClass.base.getObjectOps = XPC_WN_GetObjectOpsWithCall;
+ ops->typeOf = XPC_WN_JSOp_TypeOf_Function;
if(mFlags.WantCall())
- mJSClass.base.call = XPC_WN_Helper_Call;
+ mJSClass.base.call = js::Valueify(XPC_WN_Helper_Call);
if(mFlags.WantConstruct())
- mJSClass.base.construct = XPC_WN_Helper_Construct;
+ mJSClass.base.construct = js::Valueify(XPC_WN_Helper_Construct);
}
else
{
- mJSClass.base.getObjectOps = XPC_WN_GetObjectOpsNoCall;
+ ops->typeOf = XPC_WN_JSOp_TypeOf_Object;
}
+ // Equality is a required hook.
+ mJSClass.base.ext.equality = js::Valueify(XPC_WN_Equality);
+
if(mFlags.WantHasInstance())
- mJSClass.base.hasInstance = XPC_WN_Helper_HasInstance;
+ mJSClass.base.hasInstance = js::Valueify(XPC_WN_Helper_HasInstance);
if(mFlags.WantTrace())
mJSClass.base.mark = JS_CLASS_TRACE(XPC_WN_Helper_Trace);
else
mJSClass.base.mark = JS_CLASS_TRACE(XPC_WN_Shared_Trace);
- // Equality is a required hook.
- mJSClass.equality = XPC_WN_Equality;
-
if(mFlags.WantOuterObject())
- mJSClass.outerObject = XPC_WN_OuterObject;
+ mJSClass.base.ext.outerObject = XPC_WN_OuterObject;
if(mFlags.WantInnerObject())
- mJSClass.innerObject = XPC_WN_InnerObject;
+ mJSClass.base.ext.innerObject = XPC_WN_InnerObject;
if(!(mFlags & (nsIXPCScriptable::WANT_OUTER_OBJECT |
nsIXPCScriptable::WANT_INNER_OBJECT)))
mCanBeSlim = JS_TRUE;
}
/***************************************************************************/
/***************************************************************************/
@@ -1801,22 +1783,20 @@ XPC_WN_GetterSetter(JSContext *cx, JSObj
}
/***************************************************************************/
static JSBool
XPC_WN_Shared_Proto_Enumerate(JSContext *cx, JSObject *obj)
{
NS_ASSERTION(
- JS_InstanceOf(cx, obj, &XPC_WN_ModsAllowed_WithCall_Proto_JSClass,
- nsnull) ||
- JS_InstanceOf(cx, obj, &XPC_WN_ModsAllowed_NoCall_Proto_JSClass,
- nsnull) ||
- JS_InstanceOf(cx, obj, &XPC_WN_NoMods_WithCall_Proto_JSClass, nsnull) ||
- JS_InstanceOf(cx, obj, &XPC_WN_NoMods_NoCall_Proto_JSClass, nsnull),
+ obj->getClass() == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||
+ obj->getClass() == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass ||
+ obj->getClass() == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
+ obj->getClass() == &XPC_WN_NoMods_NoCall_Proto_JSClass,
"bad proto");
XPCWrappedNativeProto* self =
(XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
if(!self)
return JS_FALSE;
if(self->GetScriptableInfo() &&
self->GetScriptableInfo()->GetFlags().DontEnumStaticProps())
@@ -1874,21 +1854,19 @@ XPC_WN_Shared_Proto_Trace(JSTracer *trc,
}
/*****************************************************/
static JSBool
XPC_WN_ModsAllowed_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id)
{
NS_ASSERTION(
- JS_InstanceOf(cx, obj, &XPC_WN_ModsAllowed_WithCall_Proto_JSClass,
- nsnull) ||
- JS_InstanceOf(cx, obj, &XPC_WN_ModsAllowed_NoCall_Proto_JSClass,
- nsnull),
- "bad proto");
+ obj->getClass() == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||
+ obj->getClass() == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass,
+ "bad proto");
XPCWrappedNativeProto* self =
(XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
if(!self)
return JS_FALSE;
XPCCallContext ccx(JS_CALLER, cx);
if(!ccx.IsValid())
@@ -1900,103 +1878,77 @@ XPC_WN_ModsAllowed_Proto_Resolve(JSConte
return DefinePropertyIfFound(ccx, obj, id,
self->GetSet(), nsnull, nsnull,
self->GetScope(),
JS_TRUE, nsnull, nsnull, si,
enumFlag, nsnull);
}
-// Give our proto classes object ops that match the respective
-// wrappers so that the JS engine can share scope (maps) among
-// wrappers. This essentially duplicates the number of JSClasses we
-// use for prototype objects (from 2 to 4), but the scope sharing
-// benefit is well worth it.
-JSObjectOps *
-XPC_WN_Proto_GetObjectOps(JSContext *cx, JSClass *clazz)
-{
- // Protos for wrappers that want calls to their call() hooks get
- // jsops with a call hook, others get jsops w/o a call hook.
-
- if(clazz == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||
- clazz == &XPC_WN_NoMods_WithCall_Proto_JSClass)
- return &XPC_WN_WithCall_JSOps;
-
- NS_ASSERTION(clazz == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass ||
- clazz == &XPC_WN_NoMods_NoCall_Proto_JSClass ||
- clazz == &XPC_WN_NoHelper_Proto_JSClass,
- "bad proto");
-
- return &XPC_WN_NoCall_JSOps;
-}
-
-JSClass XPC_WN_ModsAllowed_WithCall_Proto_JSClass = {
+js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass = {
"XPC_WN_ModsAllowed_WithCall_Proto_JSClass", // name;
WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags;
/* Mandatory non-null function pointer members. */
- JS_PropertyStub, // addProperty;
- JS_PropertyStub, // delProperty;
- JS_PropertyStub, // getProperty;
- JS_PropertyStub, // setProperty;
- XPC_WN_Shared_Proto_Enumerate, // enumerate;
- XPC_WN_ModsAllowed_Proto_Resolve, // resolve;
- XPC_WN_Shared_Proto_Convert, // convert;
- XPC_WN_Shared_Proto_Finalize, // finalize;
+ js::PropertyStub, // addProperty;
+ js::PropertyStub, // delProperty;
+ js::PropertyStub, // getProperty;
+ js::PropertyStub, // setProperty;
+ XPC_WN_Shared_Proto_Enumerate, // enumerate;
+ XPC_WN_ModsAllowed_Proto_Resolve, // resolve;
+ js::Valueify(XPC_WN_Shared_Proto_Convert), // convert;
+ XPC_WN_Shared_Proto_Finalize, // finalize;
/* Optionally non-null members start here. */
- XPC_WN_Proto_GetObjectOps, // getObjectOps;
+ nsnull, // reserved0;
nsnull, // checkAccess;
nsnull, // call;
nsnull, // construct;
nsnull, // xdrObject;
nsnull, // hasInstance;
JS_CLASS_TRACE(XPC_WN_Shared_Proto_Trace), // mark/trace;
- nsnull // spare;
+
+ JS_NULL_CLASS_EXT,
+ XPC_WN_WithCall_ObjectOps
};
-JSObjectOps *
-XPC_WN_ModsAllowedProto_NoCall_GetObjectOps(JSContext *cx, JSClass *clazz)
-{
- return &XPC_WN_NoCall_JSOps;
-}
-
-JSClass XPC_WN_ModsAllowed_NoCall_Proto_JSClass = {
+js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass = {
"XPC_WN_ModsAllowed_NoCall_Proto_JSClass", // name;
WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags;
/* Mandatory non-null function pointer members. */
- JS_PropertyStub, // addProperty;
- JS_PropertyStub, // delProperty;
- JS_PropertyStub, // getProperty;
- JS_PropertyStub, // setProperty;
- XPC_WN_Shared_Proto_Enumerate, // enumerate;
- XPC_WN_ModsAllowed_Proto_Resolve, // resolve;
- XPC_WN_Shared_Proto_Convert, // convert;
- XPC_WN_Shared_Proto_Finalize, // finalize;
+ js::PropertyStub, // addProperty;
+ js::PropertyStub, // delProperty;
+ js::PropertyStub, // getProperty;
+ js::PropertyStub, // setProperty;
+ XPC_WN_Shared_Proto_Enumerate, // enumerate;
+ XPC_WN_ModsAllowed_Proto_Resolve,// resolve;
+ js::Valueify(XPC_WN_Shared_Proto_Convert), // convert;
+ XPC_WN_Shared_Proto_Finalize, // finalize;
/* Optionally non-null members start here. */
- XPC_WN_Proto_GetObjectOps, // getObjectOps;
+ nsnull, // reserved0;
nsnull, // checkAccess;
nsnull, // call;
nsnull, // construct;
nsnull, // xdrObject;
nsnull, // hasInstance;
JS_CLASS_TRACE(XPC_WN_Shared_Proto_Trace), // mark/trace;
- nsnull // spare;
+
+ JS_NULL_CLASS_EXT,
+ XPC_WN_NoCall_ObjectOps
};
/***************************************************************************/
static JSBool
XPC_WN_OnlyIWrite_Proto_PropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
- NS_ASSERTION(
- JS_InstanceOf(cx, obj, &XPC_WN_NoMods_WithCall_Proto_JSClass, nsnull) ||
- JS_InstanceOf(cx, obj, &XPC_WN_NoMods_NoCall_Proto_JSClass, nsnull),
+ NS_ASSERTION(obj->getClass() == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
+ obj->getClass() == &XPC_WN_NoMods_NoCall_Proto_JSClass,
"bad proto");
XPCWrappedNativeProto* self =
(XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
if(!self)
return JS_FALSE;
XPCCallContext ccx(JS_CALLER, cx);
@@ -2008,19 +1960,18 @@ XPC_WN_OnlyIWrite_Proto_PropertyStub(JSC
return JS_TRUE;
return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
}
static JSBool
XPC_WN_NoMods_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id)
{
- NS_ASSERTION(
- JS_InstanceOf(cx, obj, &XPC_WN_NoMods_WithCall_Proto_JSClass, nsnull) ||
- JS_InstanceOf(cx, obj, &XPC_WN_NoMods_NoCall_Proto_JSClass, nsnull),
+ NS_ASSERTION(obj->getClass() == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
+ obj->getClass() == &XPC_WN_NoMods_NoCall_Proto_JSClass,
"bad proto");
XPCWrappedNativeProto* self =
(XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
if(!self)
return JS_FALSE;
XPCCallContext ccx(JS_CALLER, cx);
@@ -2035,64 +1986,68 @@ XPC_WN_NoMods_Proto_Resolve(JSContext *c
self->GetSet(), nsnull, nsnull,
self->GetScope(),
JS_TRUE, nsnull, nsnull, si,
JSPROP_READONLY |
JSPROP_PERMANENT |
enumFlag, nsnull);
}
-JSClass XPC_WN_NoMods_WithCall_Proto_JSClass = {
+js::Class XPC_WN_NoMods_WithCall_Proto_JSClass = {
"XPC_WN_NoMods_WithCall_Proto_JSClass", // name;
WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags;
/* Mandatory non-null function pointer members. */
- XPC_WN_OnlyIWrite_Proto_PropertyStub, // addProperty;
- XPC_WN_CannotModifyPropertyStub, // delProperty;
- JS_PropertyStub, // getProperty;
- XPC_WN_OnlyIWrite_Proto_PropertyStub, // setProperty;
- XPC_WN_Shared_Proto_Enumerate, // enumerate;
- XPC_WN_NoMods_Proto_Resolve, // resolve;
- XPC_WN_Shared_Proto_Convert, // convert;
- XPC_WN_Shared_Proto_Finalize, // finalize;
+ js::Valueify(XPC_WN_OnlyIWrite_Proto_PropertyStub), // addProperty;
+ js::Valueify(XPC_WN_CannotModifyPropertyStub), // delProperty;
+ js::PropertyStub, // getProperty;
+ js::Valueify(XPC_WN_OnlyIWrite_Proto_PropertyStub), // setProperty;
+ XPC_WN_Shared_Proto_Enumerate, // enumerate;
+ XPC_WN_NoMods_Proto_Resolve, // resolve;
+ js::Valueify(XPC_WN_Shared_Proto_Convert), // convert;
+ XPC_WN_Shared_Proto_Finalize, // finalize;
/* Optionally non-null members start here. */
- XPC_WN_Proto_GetObjectOps, // getObjectOps;
+ nsnull, // reserved0;
nsnull, // checkAccess;
nsnull, // call;
nsnull, // construct;
nsnull, // xdrObject;
nsnull, // hasInstance;
JS_CLASS_TRACE(XPC_WN_Shared_Proto_Trace), // mark/trace;
- nsnull // spare;
+
+ JS_NULL_CLASS_EXT,
+ XPC_WN_WithCall_ObjectOps
};
-JSClass XPC_WN_NoMods_NoCall_Proto_JSClass = {
- "XPC_WN_NoMods_NoCall_Proto_JSClass", // name;
- WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags;
+js::Class XPC_WN_NoMods_NoCall_Proto_JSClass = {
+ "XPC_WN_NoMods_NoCall_Proto_JSClass", // name;
+ WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags;
/* Mandatory non-null function pointer members. */
- XPC_WN_OnlyIWrite_Proto_PropertyStub, // addProperty;
- XPC_WN_CannotModifyPropertyStub, // delProperty;
- JS_PropertyStub, // getProperty;
- XPC_WN_OnlyIWrite_Proto_PropertyStub, // setProperty;
- XPC_WN_Shared_Proto_Enumerate, // enumerate;
- XPC_WN_NoMods_Proto_Resolve, // resolve;
- XPC_WN_Shared_Proto_Convert, // convert;
- XPC_WN_Shared_Proto_Finalize, // finalize;
+ js::Valueify(XPC_WN_OnlyIWrite_Proto_PropertyStub), // addProperty;
+ js::Valueify(XPC_WN_CannotModifyPropertyStub), // delProperty;
+ js::PropertyStub, // getProperty;
+ js::Valueify(XPC_WN_OnlyIWrite_Proto_PropertyStub), // setProperty;
+ XPC_WN_Shared_Proto_Enumerate, // enumerate;
+ XPC_WN_NoMods_Proto_Resolve, // resolve;
+ js::Valueify(XPC_WN_Shared_Proto_Convert), // convert;
+ XPC_WN_Shared_Proto_Finalize, // finalize;
/* Optionally non-null members start here. */
- XPC_WN_Proto_GetObjectOps, // getObjectOps;
+ nsnull, // reserved0;
nsnull, // checkAccess;
nsnull, // call;
nsnull, // construct;
nsnull, // xdrObject;
nsnull, // hasInstance;
JS_CLASS_TRACE(XPC_WN_Shared_Proto_Trace), // mark/trace;
- nsnull // spare;
+
+ JS_NULL_CLASS_EXT,
+ XPC_WN_NoCall_ObjectOps
};
/***************************************************************************/
static JSBool
XPC_WN_TearOff_Enumerate(JSContext *cx, JSObject *obj)
{
MORPH_SLIM_WRAPPER(cx, obj);
@@ -2143,32 +2098,21 @@ XPC_WN_TearOff_Finalize(JSContext *cx, J
{
XPCWrappedNativeTearOff* p = (XPCWrappedNativeTearOff*)
xpc_GetJSPrivate(obj);
if(!p)
return;
p->JSObjectFinalized();
}
-JSClass XPC_WN_Tearoff_JSClass = {
- "WrappedNative_TearOff", // name;
- WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags;
+js::Class XPC_WN_Tearoff_JSClass = {
+ "WrappedNative_TearOff", // name;
+ WRAPPER_SLOTS | JSCLASS_MARK_IS_TRACE, // flags;
- /* Mandatory non-null function pointer members. */
- XPC_WN_OnlyIWrite_PropertyStub, // addProperty;
- XPC_WN_CannotModifyPropertyStub, // delProperty;
- JS_PropertyStub, // getProperty;
- XPC_WN_OnlyIWrite_PropertyStub, // setProperty;
- XPC_WN_TearOff_Enumerate, // enumerate;
- XPC_WN_TearOff_Resolve, // resolve;
- XPC_WN_Shared_Convert, // convert;
- XPC_WN_TearOff_Finalize, // finalize;
-
- /* Optionally non-null members start here. */
- nsnull, // getObjectOps;
- nsnull, // checkAccess;
- nsnull, // call;
- nsnull, // construct;
- nsnull, // xdrObject;
- nsnull, // hasInstance;
- nsnull, // mark/trace;
- nsnull // spare;
+ js::Valueify(XPC_WN_OnlyIWrite_PropertyStub), // addProperty;
+ js::Valueify(XPC_WN_CannotModifyPropertyStub), // delProperty;
+ js::PropertyStub, // getProperty;
+ js::Valueify(XPC_WN_OnlyIWrite_PropertyStub), // setProperty;
+ XPC_WN_TearOff_Enumerate, // enumerate;
+ XPC_WN_TearOff_Resolve, // resolve;
+ js::Valueify(XPC_WN_Shared_Convert), // convert;
+ XPC_WN_TearOff_Finalize // finalize;
};
--- a/js/src/xpconnect/src/xpcwrappednativeproto.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativeproto.cpp
@@ -99,17 +99,17 @@ XPCWrappedNativeProto::Init(
if(callback)
{
mScriptableInfo =
XPCNativeScriptableInfo::Construct(ccx, isGlobal, scriptableCreateInfo);
if(!mScriptableInfo)
return JS_FALSE;
}
- JSClass* jsclazz;
+ js::Class* jsclazz;
if(mScriptableInfo)
{
const XPCNativeScriptableFlags& flags(mScriptableInfo->GetFlags());
if(flags.AllowPropModsToPrototype())
{
@@ -127,17 +127,17 @@ XPCWrappedNativeProto::Init(
else
{
jsclazz = &XPC_WN_NoMods_NoCall_Proto_JSClass;
}
JSObject *parent = mScope->GetGlobalJSObject();
mJSProtoObject =
- xpc_NewSystemInheritingJSObject(ccx, jsclazz,
+ xpc_NewSystemInheritingJSObject(ccx, js::Jsvalify(jsclazz),
mScope->GetPrototypeJSObject(),
parent);
JSBool ok = mJSProtoObject && JS_SetPrivate(ccx, mJSProtoObject, this);
if(ok && callback)
{
nsresult rv = callback->PostCreatePrototype(ccx, mJSProtoObject);
--- a/js/src/xpconnect/src/xpcwrappednativescope.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp
@@ -199,39 +199,41 @@ XPCWrappedNativeScope::SetComponents(nsX
// scopes. By doing this we avoid allocating a new scope for every
// wrapper on creation of the wrapper, and most wrappers won't need
// their own scope at all for the lifetime of the wrapper.
// WRAPPER_SLOTS is key here (even though there's never anything
// in the private data slot in these prototypes), as the number of
// reserved slots in this class needs to match that of the wrappers
// for the JS engine to share scopes.
-JSClass XPC_WN_NoHelper_Proto_JSClass = {
+js::Class XPC_WN_NoHelper_Proto_JSClass = {
"XPC_WN_NoHelper_Proto_JSClass",// name;
WRAPPER_SLOTS, // flags;
/* Mandatory non-null function pointer members. */
- JS_PropertyStub, // addProperty;
- JS_PropertyStub, // delProperty;
- JS_PropertyStub, // getProperty;
- JS_PropertyStub, // setProperty;
- JS_EnumerateStub, // enumerate;
+ js::PropertyStub, // addProperty;
+ js::PropertyStub, // delProperty;
+ js::PropertyStub, // getProperty;
+ js::PropertyStub, // setProperty;
+ js::EnumerateStub, // enumerate;
JS_ResolveStub, // resolve;
- JS_ConvertStub, // convert;
+ js::ConvertStub, // convert;
nsnull, // finalize;
/* Optionally non-null members start here. */
- XPC_WN_Proto_GetObjectOps, // getObjectOps;
+ nsnull, // reserved0;
nsnull, // checkAccess;
nsnull, // call;
nsnull, // construct;
nsnull, // xdrObject;
nsnull, // hasInstance;
nsnull, // mark/trace;
- nsnull // spare;
+
+ JS_NULL_CLASS_EXT,
+ XPC_WN_NoCall_ObjectOps
};
void
XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal)
{
// We allow for calling this more than once. This feature is used by
// nsXPConnect::InitClassesWithNewWrappedGlobal.
@@ -345,17 +347,18 @@ JSObject *
XPCWrappedNativeScope::GetPrototypeNoHelper(XPCCallContext& ccx)
{
// We could create this prototype in SetGlobal(), but all scopes
// don't need one, so we save ourselves a bit of space if we
// create these when they're needed.
if(!mPrototypeNoHelper)
{
mPrototypeNoHelper =
- xpc_NewSystemInheritingJSObject(ccx, &XPC_WN_NoHelper_Proto_JSClass,
+ xpc_NewSystemInheritingJSObject(ccx,
+ js::Jsvalify(&XPC_WN_NoHelper_Proto_JSClass),
mPrototypeJSObject,
mGlobalJSObject);
NS_ASSERTION(mPrototypeNoHelper,
"Failed to create prototype for wrappers w/o a helper");
}
return mPrototypeNoHelper;
@@ -720,17 +723,17 @@ XPCWrappedNativeScope::SystemIsBeingShut
/***************************************************************************/
static
XPCWrappedNativeScope*
GetScopeOfObject(JSObject* obj)
{
nsISupports* supports;
- JSClass* clazz = obj->getJSClass();
+ js::Class* clazz = obj->getClass();
JSBool isWrapper = IS_WRAPPER_CLASS(clazz);
if(isWrapper && IS_SLIM_WRAPPER_OBJECT(obj))
return GetSlimWrapperProto(obj)->GetScope();
if(!isWrapper || !(supports = (nsISupports*) xpc_GetJSPrivate(obj)))
{
#ifdef DEBUG