Backout bug 684110 (08b6eaf6aad0, cf8b35fa1010, 25ee45edabe1, 659f5c7d2cc9, 870f6dd82586 & e1ad65d6a7fd) and bug 684344 (cd1957f6628d) on a CLOSED TREE; a=bustage-fairies

This commit is contained in:
Ed Morley 2011-09-03 03:21:25 +01:00
Родитель ed615fb8d5
Коммит 5ad1e0be99
75 изменённых файлов: 1010 добавлений и 740 удалений

Просмотреть файл

@ -2423,7 +2423,7 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
// avoid wasting time checking properties of their classes etc in // avoid wasting time checking properties of their classes etc in
// the loop. // the loop.
if (jsClass == &js::FunctionClass) { if (jsClass == &js_FunctionClass) {
aObj = aObj->getParent(); aObj = aObj->getParent();
if (!aObj) if (!aObj)
@ -2431,7 +2431,7 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
jsClass = aObj->getClass(); jsClass = aObj->getClass();
if (jsClass == &js::CallClass) { if (jsClass == &js_CallClass) {
aObj = aObj->getParent(); aObj = aObj->getParent();
if (!aObj) if (!aObj)

Просмотреть файл

@ -49,7 +49,7 @@ bool checkObjectFields(JSObject *savedCopy, JSObject *obj)
{ {
/* Ignore fields which are unstable across GCs. */ /* Ignore fields which are unstable across GCs. */
CHECK(savedCopy->lastProp == obj->lastProp); CHECK(savedCopy->lastProp == obj->lastProp);
CHECK(savedCopy->getClass() == obj->getClass()); CHECK(savedCopy->clasp == obj->clasp);
CHECK(savedCopy->flags == obj->flags); CHECK(savedCopy->flags == obj->flags);
CHECK(savedCopy->newType == obj->newType); CHECK(savedCopy->newType == obj->newType);
CHECK(savedCopy->getProto() == obj->getProto()); CHECK(savedCopy->getProto() == obj->getProto());

Просмотреть файл

@ -1543,7 +1543,7 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
return obj->asGlobal()->initStandardClasses(cx); return obj->asGlobal()->initStandardClasses(cx);
} }
#define CLASP(name) (&name##Class) #define CLASP(name) (&js_##name##Class)
#define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type]) #define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type])
#define EAGER_ATOM(name) ATOM_OFFSET(name), NULL #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
#define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
@ -1653,7 +1653,7 @@ static JSStdName standard_class_names[] = {
#endif #endif
/* Typed Arrays */ /* Typed Arrays */
{js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &ArrayBufferClass}, {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js_ArrayBufferClass},
{js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int8Array), TYPED_ARRAY_CLASP(TYPE_INT8)}, {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(Uint8Array), TYPED_ARRAY_CLASP(TYPE_UINT8)},
{js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int16Array), TYPED_ARRAY_CLASP(TYPE_INT16)}, {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int16Array), TYPED_ARRAY_CLASP(TYPE_INT16)},
@ -2275,7 +2275,7 @@ JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
{ {
JSObject *obj = (JSObject *)thing; JSObject *obj = (JSObject *)thing;
Class *clasp = obj->getClass(); Class *clasp = obj->getClass();
if (clasp == &FunctionClass) { if (clasp == &js_FunctionClass) {
JSFunction *fun = obj->getFunctionPrivate(); JSFunction *fun = obj->getFunctionPrivate();
if (!fun) { if (!fun) {
JS_snprintf(buf, bufsize, "<newborn>"); JS_snprintf(buf, bufsize, "<newborn>");
@ -3064,9 +3064,9 @@ JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
Class *clasp = Valueify(jsclasp); Class *clasp = Valueify(jsclasp);
if (!clasp) if (!clasp)
clasp = &ObjectClass; /* default class is Object */ clasp = &js_ObjectClass; /* default class is Object */
JS_ASSERT(clasp != &FunctionClass); JS_ASSERT(clasp != &js_FunctionClass);
JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL)); JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
if (proto) if (proto)
@ -3093,9 +3093,9 @@ JS_NewObjectWithGivenProto(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSO
Class *clasp = Valueify(jsclasp); Class *clasp = Valueify(jsclasp);
if (!clasp) if (!clasp)
clasp = &ObjectClass; /* default class is Object */ clasp = &js_ObjectClass; /* default class is Object */
JS_ASSERT(clasp != &FunctionClass); JS_ASSERT(clasp != &js_FunctionClass);
JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL)); JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
JSObject *obj = NewNonFunction<WithProto::Given>(cx, clasp, proto, parent); JSObject *obj = NewNonFunction<WithProto::Given>(cx, clasp, proto, parent);
@ -3168,7 +3168,7 @@ JS_ConstructObject(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *p
assertSameCompartment(cx, proto, parent); assertSameCompartment(cx, proto, parent);
Class *clasp = Valueify(jsclasp); Class *clasp = Valueify(jsclasp);
if (!clasp) if (!clasp)
clasp = &ObjectClass; /* default class is Object */ clasp = &js_ObjectClass; /* default class is Object */
return js_ConstructObject(cx, clasp, proto, parent, 0, NULL); return js_ConstructObject(cx, clasp, proto, parent, 0, NULL);
} }
@ -3180,7 +3180,7 @@ JS_ConstructObjectWithArguments(JSContext *cx, JSClass *jsclasp, JSObject *proto
assertSameCompartment(cx, proto, parent, JSValueArray(argv, argc)); assertSameCompartment(cx, proto, parent, JSValueArray(argv, argc));
Class *clasp = Valueify(jsclasp); Class *clasp = Valueify(jsclasp);
if (!clasp) if (!clasp)
clasp = &ObjectClass; /* default class is Object */ clasp = &js_ObjectClass; /* default class is Object */
return js_ConstructObject(cx, clasp, proto, parent, argc, Valueify(argv)); return js_ConstructObject(cx, clasp, proto, parent, argc, Valueify(argv));
} }
@ -3520,7 +3520,7 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *jsclasp
Class *clasp = Valueify(jsclasp); Class *clasp = Valueify(jsclasp);
if (!clasp) if (!clasp)
clasp = &ObjectClass; /* default class is Object */ clasp = &js_ObjectClass; /* default class is Object */
JSObject *nobj = NewObject<WithProto::Class>(cx, clasp, proto, obj); JSObject *nobj = NewObject<WithProto::Class>(cx, clasp, proto, obj);
if (!nobj) if (!nobj)
@ -4215,7 +4215,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
JS_ASSERT(parent); JS_ASSERT(parent);
} }
if (!funobj->isFunction()) { if (funobj->getClass() != &js_FunctionClass) {
/* /*
* We cannot clone this object, so fail (we used to return funobj, bad * We cannot clone this object, so fail (we used to return funobj, bad
* idea, but we changed incompatibly to teach any abusers a lesson!). * idea, but we changed incompatibly to teach any abusers a lesson!).
@ -4306,7 +4306,7 @@ JS_GetFunctionArity(JSFunction *fun)
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_ObjectIsFunction(JSContext *cx, JSObject *obj) JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
{ {
return obj->isFunction(); return obj->getClass() == &js_FunctionClass;
} }
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)

Просмотреть файл

@ -44,7 +44,7 @@
* Array objects begin as "dense" arrays, optimized for index-only property * Array objects begin as "dense" arrays, optimized for index-only property
* access over a vector of slots with high load factor. Array methods * access over a vector of slots with high load factor. Array methods
* optimize for denseness by testing that the object's class is * optimize for denseness by testing that the object's class is
* &ArrayClass, and can then directly manipulate the slots for efficiency. * &js_ArrayClass, and can then directly manipulate the slots for efficiency.
* *
* We track these pieces of metadata for arrays in dense mode: * We track these pieces of metadata for arrays in dense mode:
* - The array's length property as a uint32, accessible with * - The array's length property as a uint32, accessible with
@ -81,7 +81,7 @@
* known to have no hole values below its initialized length, then it is a * known to have no hole values below its initialized length, then it is a
* "packed" array and can be accessed much faster by JIT code. * "packed" array and can be accessed much faster by JIT code.
* *
* Arrays are converted to use SlowArrayClass when any of these conditions * Arrays are converted to use js_SlowArrayClass when any of these conditions
* are met: * are met:
* - there are more than MIN_SPARSE_INDEX slots total and the load factor * - there are more than MIN_SPARSE_INDEX slots total and the load factor
* (COUNT / capacity) is less than 0.25 * (COUNT / capacity) is less than 0.25
@ -93,7 +93,7 @@
* properties in the order they were created. We could instead maintain the * properties in the order they were created. We could instead maintain the
* scope to track property enumeration order, but still use the fast slot * scope to track property enumeration order, but still use the fast slot
* access. That would have the same memory cost as just using a * access. That would have the same memory cost as just using a
* SlowArrayClass, but have the same performance characteristics as a dense * js_SlowArrayClass, but have the same performance characteristics as a dense
* array for slot accesses, at some cost in code complexity. * array for slot accesses, at some cost in code complexity.
*/ */
#include <stdlib.h> #include <stdlib.h>
@ -146,6 +146,13 @@ using namespace js;
using namespace js::gc; using namespace js::gc;
using namespace js::types; using namespace js::types;
static inline bool
ENSURE_SLOW_ARRAY(JSContext *cx, JSObject *obj)
{
return obj->getClass() == &js_SlowArrayClass ||
obj->makeDenseArraySlow(cx);
}
JSBool JSBool
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp) js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
{ {
@ -239,11 +246,14 @@ static JSBool
BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom, BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom,
jsid *idp) jsid *idp)
{ {
jschar buf[10], *start;
Class *clasp;
JSAtom *atom;
JS_STATIC_ASSERT((jsuint)-1 == 4294967295U); JS_STATIC_ASSERT((jsuint)-1 == 4294967295U);
JS_ASSERT(index > JSID_INT_MAX); JS_ASSERT(index > JSID_INT_MAX);
jschar buf[10]; start = JS_ARRAY_END(buf);
jschar *start = JS_ARRAY_END(buf);
do { do {
--start; --start;
*start = (jschar)('0' + index % 10); *start = (jschar)('0' + index % 10);
@ -254,11 +264,14 @@ BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom,
* Skip the atomization if the class is known to store atoms corresponding * Skip the atomization if the class is known to store atoms corresponding
* to big indexes together with elements. In such case we know that the * to big indexes together with elements. In such case we know that the
* array does not have an element at the given index if its atom does not * array does not have an element at the given index if its atom does not
* exist. Dense arrays don't use atoms for any indexes, though it would be * exist. Fast arrays (clasp == &js_ArrayClass) don't use atoms for
* rare to see them have a big index in any case. * any indexes, though it would be rare to see them have a big index
* in any case.
*/ */
JSAtom *atom; if (!createAtom &&
if (!createAtom && (obj->isSlowArray() || obj->isArguments() || obj->isObject())) { ((clasp = obj->getClass()) == &js_SlowArrayClass ||
obj->isArguments() ||
clasp == &js_ObjectClass)) {
atom = js_GetExistingStringAtom(cx, start, JS_ARRAY_END(buf) - start); atom = js_GetExistingStringAtom(cx, start, JS_ARRAY_END(buf) - start);
if (!atom) { if (!atom) {
*idp = JSID_VOID; *idp = JSID_VOID;
@ -488,13 +501,13 @@ JSBool JS_FASTCALL
js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i) js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i)
{ {
#ifdef DEBUG #ifdef DEBUG
Class *origObjClasp = obj->getClass(); Class *origObjClasp = obj->clasp;
#endif #endif
jsuint u = jsuint(i); jsuint u = jsuint(i);
JSBool ret = (obj->ensureDenseArrayElements(cx, u, 1) == JSObject::ED_OK); JSBool ret = (obj->ensureDenseArrayElements(cx, u, 1) == JSObject::ED_OK);
/* Partially check the CallInfo's storeAccSet is correct. */ /* Partially check the CallInfo's storeAccSet is correct. */
JS_ASSERT(obj->getClass() == origObjClasp); JS_ASSERT(obj->clasp == origObjClasp);
return ret; return ret;
} }
/* This function and its callees do not touch any object's .clasp field. */ /* This function and its callees do not touch any object's .clasp field. */
@ -976,7 +989,7 @@ array_fix(JSContext *cx, JSObject *obj, bool *success, AutoIdVector *props)
return true; return true;
} }
Class js::ArrayClass = { Class js_ArrayClass = {
"Array", "Array",
Class::NON_NATIVE | JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array), Class::NON_NATIVE | JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -1011,7 +1024,7 @@ Class js::ArrayClass = {
} }
}; };
Class js::SlowArrayClass = { Class js_SlowArrayClass = {
"Array", "Array",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_CACHED_PROTO(JSProto_Array), JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
@ -1056,7 +1069,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
/* Create a native scope. */ /* Create a native scope. */
gc::AllocKind kind = getAllocKind(); gc::AllocKind kind = getAllocKind();
if (!InitScopeForObject(cx, this, &SlowArrayClass, getProto()->getNewType(cx), kind)) if (!InitScopeForObject(cx, this, &js_SlowArrayClass, getProto()->getNewType(cx), kind))
return false; return false;
backfillDenseArrayHoles(cx); backfillDenseArrayHoles(cx);
@ -1077,7 +1090,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
JS_ASSERT(!denseArrayHasInlineSlots()); JS_ASSERT(!denseArrayHasInlineSlots());
} }
capacity = numFixedSlots() + arrayCapacity; capacity = numFixedSlots() + arrayCapacity;
clasp = &SlowArrayClass; clasp = &js_SlowArrayClass;
/* /*
* Root all values in the array during conversion, as SlowArrayClass only * Root all values in the array during conversion, as SlowArrayClass only
@ -1097,7 +1110,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
setMap(oldMap); setMap(oldMap);
capacity = arrayCapacity; capacity = arrayCapacity;
initializedLength = arrayInitialized; initializedLength = arrayInitialized;
clasp = &ArrayClass; clasp = &js_ArrayClass;
return false; return false;
} }
@ -1120,7 +1133,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
setMap(oldMap); setMap(oldMap);
capacity = arrayCapacity; capacity = arrayCapacity;
initializedLength = arrayInitialized; initializedLength = arrayInitialized;
clasp = &ArrayClass; clasp = &js_ArrayClass;
return false; return false;
} }
@ -1131,7 +1144,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
/* /*
* Finally, update class. If |this| is Array.prototype, then js_InitClass * Finally, update class. If |this| is Array.prototype, then js_InitClass
* will create an emptyShape whose class is &SlowArrayClass, to ensure * will create an emptyShape whose class is &js_SlowArrayClass, to ensure
* that delegating instances can share shapes in the tree rooted at the * that delegating instances can share shapes in the tree rooted at the
* proto's empty shape. * proto's empty shape.
*/ */
@ -1198,7 +1211,7 @@ array_toSource(JSContext *cx, uintN argc, Value *vp)
if (!obj) if (!obj)
return false; return false;
if (!obj->isArray()) { if (!obj->isArray()) {
ReportIncompatibleMethod(cx, vp, &ArrayClass); ReportIncompatibleMethod(cx, vp, &js_ArrayClass);
return false; return false;
} }
@ -1527,7 +1540,7 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, Valu
return JS_TRUE; return JS_TRUE;
/* Finish out any remaining elements past the max array index. */ /* Finish out any remaining elements past the max array index. */
if (obj->isDenseArray() && !obj->makeDenseArraySlow(cx)) if (obj->isDenseArray() && !ENSURE_SLOW_ARRAY(cx, obj))
return JS_FALSE; return JS_FALSE;
JS_ASSERT(start == MAX_ARRAY_INDEX + 1); JS_ASSERT(start == MAX_ARRAY_INDEX + 1);
@ -3204,12 +3217,12 @@ js_InitArrayClass(JSContext *cx, JSObject *obj)
GlobalObject *global = obj->asGlobal(); GlobalObject *global = obj->asGlobal();
JSObject *arrayProto = global->createBlankPrototype(cx, &SlowArrayClass); JSObject *arrayProto = global->createBlankPrototype(cx, &js_SlowArrayClass);
if (!arrayProto || !AddLengthProperty(cx, arrayProto)) if (!arrayProto || !AddLengthProperty(cx, arrayProto))
return NULL; return NULL;
arrayProto->setArrayLength(cx, 0); arrayProto->setArrayLength(cx, 0);
JSFunction *ctor = global->createConstructor(cx, js_Array, &ArrayClass, JSFunction *ctor = global->createConstructor(cx, js_Array, &js_ArrayClass,
CLASS_ATOM(cx, Array), 1); CLASS_ATOM(cx, Array), 1);
if (!ctor) if (!ctor)
return NULL; return NULL;
@ -3244,7 +3257,7 @@ NewArray(JSContext *cx, jsuint length, JSObject *proto)
JS_ASSERT_IF(proto, proto->isArray()); JS_ASSERT_IF(proto, proto->isArray());
gc::AllocKind kind = GuessObjectGCKind(length, true); gc::AllocKind kind = GuessObjectGCKind(length, true);
JSObject *obj = detail::NewObject<WithProto::Class, false>(cx, &ArrayClass, proto, NULL, kind); JSObject *obj = detail::NewObject<WithProto::Class, false>(cx, &js_ArrayClass, proto, NULL, kind);
if (!obj) if (!obj)
return NULL; return NULL;
@ -3333,7 +3346,7 @@ JS_DEFINE_CALLINFO_3(extern, OBJECT, NewDenseUnallocatedArray, CONTEXT, UINT32,
JSObject * JSObject *
NewSlowEmptyArray(JSContext *cx) NewSlowEmptyArray(JSContext *cx)
{ {
JSObject *obj = NewNonFunction<WithProto::Class>(cx, &SlowArrayClass, NULL, NULL); JSObject *obj = NewNonFunction<WithProto::Class>(cx, &js_SlowArrayClass, NULL, NULL);
if (!obj || !AddLengthProperty(cx, obj)) if (!obj || !AddLengthProperty(cx, obj))
return NULL; return NULL;

Просмотреть файл

@ -63,7 +63,7 @@
using namespace js; using namespace js;
using namespace js::types; using namespace js::types;
Class js::BooleanClass = { Class js_BooleanClass = {
"Boolean", "Boolean",
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_RESERVED_SLOTS(1) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean), JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
@ -138,7 +138,7 @@ Boolean(JSContext *cx, uintN argc, Value *vp)
bool b = argc != 0 ? js_ValueToBoolean(argv[0]) : false; bool b = argc != 0 ? js_ValueToBoolean(argv[0]) : false;
if (IsConstructing(vp)) { if (IsConstructing(vp)) {
JSObject *obj = NewBuiltinClassInstance(cx, &BooleanClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_BooleanClass);
if (!obj) if (!obj)
return false; return false;
obj->setPrimitiveThis(BooleanValue(b)); obj->setPrimitiveThis(BooleanValue(b));
@ -152,7 +152,7 @@ Boolean(JSContext *cx, uintN argc, Value *vp)
JSObject * JSObject *
js_InitBooleanClass(JSContext *cx, JSObject *obj) js_InitBooleanClass(JSContext *cx, JSObject *obj)
{ {
JSObject *proto = js_InitClass(cx, obj, NULL, &BooleanClass, Boolean, 1, JSObject *proto = js_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1,
NULL, boolean_methods, NULL, NULL); NULL, boolean_methods, NULL, NULL);
if (!proto) if (!proto)
return NULL; return NULL;

Просмотреть файл

@ -46,6 +46,14 @@
#include "jsapi.h" #include "jsapi.h"
#include "jsobj.h" #include "jsobj.h"
extern js::Class js_BooleanClass;
inline bool
JSObject::isBoolean() const
{
return getClass() == &js_BooleanClass;
}
extern JSObject * extern JSObject *
js_InitBooleanClass(JSContext *cx, JSObject *obj); js_InitBooleanClass(JSContext *cx, JSObject *obj);

Просмотреть файл

@ -251,7 +251,7 @@ HasProperty(JSContext* cx, JSObject* obj, jsid id)
if (pobj->getOps()->lookupProperty) if (pobj->getOps()->lookupProperty)
return JS_NEITHER; return JS_NEITHER;
Class* clasp = pobj->getClass(); Class* clasp = pobj->getClass();
if (clasp->resolve != JS_ResolveStub && clasp != &StringClass) if (clasp->resolve != JS_ResolveStub && clasp != &js_StringClass)
return JS_NEITHER; return JS_NEITHER;
} }
@ -320,7 +320,7 @@ js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* pa
if (!closure) if (!closure)
return NULL; return NULL;
if (!closure->initSharingEmptyShape(cx, &FunctionClass, type, parent, if (!closure->initSharingEmptyShape(cx, &js_FunctionClass, type, parent,
fun, gc::FINALIZE_OBJECT2)) { fun, gc::FINALIZE_OBJECT2)) {
return NULL; return NULL;
} }

Просмотреть файл

@ -84,8 +84,8 @@ enum {
* 'i': an integer argument * 'i': an integer argument
* 's': a JSString* argument * 's': a JSString* argument
* 'o': a JSObject* argument * 'o': a JSObject* argument
* 'r': a JSObject* argument that is of class RegExpClass * 'r': a JSObject* argument that is of class js_RegExpClass
* 'f': a JSObject* argument that is of class FunctionClass * 'f': a JSObject* argument that is of class js_FunctionClass
* 'v': a value argument: on 32-bit, a Value*, on 64-bit, a jsval * 'v': a value argument: on 32-bit, a Value*, on 64-bit, a jsval
*/ */
struct JSSpecializedNative { struct JSSpecializedNative {

Просмотреть файл

@ -782,7 +782,7 @@ JSStructuredCloneReader::startRead(Value *vp)
case SCTAG_OBJECT_OBJECT: { case SCTAG_OBJECT_OBJECT: {
JSObject *obj = (tag == SCTAG_ARRAY_OBJECT) JSObject *obj = (tag == SCTAG_ARRAY_OBJECT)
? NewDenseEmptyArray(context()) ? NewDenseEmptyArray(context())
: NewBuiltinClassInstance(context(), &ObjectClass); : NewBuiltinClassInstance(context(), &js_ObjectClass);
if (!obj || !objs.append(ObjectValue(*obj)) || if (!obj || !objs.append(ObjectValue(*obj)) ||
!allObjs.append(ObjectValue(*obj))) !allObjs.append(ObjectValue(*obj)))
return false; return false;

Просмотреть файл

@ -334,10 +334,12 @@ CallJSNativeConstructor(JSContext *cx, js::Native native, const CallArgs &args)
* *
* (new Object(Object)) returns the callee. * (new Object(Object)) returns the callee.
*/ */
JS_ASSERT_IF(native != FunctionProxyClass.construct && extern JSBool proxy_Construct(JSContext *, uintN, Value *);
native != CallableObjectClass.construct && extern JSBool callable_Construct(JSContext *, uintN, Value *);
JS_ASSERT_IF(native != proxy_Construct &&
native != callable_Construct &&
native != js::CallOrConstructBoundFunction && native != js::CallOrConstructBoundFunction &&
(!callee.isFunction() || callee.getFunctionPrivate()->u.n.clasp != &ObjectClass), (!callee.isFunction() || callee.getFunctionPrivate()->u.n.clasp != &js_ObjectClass),
!args.rval().isPrimitive() && callee != args.rval().toObject()); !args.rval().isPrimitive() && callee != args.rval().toObject());
return true; return true;

Просмотреть файл

@ -247,7 +247,7 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
return true; return true;
/* Translate StopIteration singleton. */ /* Translate StopIteration singleton. */
if (obj->isStopIteration()) if (obj->getClass() == &js_StopIterationClass)
return js_FindClassObject(cx, NULL, JSProto_StopIteration, vp); return js_FindClassObject(cx, NULL, JSProto_StopIteration, vp);
/* Don't unwrap an outer window proxy. */ /* Don't unwrap an outer window proxy. */

Просмотреть файл

@ -503,7 +503,7 @@ date_convert(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
* Other Support routines and definitions * Other Support routines and definitions
*/ */
Class js::DateClass = { Class js_DateClass = {
js_Date_str, js_Date_str,
JSCLASS_HAS_RESERVED_SLOTS(JSObject::DATE_CLASS_RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(JSObject::DATE_CLASS_RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Date), JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
@ -1226,7 +1226,7 @@ GetUTCTime(JSContext *cx, JSObject *obj, Value *vp, jsdouble *dp)
{ {
if (!obj->isDate()) { if (!obj->isDate()) {
if (vp) if (vp)
ReportIncompatibleMethod(cx, vp, &DateClass); ReportIncompatibleMethod(cx, vp, &js_DateClass);
return false; return false;
} }
*dp = obj->getDateUTCTime().toNumber(); *dp = obj->getDateUTCTime().toNumber();
@ -1408,7 +1408,7 @@ GetAndCacheLocalTime(JSContext *cx, JSObject *obj, Value *vp, jsdouble *time = N
return false; return false;
if (!obj->isDate()) { if (!obj->isDate()) {
if (vp) if (vp)
ReportIncompatibleMethod(cx, vp, &DateClass); ReportIncompatibleMethod(cx, vp, &js_DateClass);
return false; return false;
} }
@ -1701,7 +1701,7 @@ date_setTime(JSContext *cx, uintN argc, Value *vp)
return false; return false;
if (!obj->isDate()) { if (!obj->isDate()) {
ReportIncompatibleMethod(cx, vp, &DateClass); ReportIncompatibleMethod(cx, vp, &js_DateClass);
return false; return false;
} }
@ -2607,7 +2607,7 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
{ {
/* set static LocalTZA */ /* set static LocalTZA */
LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond); LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
JSObject *proto = js_InitClass(cx, obj, NULL, &DateClass, js_Date, MAXARGS, JSObject *proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS,
NULL, date_methods, NULL, date_static_methods); NULL, date_methods, NULL, date_static_methods);
if (!proto) if (!proto)
return NULL; return NULL;
@ -2638,7 +2638,7 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
JS_FRIEND_API(JSObject *) JS_FRIEND_API(JSObject *)
js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time) js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
{ {
JSObject *obj = NewBuiltinClassInstance(cx, &DateClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_DateClass);
if (!obj || !obj->ensureSlots(cx, JSObject::DATE_CLASS_RESERVED_SLOTS)) if (!obj || !obj->ensureSlots(cx, JSObject::DATE_CLASS_RESERVED_SLOTS))
return NULL; return NULL;
if (!SetUTCTime(cx, obj, msec_time)) if (!SetUTCTime(cx, obj, msec_time))

Просмотреть файл

@ -46,6 +46,14 @@
#include "jsobj.h" #include "jsobj.h"
extern js::Class js_DateClass;
inline bool
JSObject::isDate() const
{
return getClass() == &js_DateClass;
}
#define HalfTimeDomain 8.64e15 #define HalfTimeDomain 8.64e15
#define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \ #define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \

Просмотреть файл

@ -2000,7 +2000,7 @@ EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg)
if (depth < 0) if (depth < 0)
return false; return false;
uintN base = JSSLOT_FREE(&BlockClass); uintN base = JSSLOT_FREE(&js_BlockClass);
for (uintN slot = base, limit = base + OBJ_BLOCK_COUNT(cx, blockObj); slot < limit; slot++) { for (uintN slot = base, limit = base + OBJ_BLOCK_COUNT(cx, blockObj); slot < limit; slot++) {
const Value &v = blockObj->getSlot(slot); const Value &v = blockObj->getSlot(slot);
@ -4898,7 +4898,7 @@ JSParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp)
JS_ASSERT((pn_op == JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST)); JS_ASSERT((pn_op == JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
gc::AllocKind kind = GuessObjectGCKind(pn_count, false); gc::AllocKind kind = GuessObjectGCKind(pn_count, false);
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, kind); JSObject *obj = NewBuiltinClassInstance(cx, &js_ObjectClass, kind);
if (!obj) if (!obj)
return false; return false;
@ -7092,7 +7092,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
JSObject *obj = NULL; JSObject *obj = NULL;
if (!cg->hasSharps() && cg->compileAndGo()) { if (!cg->hasSharps() && cg->compileAndGo()) {
gc::AllocKind kind = GuessObjectGCKind(pn->pn_count, false); gc::AllocKind kind = GuessObjectGCKind(pn->pn_count, false);
obj = NewBuiltinClassInstance(cx, &ObjectClass, kind); obj = NewBuiltinClassInstance(cx, &js_ObjectClass, kind);
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
} }

Просмотреть файл

@ -75,7 +75,7 @@ using namespace js;
using namespace js::gc; using namespace js::gc;
using namespace js::types; using namespace js::types;
/* Forward declarations for ErrorClass's initializer. */ /* Forward declarations for js_ErrorClass's initializer. */
static JSBool static JSBool
Exception(JSContext *cx, uintN argc, Value *vp); Exception(JSContext *cx, uintN argc, Value *vp);
@ -89,7 +89,7 @@ static JSBool
exn_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, exn_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
JSObject **objp); JSObject **objp);
Class js::ErrorClass = { Class js_ErrorClass = {
js_Error_str, js_Error_str,
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_CACHED_PROTO(JSProto_Error), JSCLASS_HAS_CACHED_PROTO(JSProto_Error),
@ -263,99 +263,113 @@ GetStackTraceValueBuffer(JSExnPrivate *priv)
return (jsval *)(priv->stackElems + priv->stackDepth); return (jsval *)(priv->stackElems + priv->stackDepth);
} }
struct SuppressErrorsGuard static JSBool
{
JSContext *cx;
JSErrorReporter prevReporter;
JSExceptionState *prevState;
SuppressErrorsGuard(JSContext *cx)
: cx(cx),
prevReporter(JS_SetErrorReporter(cx, NULL)),
prevState(JS_SaveExceptionState(cx))
{}
~SuppressErrorsGuard()
{
JS_RestoreExceptionState(cx, prevState);
JS_SetErrorReporter(cx, prevReporter);
}
};
struct AppendArg {
Vector<Value> &values;
AppendArg(Vector<Value> &values) : values(values) {}
bool operator()(uintN, Value *vp) {
return values.append(*vp);
}
};
static bool
InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message, InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
JSString *filename, uintN lineno, JSErrorReport *report, intN exnType) JSString *filename, uintN lineno, JSErrorReport *report, intN exnType)
{ {
JS_ASSERT(exnObject->isError()); JSSecurityCallbacks *callbacks;
JS_ASSERT(!exnObject->getPrivate()); CheckAccessOp checkAccess;
JSErrorReporter older;
JSExceptionState *state;
jsid callerid;
size_t stackDepth, valueCount, size;
JSBool overflow;
JSExnPrivate *priv;
JSStackTraceElem *elem;
jsval *values;
JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx); JS_ASSERT(exnObject->getClass() == &js_ErrorClass);
CheckAccessOp checkAccess = callbacks
? Valueify(callbacks->checkObjectAccess)
: NULL;
Vector<JSStackTraceElem> frames(cx); /*
Vector<Value> values(cx); * Prepare stack trace data.
{ *
SuppressErrorsGuard seg(cx); * Set aside any error reporter for cx and save its exception state
for (FrameRegsIter i(cx); !i.done(); ++i) { * so we can suppress any checkAccess failures. Such failures should stop
/* * the backtrace procedure, not result in a failure of this constructor.
* An exception object stores stack values from 'fp' which may be */
* in a different compartment from 'exnObject'. Engine compartment callbacks = JS_GetSecurityCallbacks(cx);
* invariants require such values to be wrapped. A simpler solution checkAccess = callbacks
* is to just cut off the backtrace at compartment boundaries. ? Valueify(callbacks->checkObjectAccess)
* Also, avoid exposing values from different security principals. : NULL;
*/ older = JS_SetErrorReporter(cx, NULL);
StackFrame *fp = i.fp(); state = JS_SaveExceptionState(cx);
if (fp->compartment() != cx->compartment)
callerid = ATOM_TO_JSID(cx->runtime->atomState.callerAtom);
stackDepth = 0;
valueCount = 0;
FrameRegsIter firstPass(cx);
for (; !firstPass.done(); ++firstPass) {
StackFrame *fp = firstPass.fp();
if (fp->compartment() != cx->compartment)
break;
if (fp->isNonEvalFunctionFrame()) {
Value v = NullValue();
if (checkAccess &&
!checkAccess(cx, &fp->callee(), callerid, JSACC_READ, &v)) {
break; break;
if (checkAccess && fp->isNonEvalFunctionFrame()) {
Value v = NullValue();
jsid callerid = ATOM_TO_JSID(cx->runtime->atomState.callerAtom);
if (!checkAccess(cx, &fp->callee(), callerid, JSACC_READ, &v))
break;
}
if (!frames.growBy(1))
return false;
JSStackTraceElem &frame = frames.back();
if (fp->isNonEvalFunctionFrame()) {
frame.funName = fp->fun()->atom ? fp->fun()->atom : cx->runtime->emptyString;
frame.argc = fp->numActualArgs();
if (!fp->forEachCanonicalActualArg(AppendArg(values)))
return false;
} else {
frame.funName = NULL;
frame.argc = 0;
}
if (fp->isScriptFrame()) {
frame.filename = fp->script()->filename;
frame.ulineno = js_FramePCToLineNumber(cx, fp, i.pc());
} else {
frame.ulineno = 0;
frame.filename = NULL;
} }
valueCount += fp->numActualArgs();
} }
++stackDepth;
} }
JS_RestoreExceptionState(cx, state);
JS_SetErrorReporter(cx, older);
/* Do not need overflow check: the vm stack is already bigger. */ size = offsetof(JSExnPrivate, stackElems);
JS_STATIC_ASSERT(sizeof(JSStackTraceElem) <= sizeof(StackFrame)); overflow = (stackDepth > ((size_t)-1 - size) / sizeof(JSStackTraceElem));
size += stackDepth * sizeof(JSStackTraceElem);
size_t nbytes = offsetof(JSExnPrivate, stackElems) + overflow |= (valueCount > ((size_t)-1 - size) / sizeof(jsval));
frames.length() * sizeof(JSStackTraceElem) + size += valueCount * sizeof(jsval);
values.length() * sizeof(Value); if (overflow) {
js_ReportAllocationOverflow(cx);
JSExnPrivate *priv = (JSExnPrivate *)cx->malloc_(nbytes); return JS_FALSE;
}
priv = (JSExnPrivate *)cx->malloc_(size);
if (!priv) if (!priv)
return false; return JS_FALSE;
/*
* We initialize errorReport with a copy of report after setting the
* private slot, to prevent GC accessing a junk value we clear the field
* here.
*/
priv->errorReport = NULL;
priv->message = message;
priv->filename = filename;
priv->lineno = lineno;
priv->stackDepth = stackDepth;
priv->exnType = exnType;
values = GetStackTraceValueBuffer(priv);
elem = priv->stackElems;
for (FrameRegsIter iter(cx); iter != firstPass; ++iter) {
StackFrame *fp = iter.fp();
if (fp->compartment() != cx->compartment)
break;
if (!fp->isNonEvalFunctionFrame()) {
elem->funName = NULL;
elem->argc = 0;
} else {
elem->funName = fp->fun()->atom
? fp->fun()->atom
: cx->runtime->emptyString;
elem->argc = fp->numActualArgs();
fp->forEachCanonicalActualArg(CopyTo(Valueify(values)));
values += elem->argc;
}
elem->ulineno = 0;
elem->filename = NULL;
if (fp->isScriptFrame()) {
elem->filename = fp->script()->filename;
elem->ulineno = js_FramePCToLineNumber(cx, fp, iter.pc());
}
++elem;
}
JS_ASSERT(priv->stackElems + stackDepth == elem);
JS_ASSERT(GetStackTraceValueBuffer(priv) + valueCount == values);
exnObject->setPrivate(priv);
if (report) { if (report) {
/* /*
@ -366,28 +380,12 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
*/ */
priv->errorReport = CopyErrorReport(cx, report); priv->errorReport = CopyErrorReport(cx, report);
if (!priv->errorReport) { if (!priv->errorReport) {
cx->free_(priv); /* The finalizer realeases priv since it is in the private slot. */
return false; return JS_FALSE;
} }
} else {
priv->errorReport = NULL;
} }
priv->message = message; return JS_TRUE;
priv->filename = filename;
priv->lineno = lineno;
priv->stackDepth = frames.length();
priv->exnType = exnType;
JSStackTraceElem *framesDest = priv->stackElems;
Value *valuesDest = reinterpret_cast<Value *>(framesDest + frames.length());
JS_ASSERT(valuesDest == Valueify(GetStackTraceValueBuffer(priv)));
PodCopy(framesDest, frames.begin(), frames.length());
PodCopy(valuesDest, values.begin(), values.length());
exnObject->setPrivate(priv);
return true;
} }
static inline JSExnPrivate * static inline JSExnPrivate *
@ -431,9 +429,12 @@ exn_trace(JSTracer *trc, JSObject *obj)
static void static void
exn_finalize(JSContext *cx, JSObject *obj) exn_finalize(JSContext *cx, JSObject *obj)
{ {
if (JSExnPrivate *priv = GetExnPrivate(obj)) { JSExnPrivate *priv;
if (JSErrorReport *report = priv->errorReport)
cx->free_(report); priv = GetExnPrivate(obj);
if (priv) {
if (priv->errorReport)
cx->free_(priv->errorReport);
cx->free_(priv); cx->free_(priv);
} }
} }
@ -520,7 +521,7 @@ js_ErrorFromException(JSContext *cx, jsval exn)
if (JSVAL_IS_PRIMITIVE(exn)) if (JSVAL_IS_PRIMITIVE(exn))
return NULL; return NULL;
obj = JSVAL_TO_OBJECT(exn); obj = JSVAL_TO_OBJECT(exn);
if (!obj->isError()) if (obj->getClass() != &js_ErrorClass)
return NULL; return NULL;
priv = GetExnPrivate(obj); priv = GetExnPrivate(obj);
if (!priv) if (!priv)
@ -703,8 +704,6 @@ enum {
static JSBool static JSBool
Exception(JSContext *cx, uintN argc, Value *vp) Exception(JSContext *cx, uintN argc, Value *vp)
{ {
CallArgs args = CallArgsFromVp(argc, vp);
/* /*
* ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
* called as functions, without operator new. But as we do not give * called as functions, without operator new. But as we do not give
@ -712,28 +711,36 @@ Exception(JSContext *cx, uintN argc, Value *vp)
* NewNativeClassInstance to find the class prototype, we must get the * NewNativeClassInstance to find the class prototype, we must get the
* class prototype ourselves. * class prototype ourselves.
*/ */
JSObject &callee = vp[0].toObject();
Value protov; Value protov;
jsid protoAtom = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom); if (!callee.getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), &protov))
if (!args.callee().getProperty(cx, protoAtom, &protov)) return JS_FALSE;
return false;
if (!protov.isObject()) { if (!protov.isObject()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE, "Error"); JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE, "Error");
return false; return JS_FALSE;
} }
JSObject *errProto = &protov.toObject(); JSObject *errProto = &protov.toObject();
JSObject *obj = NewNativeClassInstance(cx, &ErrorClass, errProto, errProto->getParent()); JSObject *obj = NewNativeClassInstance(cx, &js_ErrorClass, errProto, errProto->getParent());
if (!obj) if (!obj)
return false; return JS_FALSE;
/*
* If it's a new object of class Exception, then null out the private
* data so that the finalizer doesn't attempt to free it.
*/
if (obj->getClass() == &js_ErrorClass)
obj->setPrivate(NULL);
/* Set the 'message' property. */ /* Set the 'message' property. */
Value *argv = vp + 2;
JSString *message; JSString *message;
if (args.argc() != 0 && !args[0].isUndefined()) { if (argc != 0 && !argv[0].isUndefined()) {
message = js_ValueToString(cx, args[0]); message = js_ValueToString(cx, argv[0]);
if (!message) if (!message)
return false; return JS_FALSE;
args[0].setString(message); argv[0].setString(message);
} else { } else {
message = NULL; message = NULL;
} }
@ -745,16 +752,16 @@ Exception(JSContext *cx, uintN argc, Value *vp)
/* Set the 'fileName' property. */ /* Set the 'fileName' property. */
JSString *filename; JSString *filename;
if (args.argc() > 1) { if (argc > 1) {
filename = js_ValueToString(cx, args[1]); filename = js_ValueToString(cx, argv[1]);
if (!filename) if (!filename)
return false; return JS_FALSE;
args[1].setString(filename); argv[1].setString(filename);
} else { } else {
if (!iter.done()) { if (!iter.done()) {
filename = FilenameToString(cx, iter.fp()->script()->filename); filename = FilenameToString(cx, iter.fp()->script()->filename);
if (!filename) if (!filename)
return false; return JS_FALSE;
} else { } else {
filename = cx->runtime->emptyString; filename = cx->runtime->emptyString;
} }
@ -762,19 +769,21 @@ Exception(JSContext *cx, uintN argc, Value *vp)
/* Set the 'lineNumber' property. */ /* Set the 'lineNumber' property. */
uint32_t lineno; uint32_t lineno;
if (args.argc() > 2) { if (argc > 2) {
if (!ValueToECMAUint32(cx, args[2], &lineno)) if (!ValueToECMAUint32(cx, argv[2], &lineno))
return false; return JS_FALSE;
} else { } else {
lineno = iter.done() ? 0 : js_FramePCToLineNumber(cx, iter.fp(), iter.pc()); lineno = iter.done() ? 0 : js_FramePCToLineNumber(cx, iter.fp(), iter.pc());
} }
intN exnType = args.callee().getReservedSlot(JSSLOT_ERROR_EXNTYPE).toInt32(); intN exnType = callee.getReservedSlot(JSSLOT_ERROR_EXNTYPE).toInt32();
if (!InitExnPrivate(cx, obj, message, filename, lineno, NULL, exnType)) if (obj->getClass() == &js_ErrorClass &&
return false; !InitExnPrivate(cx, obj, message, filename, lineno, NULL, exnType)) {
return JS_FALSE;
}
args.rval().setObject(*obj); vp->setObject(*obj);
return true; return JS_TRUE;
} }
/* /*
@ -1010,7 +1019,7 @@ InitErrorClass(JSContext *cx, GlobalObject *global, intN type, JSObject &proto)
{ {
JSProtoKey key = GetExceptionProtoKey(type); JSProtoKey key = GetExceptionProtoKey(type);
JSAtom *name = cx->runtime->atomState.classAtoms[key]; JSAtom *name = cx->runtime->atomState.classAtoms[key];
JSObject *errorProto = global->createBlankPrototypeInheriting(cx, &ErrorClass, proto); JSObject *errorProto = global->createBlankPrototypeInheriting(cx, &js_ErrorClass, proto);
if (!errorProto) if (!errorProto)
return NULL; return NULL;
@ -1032,7 +1041,7 @@ InitErrorClass(JSContext *cx, GlobalObject *global, intN type, JSObject &proto)
} }
/* Create the corresponding constructor. */ /* Create the corresponding constructor. */
JSFunction *ctor = global->createConstructor(cx, Exception, &ErrorClass, name, 1); JSFunction *ctor = global->createConstructor(cx, Exception, &js_ErrorClass, name, 1);
if (!ctor) if (!ctor)
return NULL; return NULL;
ctor->setReservedSlot(JSSLOT_ERROR_EXNTYPE, Int32Value(int32(type))); ctor->setReservedSlot(JSSLOT_ERROR_EXNTYPE, Int32Value(int32(type)));
@ -1171,7 +1180,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
goto out; goto out;
tv[0] = OBJECT_TO_JSVAL(errProto); tv[0] = OBJECT_TO_JSVAL(errProto);
errObject = NewNativeClassInstance(cx, &ErrorClass, errProto, errProto->getParent()); errObject = NewNativeClassInstance(cx, &js_ErrorClass, errProto, errProto->getParent());
if (!errObject) { if (!errObject) {
ok = JS_FALSE; ok = JS_FALSE;
goto out; goto out;
@ -1255,7 +1264,7 @@ js_ReportUncaughtException(JSContext *cx)
} }
JSAutoByteString filename; JSAutoByteString filename;
if (!reportp && exnObject && exnObject->isError()) { if (!reportp && exnObject && exnObject->getClass() == &js_ErrorClass) {
if (!JS_GetProperty(cx, exnObject, js_message_str, &roots[2])) if (!JS_GetProperty(cx, exnObject, js_message_str, &roots[2]))
return false; return false;
if (JSVAL_IS_STRING(roots[2])) { if (JSVAL_IS_STRING(roots[2])) {
@ -1359,7 +1368,7 @@ js_CopyErrorObject(JSContext *cx, JSObject *errobj, JSObject *scope)
JSObject *proto; JSObject *proto;
if (!js_GetClassPrototype(cx, scope->getGlobal(), GetExceptionProtoKey(copy->exnType), &proto)) if (!js_GetClassPrototype(cx, scope->getGlobal(), GetExceptionProtoKey(copy->exnType), &proto))
return NULL; return NULL;
JSObject *copyobj = NewNativeClassInstance(cx, &ErrorClass, proto, proto->getParent()); JSObject *copyobj = NewNativeClassInstance(cx, &js_ErrorClass, proto, proto->getParent());
copyobj->setPrivate(copy); copyobj->setPrivate(copy);
autoFree.p = NULL; autoFree.p = NULL;
return copyobj; return copyobj;

Просмотреть файл

@ -46,6 +46,14 @@
#include "jsobj.h" #include "jsobj.h"
extern js::Class js_ErrorClass;
inline bool
JSObject::isError() const
{
return clasp == &js_ErrorClass;
}
/* /*
* Initialize the exception constructor/prototype hierarchy. * Initialize the exception constructor/prototype hierarchy.
*/ */

Просмотреть файл

@ -216,8 +216,8 @@ ArgumentsObject::create(JSContext *cx, uint32 argc, JSObject &callee)
/* Can't fail from here on, so initialize everything in argsobj. */ /* Can't fail from here on, so initialize everything in argsobj. */
obj->init(cx, callee.getFunctionPrivate()->inStrictMode() obj->init(cx, callee.getFunctionPrivate()->inStrictMode()
? &StrictArgumentsObjectClass ? &StrictArgumentsObject::jsClass
: &NormalArgumentsObjectClass, : &NormalArgumentsObject::jsClass,
type, proto->getParent(), NULL, false); type, proto->getParent(), NULL, false);
obj->setMap(emptyArgumentsShape); obj->setMap(emptyArgumentsShape);
@ -686,16 +686,18 @@ args_trace(JSTracer *trc, JSObject *obj)
MaybeMarkGenerator(trc, argsobj); MaybeMarkGenerator(trc, argsobj);
} }
namespace js {
/* /*
* The classes below collaborate to lazily reflect and synchronize actual * The classes below collaborate to lazily reflect and synchronize actual
* argument values, argument count, and callee function object stored in a * argument values, argument count, and callee function object stored in a
* StackFrame with their corresponding property values in the frame's * StackFrame with their corresponding property values in the frame's
* arguments object. * arguments object.
*/ */
Class js::NormalArgumentsObjectClass = { Class NormalArgumentsObject::jsClass = {
"Arguments", "Arguments",
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_RESERVED_SLOTS(NormalArgumentsObject::RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Object), JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
args_delProperty, args_delProperty,
@ -719,10 +721,10 @@ Class js::NormalArgumentsObjectClass = {
* arguments, so it is represented by a different class while sharing some * arguments, so it is represented by a different class while sharing some
* functionality. * functionality.
*/ */
Class js::StrictArgumentsObjectClass = { Class StrictArgumentsObject::jsClass = {
"Arguments", "Arguments",
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_RESERVED_SLOTS(StrictArgumentsObject::RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Object), JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
args_delProperty, args_delProperty,
@ -741,11 +743,13 @@ Class js::StrictArgumentsObjectClass = {
args_trace args_trace
}; };
}
/* /*
* A Declarative Environment object stores its active StackFrame pointer in * A Declarative Environment object stores its active StackFrame pointer in
* its private slot, just as Call and Arguments objects do. * its private slot, just as Call and Arguments objects do.
*/ */
Class js::DeclEnvClass = { Class js_DeclEnvClass = {
js_Object_str, js_Object_str,
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object), JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -807,7 +811,7 @@ NewDeclEnvObject(JSContext *cx, StackFrame *fp)
EmptyShape *emptyDeclEnvShape = EmptyShape::getEmptyDeclEnvShape(cx); EmptyShape *emptyDeclEnvShape = EmptyShape::getEmptyDeclEnvShape(cx);
if (!emptyDeclEnvShape) if (!emptyDeclEnvShape)
return NULL; return NULL;
envobj->init(cx, &DeclEnvClass, &emptyTypeObject, &fp->scopeChain(), fp, false); envobj->init(cx, &js_DeclEnvClass, &emptyTypeObject, &fp->scopeChain(), fp, false);
envobj->setMap(emptyDeclEnvShape); envobj->setMap(emptyDeclEnvShape);
return envobj; return envobj;
@ -948,11 +952,11 @@ js_PutCallObject(StackFrame *fp)
} }
} }
/* Clear private pointers to fp, which is about to go away. */ /* Clear private pointers to fp, which is about to go away (js_Invoke). */
if (js_IsNamedLambda(fun)) { if (js_IsNamedLambda(fun)) {
JSObject *env = callobj.getParent(); JSObject *env = callobj.getParent();
JS_ASSERT(env->isDeclEnv()); JS_ASSERT(env->getClass() == &js_DeclEnvClass);
JS_ASSERT(env->getPrivate() == fp); JS_ASSERT(env->getPrivate() == fp);
env->setPrivate(NULL); env->setPrivate(NULL);
} }
@ -1172,7 +1176,7 @@ call_trace(JSTracer *trc, JSObject *obj)
MaybeMarkGenerator(trc, obj); MaybeMarkGenerator(trc, obj);
} }
JS_PUBLIC_DATA(Class) js::CallClass = { JS_PUBLIC_DATA(Class) js_CallClass = {
"Call", "Call",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::CALL_RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(JSObject::CALL_RESERVED_SLOTS) |
@ -1462,7 +1466,7 @@ ResolveInterpretedFunctionPrototype(JSContext *cx, JSObject *obj)
JSObject *objProto; JSObject *objProto;
if (!js_GetClassPrototype(cx, parent, JSProto_Object, &objProto)) if (!js_GetClassPrototype(cx, parent, JSProto_Object, &objProto))
return NULL; return NULL;
JSObject *proto = NewNativeClassInstance(cx, &ObjectClass, objProto, parent); JSObject *proto = NewNativeClassInstance(cx, &js_ObjectClass, objProto, parent);
if (!proto || !proto->setSingletonType(cx)) if (!proto || !proto->setSingletonType(cx))
return NULL; return NULL;
@ -1714,7 +1718,7 @@ fun_finalize(JSContext *cx, JSObject *obj)
* does not bloat every instance, only those on which reserved slots are set, * does not bloat every instance, only those on which reserved slots are set,
* and those on which ad-hoc properties are defined. * and those on which ad-hoc properties are defined.
*/ */
JS_PUBLIC_DATA(Class) js::FunctionClass = { JS_PUBLIC_DATA(Class) js_FunctionClass = {
js_Function_str, js_Function_str,
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
JSCLASS_HAS_RESERVED_SLOTS(JSFunction::CLASS_RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(JSFunction::CLASS_RESERVED_SLOTS) |
@ -1827,7 +1831,7 @@ js_fun_call(JSContext *cx, uintN argc, Value *vp)
Value fval = vp[1]; Value fval = vp[1];
if (!js_IsCallable(fval)) { if (!js_IsCallable(fval)) {
ReportIncompatibleMethod(cx, vp, &FunctionClass); ReportIncompatibleMethod(cx, vp, &js_FunctionClass);
return false; return false;
} }
@ -1864,7 +1868,7 @@ js_fun_apply(JSContext *cx, uintN argc, Value *vp)
/* Step 1. */ /* Step 1. */
Value fval = vp[1]; Value fval = vp[1];
if (!js_IsCallable(fval)) { if (!js_IsCallable(fval)) {
ReportIncompatibleMethod(cx, vp, &FunctionClass); ReportIncompatibleMethod(cx, vp, &js_FunctionClass);
return false; return false;
} }
@ -2073,7 +2077,7 @@ fun_bind(JSContext *cx, uintN argc, Value *vp)
/* Step 2. */ /* Step 2. */
if (!js_IsCallable(thisv)) { if (!js_IsCallable(thisv)) {
ReportIncompatibleMethod(cx, vp, &FunctionClass); ReportIncompatibleMethod(cx, vp, &js_FunctionClass);
return false; return false;
} }
@ -2366,7 +2370,7 @@ ThrowTypeError(JSContext *cx, uintN argc, Value *vp)
JSObject * JSObject *
js_InitFunctionClass(JSContext *cx, JSObject *obj) js_InitFunctionClass(JSContext *cx, JSObject *obj)
{ {
JSObject *proto = js_InitClass(cx, obj, NULL, &FunctionClass, Function, 1, JSObject *proto = js_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,
NULL, function_methods, NULL, NULL); NULL, function_methods, NULL, NULL);
if (!proto) if (!proto)
return NULL; return NULL;
@ -2473,7 +2477,7 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
* The cloned function object does not need the extra JSFunction members * The cloned function object does not need the extra JSFunction members
* beyond JSObject as it points to fun via the private slot. * beyond JSObject as it points to fun via the private slot.
*/ */
clone = NewNativeClassInstance(cx, &FunctionClass, proto, parent); clone = NewNativeClassInstance(cx, &js_FunctionClass, proto, parent);
if (!clone) if (!clone)
return NULL; return NULL;

Просмотреть файл

@ -170,7 +170,7 @@ struct JSFunction : public JSObject_Slots2
private: private:
/* /*
* FunctionClass reserves two slots, which are free in JSObject::fslots * js_FunctionClass reserves two slots, which are free in JSObject::fslots
* without requiring dslots allocation. Null closures that can be joined to * without requiring dslots allocation. Null closures that can be joined to
* a compiler-created function object use the first one to hold a mutable * a compiler-created function object use the first one to hold a mutable
* methodAtom() state variable, needed for correct foo.caller handling. * methodAtom() state variable, needed for correct foo.caller handling.
@ -255,6 +255,22 @@ struct JSFunction : public JSObject_Slots2
JS_FN(name, fastcall, nargs, flags) JS_FN(name, fastcall, nargs, flags)
#endif #endif
extern JS_PUBLIC_DATA(js::Class) js_CallClass;
extern JS_PUBLIC_DATA(js::Class) js_FunctionClass;
extern JS_FRIEND_DATA(js::Class) js_DeclEnvClass;
inline bool
JSObject::isCall() const
{
return getClass() == &js_CallClass;
}
inline bool
JSObject::isFunction() const
{
return getClass() == &js_FunctionClass;
}
inline JSFunction * inline JSFunction *
JSObject::getFunctionPrivate() const JSObject::getFunctionPrivate() const
{ {
@ -315,7 +331,7 @@ IsNativeFunction(const js::Value &v, Native native)
/* /*
* When we have an object of a builtin class, we don't quite know what its * When we have an object of a builtin class, we don't quite know what its
* valueOf/toString methods are, since these methods may have been overwritten * valueOf/toString methods are, since these methods may have been overwritten
* or shadowed. However, we can still do better than the general case by * or shadowed. However, we can still do better than js_TryMethod by
* hard-coding the necessary properties for us to find the native we expect. * hard-coding the necessary properties for us to find the native we expect.
* *
* TODO: a per-thread shape-based cache would be faster and simpler. * TODO: a per-thread shape-based cache would be faster and simpler.

Просмотреть файл

@ -1572,8 +1572,9 @@ GCMarker::~GCMarker()
} }
void void
GCMarker::delayMarkingChildren(const Cell *cell) GCMarker::delayMarkingChildren(const void *thing)
{ {
const Cell *cell = reinterpret_cast<const Cell *>(thing);
ArenaHeader *aheader = cell->arenaHeader(); ArenaHeader *aheader = cell->arenaHeader();
if (aheader->getMarkingDelay()->link) { if (aheader->getMarkingDelay()->link) {
/* Arena already scheduled to be marked later */ /* Arena already scheduled to be marked later */

Просмотреть файл

@ -58,10 +58,12 @@
#include "jsfun.h" #include "jsfun.h"
#include "jsgcstats.h" #include "jsgcstats.h"
#include "jscell.h" #include "jscell.h"
#include "jsxml.h"
struct JSCompartment; struct JSCompartment;
extern "C" void
js_TraceXML(JSTracer *trc, JSXML* thing);
#if JS_STACK_GROWTH_DIRECTION > 0 #if JS_STACK_GROWTH_DIRECTION > 0
# define JS_CHECK_STACK_SIZE(limit, lval) ((jsuword)(lval) < limit) # define JS_CHECK_STACK_SIZE(limit, lval) ((jsuword)(lval) < limit)
#else #else
@ -1511,7 +1513,7 @@ struct GCMarker : public JSTracer {
color = newColor; color = newColor;
} }
void delayMarkingChildren(const js::gc::Cell *cell); void delayMarkingChildren(const void *thing);
void markDelayedChildren(); void markDelayedChildren();

Просмотреть файл

@ -66,7 +66,7 @@
* MarkString, etc. These functions check if an object is in the compartment * MarkString, etc. These functions check if an object is in the compartment
* currently being GCed. If it is, they call PushMarkStack. Roots are pushed * currently being GCed. If it is, they call PushMarkStack. Roots are pushed
* this way as well as pointers traversed inside trace hooks (for things like * this way as well as pointers traversed inside trace hooks (for things like
* IteratorClass). It it always valid to call a MarkX function instead of * js_IteratorClass). It it always valid to call a MarkX function instead of
* PushMarkStack, although it may be slower. * PushMarkStack, although it may be slower.
* *
* The MarkX functions also handle non-GC object traversal. In this case, they * The MarkX functions also handle non-GC object traversal. In this case, they
@ -708,7 +708,7 @@ ScanObject(GCMarker *gcmarker, JSObject *obj)
*/ */
Class *clasp = obj->getClass(); Class *clasp = obj->getClass();
if (clasp->trace) { if (clasp->trace) {
if (clasp == &ArrayClass) { if (clasp == &js_ArrayClass) {
if (obj->getDenseArrayInitializedLength() > LARGE_OBJECT_CHUNK_SIZE) { if (obj->getDenseArrayInitializedLength() > LARGE_OBJECT_CHUNK_SIZE) {
if (!gcmarker->largeStack.push(LargeMarkItem(obj))) if (!gcmarker->largeStack.push(LargeMarkItem(obj)))
clasp->trace(gcmarker, obj); clasp->trace(gcmarker, obj);

Просмотреть файл

@ -4385,7 +4385,7 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSScript *script)
return; return;
/* Strawman object to add properties to and watch for duplicates. */ /* Strawman object to add properties to and watch for duplicates. */
JSObject *baseobj = NewBuiltinClassInstance(cx, &ObjectClass, gc::FINALIZE_OBJECT16); JSObject *baseobj = NewBuiltinClassInstance(cx, &js_ObjectClass, gc::FINALIZE_OBJECT16);
if (!baseobj) { if (!baseobj) {
if (type->newScript) if (type->newScript)
type->clearNewScript(cx); type->clearNewScript(cx);

Просмотреть файл

@ -300,7 +300,7 @@ GetScopeChainFull(JSContext *cx, StackFrame *fp, JSObject *blockChain)
* to, but not including, that prototype. * to, but not including, that prototype.
*/ */
limitClone = &fp->scopeChain(); limitClone = &fp->scopeChain();
while (limitClone->isWith()) while (limitClone->getClass() == &js_WithClass)
limitClone = limitClone->getParent(); limitClone = limitClone->getParent();
JS_ASSERT(limitClone); JS_ASSERT(limitClone);
@ -402,8 +402,10 @@ CallThisObjectHook(JSContext *cx, JSObject *obj, Value *argv)
return thisp; return thisp;
} }
namespace js {
void void
js::ReportIncompatibleMethod(JSContext *cx, Value *vp, Class *clasp) ReportIncompatibleMethod(JSContext *cx, Value *vp, Class *clasp)
{ {
Value &thisv = vp[1]; Value &thisv = vp[1];
@ -411,11 +413,11 @@ js::ReportIncompatibleMethod(JSContext *cx, Value *vp, Class *clasp)
if (thisv.isObject()) { if (thisv.isObject()) {
JS_ASSERT(thisv.toObject().getClass() != clasp); JS_ASSERT(thisv.toObject().getClass() != clasp);
} else if (thisv.isString()) { } else if (thisv.isString()) {
JS_ASSERT(clasp != &StringClass); JS_ASSERT(clasp != &js_StringClass);
} else if (thisv.isNumber()) { } else if (thisv.isNumber()) {
JS_ASSERT(clasp != &NumberClass); JS_ASSERT(clasp != &js_NumberClass);
} else if (thisv.isBoolean()) { } else if (thisv.isBoolean()) {
JS_ASSERT(clasp != &BooleanClass); JS_ASSERT(clasp != &js_BooleanClass);
} else { } else {
JS_ASSERT(thisv.isUndefined() || thisv.isNull()); JS_ASSERT(thisv.isUndefined() || thisv.isNull());
} }
@ -446,7 +448,7 @@ js::ReportIncompatibleMethod(JSContext *cx, Value *vp, Class *clasp)
* The alert should display "true". * The alert should display "true".
*/ */
bool bool
js::BoxNonStrictThis(JSContext *cx, const CallReceiver &call) BoxNonStrictThis(JSContext *cx, const CallReceiver &call)
{ {
/* /*
* Check for SynthesizeFrame poisoning and fast constructors which * Check for SynthesizeFrame poisoning and fast constructors which
@ -474,6 +476,8 @@ js::BoxNonStrictThis(JSContext *cx, const CallReceiver &call)
return true; return true;
} }
}
#if JS_HAS_NO_SUCH_METHOD #if JS_HAS_NO_SUCH_METHOD
const uint32 JSSLOT_FOUND_FUNCTION = 0; const uint32 JSSLOT_FOUND_FUNCTION = 0;
@ -520,8 +524,8 @@ Class js_NoSuchMethodClass = {
* call by name, and args is an Array containing this invocation's actual * call by name, and args is an Array containing this invocation's actual
* parameters. * parameters.
*/ */
bool JSBool
js::OnUnknownMethod(JSContext *cx, Value *vp) js_OnUnknownMethod(JSContext *cx, Value *vp)
{ {
JS_ASSERT(!vp[1].isPrimitive()); JS_ASSERT(!vp[1].isPrimitive());
@ -582,8 +586,10 @@ NoSuchMethod(JSContext *cx, uintN argc, Value *vp)
#endif /* JS_HAS_NO_SUCH_METHOD */ #endif /* JS_HAS_NO_SUCH_METHOD */
namespace js {
JS_REQUIRES_STACK bool JS_REQUIRES_STACK bool
js::RunScript(JSContext *cx, JSScript *script, StackFrame *fp) RunScript(JSContext *cx, JSScript *script, StackFrame *fp)
{ {
JS_ASSERT(script); JS_ASSERT(script);
JS_ASSERT(fp == cx->fp()); JS_ASSERT(fp == cx->fp());
@ -620,8 +626,8 @@ js::RunScript(JSContext *cx, JSScript *script, StackFrame *fp)
* required arguments, allocate declared local variables, and pop everything * required arguments, allocate declared local variables, and pop everything
* when done. Then push the return value. * when done. Then push the return value.
*/ */
bool JS_REQUIRES_STACK bool
js::InvokeKernel(JSContext *cx, const CallArgs &argsRef, MaybeConstruct construct) InvokeKernel(JSContext *cx, const CallArgs &argsRef, MaybeConstruct construct)
{ {
/* N.B. Must be kept in sync with InvokeSessionGuard::start/invoke */ /* N.B. Must be kept in sync with InvokeSessionGuard::start/invoke */
@ -642,7 +648,7 @@ js::InvokeKernel(JSContext *cx, const CallArgs &argsRef, MaybeConstruct construc
Class *clasp = callee.getClass(); Class *clasp = callee.getClass();
/* Invoke non-functions. */ /* Invoke non-functions. */
if (JS_UNLIKELY(clasp != &FunctionClass)) { if (JS_UNLIKELY(clasp != &js_FunctionClass)) {
#if JS_HAS_NO_SUCH_METHOD #if JS_HAS_NO_SUCH_METHOD
if (JS_UNLIKELY(clasp == &js_NoSuchMethodClass)) if (JS_UNLIKELY(clasp == &js_NoSuchMethodClass))
return NoSuchMethod(cx, args.argc(), args.base()); return NoSuchMethod(cx, args.argc(), args.base());
@ -661,6 +667,22 @@ js::InvokeKernel(JSContext *cx, const CallArgs &argsRef, MaybeConstruct construc
if (fun->isNative()) if (fun->isNative())
return CallJSNative(cx, fun->u.n.native, args); return CallJSNative(cx, fun->u.n.native, args);
/* Handle the empty-script special case. */
JSScript *script = fun->script();
if (JS_UNLIKELY(script->isEmpty())) {
if (construct) {
bool newType = cx->typeInferenceEnabled() && cx->fp()->isScriptFrame() &&
UseNewType(cx, cx->fp()->script(), cx->regs().pc);
JSObject *obj = js_CreateThisForFunction(cx, &callee, newType);
if (!obj)
return false;
args.rval().setObject(*obj);
} else {
args.rval().setUndefined();
}
return true;
}
TypeMonitorCall(cx, args, construct); TypeMonitorCall(cx, args, construct);
/* Get pointer to new frame/slots, prepare arguments. */ /* Get pointer to new frame/slots, prepare arguments. */
@ -677,7 +699,7 @@ js::InvokeKernel(JSContext *cx, const CallArgs &argsRef, MaybeConstruct construc
JSBool ok; JSBool ok;
{ {
AutoPreserveEnumerators preserve(cx); AutoPreserveEnumerators preserve(cx);
ok = RunScript(cx, fun->script(), fp); ok = RunScript(cx, script, fp);
} }
args.rval() = fp->returnValue(); args.rval() = fp->returnValue();
@ -711,13 +733,13 @@ InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &this
if (!calleev.isObject()) if (!calleev.isObject())
break; break;
JSObject &callee = calleev.toObject(); JSObject &callee = calleev.toObject();
if (callee.getClass() != &FunctionClass) if (callee.getClass() != &js_FunctionClass)
break; break;
JSFunction *fun = callee.getFunctionPrivate(); JSFunction *fun = callee.getFunctionPrivate();
if (fun->isNative()) if (fun->isNative())
break; break;
script_ = fun->script(); script_ = fun->script();
if (fun->isHeavyweight()) if (fun->isHeavyweight() || script_->isEmpty())
break; break;
/* /*
@ -784,8 +806,8 @@ InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &this
} }
bool bool
js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, uintN argc, Value *argv, Invoke(JSContext *cx, const Value &thisv, const Value &fval, uintN argc, Value *argv,
Value *rval) Value *rval)
{ {
LeaveTrace(cx); LeaveTrace(cx);
@ -817,7 +839,7 @@ js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, uintN argc, Val
} }
bool bool
js::InvokeConstructor(JSContext *cx, const Value &fval, uintN argc, Value *argv, Value *rval) InvokeConstructor(JSContext *cx, const Value &fval, uintN argc, Value *argv, Value *rval)
{ {
LeaveTrace(cx); LeaveTrace(cx);
@ -837,8 +859,8 @@ js::InvokeConstructor(JSContext *cx, const Value &fval, uintN argc, Value *argv,
} }
bool bool
js::InvokeGetterOrSetter(JSContext *cx, JSObject *obj, const Value &fval, uintN argc, Value *argv, InvokeGetterOrSetter(JSContext *cx, JSObject *obj, const Value &fval, uintN argc, Value *argv,
Value *rval) Value *rval)
{ {
LeaveTrace(cx); LeaveTrace(cx);
@ -880,8 +902,8 @@ InitSharpSlots(JSContext *cx, StackFrame *fp)
#endif #endif
bool bool
js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const Value &thisv, ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const Value &thisv,
ExecuteType type, StackFrame *evalInFrame, Value *result) ExecuteType type, StackFrame *evalInFrame, Value *result)
{ {
JS_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG); JS_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG);
@ -922,7 +944,7 @@ js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const V
} }
bool bool
js::Execute(JSContext *cx, JSScript *script, JSObject &scopeChainArg, Value *rval) Execute(JSContext *cx, JSScript *script, JSObject &scopeChainArg, Value *rval)
{ {
/* The scope chain could be anything, so innerize just in case. */ /* The scope chain could be anything, so innerize just in case. */
JSObject *scopeChain = &scopeChainArg; JSObject *scopeChain = &scopeChainArg;
@ -952,7 +974,7 @@ js::Execute(JSContext *cx, JSScript *script, JSObject &scopeChainArg, Value *rva
} }
bool bool
js::CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs) CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs)
{ {
JSObject *obj2; JSObject *obj2;
JSProperty *prop; JSProperty *prop;
@ -1023,7 +1045,7 @@ js::CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs)
} }
JSBool JSBool
js::HasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp) HasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
{ {
Class *clasp = obj->getClass(); Class *clasp = obj->getClass();
if (clasp->hasInstance) if (clasp->hasInstance)
@ -1034,7 +1056,7 @@ js::HasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
} }
bool bool
js::LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, JSBool *result) LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, JSBool *result)
{ {
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
if (JS_UNLIKELY(lval.isObject() && lval.toObject().isXML()) || if (JS_UNLIKELY(lval.isObject() && lval.toObject().isXML()) ||
@ -1105,7 +1127,7 @@ js::LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, JSBool *re
} }
bool bool
js::StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref, JSBool *equal) StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref, JSBool *equal)
{ {
Value lval = lref, rval = rref; Value lval = lref, rval = rref;
if (SameType(lval, rval)) { if (SameType(lval, rval)) {
@ -1157,7 +1179,7 @@ IsNaN(const Value &v)
} }
bool bool
js::SameValue(JSContext *cx, const Value &v1, const Value &v2, JSBool *same) SameValue(JSContext *cx, const Value &v1, const Value &v2, JSBool *same)
{ {
if (IsNegativeZero(v1)) { if (IsNegativeZero(v1)) {
*same = IsNegativeZero(v2); *same = IsNegativeZero(v2);
@ -1175,7 +1197,7 @@ js::SameValue(JSContext *cx, const Value &v1, const Value &v2, JSBool *same)
} }
JSType JSType
js::TypeOfValue(JSContext *cx, const Value &vref) TypeOfValue(JSContext *cx, const Value &vref)
{ {
Value v = vref; Value v = vref;
if (v.isNumber()) if (v.isNumber())
@ -1192,16 +1214,16 @@ js::TypeOfValue(JSContext *cx, const Value &vref)
return JSTYPE_BOOLEAN; return JSTYPE_BOOLEAN;
} }
bool JS_REQUIRES_STACK bool
js::InvokeConstructorKernel(JSContext *cx, const CallArgs &argsRef) InvokeConstructorKernel(JSContext *cx, const CallArgs &argsRef)
{ {
JS_ASSERT(!FunctionClass.construct); JS_ASSERT(!js_FunctionClass.construct);
CallArgs args = argsRef; CallArgs args = argsRef;
if (args.calleev().isObject()) { if (args.calleev().isObject()) {
JSObject *callee = &args.callee(); JSObject *callee = &args.callee();
Class *clasp = callee->getClass(); Class *clasp = callee->getClass();
if (clasp == &FunctionClass) { if (clasp == &js_FunctionClass) {
JSFunction *fun = callee->getFunctionPrivate(); JSFunction *fun = callee->getFunctionPrivate();
if (fun->isConstructor()) { if (fun->isConstructor()) {
@ -1233,8 +1255,8 @@ error:
} }
bool bool
js::InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value &fval, InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value &fval,
uintN argc, Value *argv, Value *rval) uintN argc, Value *argv, Value *rval)
{ {
LeaveTrace(cx); LeaveTrace(cx);
@ -1251,7 +1273,7 @@ js::InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value
Class *clasp = callee.getClass(); Class *clasp = callee.getClass();
JSFunction *fun; JSFunction *fun;
bool ok; bool ok;
if (clasp == &FunctionClass && (fun = callee.getFunctionPrivate())->isConstructor()) { if (clasp == &js_FunctionClass && (fun = callee.getFunctionPrivate())->isConstructor()) {
args.thisv().setMagicWithObjectOrNullPayload(thisobj); args.thisv().setMagicWithObjectOrNullPayload(thisobj);
Probes::calloutBegin(cx, fun); Probes::calloutBegin(cx, fun);
ok = CallJSNativeConstructor(cx, fun->u.n.native, args); ok = CallJSNativeConstructor(cx, fun->u.n.native, args);
@ -1269,7 +1291,7 @@ js::InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value
} }
bool bool
js::ValueToId(JSContext *cx, const Value &v, jsid *idp) ValueToId(JSContext *cx, const Value &v, jsid *idp)
{ {
int32_t i; int32_t i;
if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) { if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) {
@ -1290,12 +1312,14 @@ js::ValueToId(JSContext *cx, const Value &v, jsid *idp)
return js_ValueToStringId(cx, v, idp); return js_ValueToStringId(cx, v, idp);
} }
} /* namespace js */
/* /*
* Enter the new with scope using an object at sp[-1] and associate the depth * Enter the new with scope using an object at sp[-1] and associate the depth
* of the with block with sp + stackIndex. * of the with block with sp + stackIndex.
*/ */
static bool JS_REQUIRES_STACK JSBool
EnterWith(JSContext *cx, jsint stackIndex, JSOp op, size_t oplen) js_EnterWith(JSContext *cx, jsint stackIndex, JSOp op, size_t oplen)
{ {
StackFrame *fp = cx->fp(); StackFrame *fp = cx->fp();
Value *sp = cx->regs().sp; Value *sp = cx->regs().sp;
@ -1329,47 +1353,55 @@ EnterWith(JSContext *cx, jsint stackIndex, JSOp op, size_t oplen)
return JS_TRUE; return JS_TRUE;
} }
static void JS_REQUIRES_STACK void
LeaveWith(JSContext *cx) js_LeaveWith(JSContext *cx)
{ {
JSObject *withobj; JSObject *withobj;
withobj = &cx->fp()->scopeChain(); withobj = &cx->fp()->scopeChain();
JS_ASSERT(withobj->getClass() == &WithClass); JS_ASSERT(withobj->getClass() == &js_WithClass);
JS_ASSERT(withobj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp())); JS_ASSERT(withobj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()));
JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0); JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
withobj->setPrivate(NULL); withobj->setPrivate(NULL);
cx->fp()->setScopeChainNoCallObj(*withobj->getParent()); cx->fp()->setScopeChainNoCallObj(*withobj->getParent());
} }
bool JS_REQUIRES_STACK Class *
js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, int stackDepth) js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth)
{ {
return (obj.isWith() || obj.isBlock()) && Class *clasp;
obj.getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()) &&
OBJ_BLOCK_DEPTH(cx, &obj) >= stackDepth; clasp = obj->getClass();
if ((clasp == &js_WithClass || clasp == &js_BlockClass) &&
obj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()) &&
OBJ_BLOCK_DEPTH(cx, obj) >= stackDepth) {
return clasp;
}
return NULL;
} }
/* /*
* Unwind block and scope chains to match the given depth. The function sets * Unwind block and scope chains to match the given depth. The function sets
* fp->sp on return to stackDepth. * fp->sp on return to stackDepth.
*/ */
bool JS_REQUIRES_STACK JSBool
js::UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind) js_UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind)
{ {
Class *clasp;
JS_ASSERT(stackDepth >= 0); JS_ASSERT(stackDepth >= 0);
JS_ASSERT(cx->fp()->base() + stackDepth <= cx->regs().sp); JS_ASSERT(cx->fp()->base() + stackDepth <= cx->regs().sp);
StackFrame *fp = cx->fp(); StackFrame *fp = cx->fp();
for (;;) { for (;;) {
JSObject &scopeChain = fp->scopeChain(); clasp = js_IsActiveWithOrBlock(cx, &fp->scopeChain(), stackDepth);
if (!IsActiveWithOrBlock(cx, scopeChain, stackDepth)) if (!clasp)
break; break;
if (scopeChain.isBlock()) { if (clasp == &js_BlockClass) {
/* Don't fail until after we've updated all stacks. */ /* Don't fail until after we've updated all stacks. */
normalUnwind &= js_PutBlockObject(cx, normalUnwind); normalUnwind &= js_PutBlockObject(cx, normalUnwind);
} else { } else {
LeaveWith(cx); js_LeaveWith(cx);
} }
} }
@ -1377,14 +1409,8 @@ js::UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind)
return normalUnwind; return normalUnwind;
} }
/* JSBool
* Find the results of incrementing or decrementing *vp. For pre-increments, js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, Value *vp, Value *vp2)
* both *vp and *vp2 will contain the result on return. For post-increments,
* vp will contain the original value converted to a number and vp2 will get
* the result. Both vp and vp2 must be roots.
*/
static bool
DoIncDec(JSContext *cx, const JSCodeSpec *cs, Value *vp, Value *vp2)
{ {
if (cs->format & JOF_POST) { if (cs->format & JOF_POST) {
double d; double d;
@ -1659,7 +1685,7 @@ JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEDEC_LENGTH);
static inline bool static inline bool
IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval) IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval)
{ {
if (iterobj->isIterator()) { if (iterobj->getClass() == &js_IteratorClass) {
NativeIterator *ni = iterobj->getNativeIterator(); NativeIterator *ni = iterobj->getNativeIterator();
if (ni->isKeyIter()) { if (ni->isKeyIter()) {
*cond = (ni->props_cursor < ni->props_end); *cond = (ni->props_cursor < ni->props_end);
@ -1675,7 +1701,7 @@ IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval)
static inline bool static inline bool
IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval) IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
{ {
if (iterobj->isIterator()) { if (iterobj->getClass() == &js_IteratorClass) {
NativeIterator *ni = iterobj->getNativeIterator(); NativeIterator *ni = iterobj->getNativeIterator();
if (ni->isKeyIter()) { if (ni->isKeyIter()) {
JS_ASSERT(ni->props_cursor < ni->props_end); JS_ASSERT(ni->props_cursor < ni->props_end);
@ -1707,8 +1733,10 @@ TypeCheckNextBytecode(JSContext *cx, JSScript *script, unsigned n, const FrameRe
#endif #endif
} }
JS_NEVER_INLINE bool namespace js {
js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
JS_REQUIRES_STACK JS_NEVER_INLINE bool
Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
{ {
#ifdef MOZ_TRACEVIS #ifdef MOZ_TRACEVIS
TraceVisStateObj tvso(cx, S_INTERP); TraceVisStateObj tvso(cx, S_INTERP);
@ -2343,12 +2371,15 @@ BEGIN_CASE(JSOP_POPN)
OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj) OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
<= (size_t) (regs.sp - regs.fp()->base())); <= (size_t) (regs.sp - regs.fp()->base()));
for (obj = &regs.fp()->scopeChain(); obj; obj = obj->getParent()) { for (obj = &regs.fp()->scopeChain(); obj; obj = obj->getParent()) {
if (!obj->isBlock() || !obj->isWith()) Class *clasp = obj->getClass();
if (clasp != &js_BlockClass && clasp != &js_WithClass)
continue; continue;
if (obj->getPrivate() != js_FloatingFrameIfGenerator(cx, regs.fp())) if (obj->getPrivate() != js_FloatingFrameIfGenerator(cx, regs.fp()))
break; break;
JS_ASSERT(regs.fp()->base() + OBJ_BLOCK_DEPTH(cx, obj) JS_ASSERT(regs.fp()->base() + OBJ_BLOCK_DEPTH(cx, obj)
+ (obj->isBlock() ? OBJ_BLOCK_COUNT(cx, obj) : 1) + ((clasp == &js_BlockClass)
? OBJ_BLOCK_COUNT(cx, obj)
: 1)
<= regs.sp); <= regs.sp);
} }
#endif #endif
@ -2361,7 +2392,7 @@ BEGIN_CASE(JSOP_POPV)
END_CASE(JSOP_POPV) END_CASE(JSOP_POPV)
BEGIN_CASE(JSOP_ENTERWITH) BEGIN_CASE(JSOP_ENTERWITH)
if (!EnterWith(cx, -1, JSOP_ENTERWITH, JSOP_ENTERWITH_LENGTH)) if (!js_EnterWith(cx, -1, JSOP_ENTERWITH, JSOP_ENTERWITH_LENGTH))
goto error; goto error;
/* /*
@ -2379,7 +2410,7 @@ END_CASE(JSOP_ENTERWITH)
BEGIN_CASE(JSOP_LEAVEWITH) BEGIN_CASE(JSOP_LEAVEWITH)
JS_ASSERT(regs.sp[-1].toObject() == regs.fp()->scopeChain()); JS_ASSERT(regs.sp[-1].toObject() == regs.fp()->scopeChain());
regs.sp--; regs.sp--;
LeaveWith(cx); js_LeaveWith(cx);
END_CASE(JSOP_LEAVEWITH) END_CASE(JSOP_LEAVEWITH)
BEGIN_CASE(JSOP_RETURN) BEGIN_CASE(JSOP_RETURN)
@ -2420,7 +2451,7 @@ BEGIN_CASE(JSOP_STOP)
inline_return: inline_return:
{ {
JS_ASSERT(!regs.fp()->hasImacropc()); JS_ASSERT(!regs.fp()->hasImacropc());
JS_ASSERT(!IsActiveWithOrBlock(cx, regs.fp()->scopeChain(), 0)); JS_ASSERT(!js_IsActiveWithOrBlock(cx, &regs.fp()->scopeChain(), 0));
interpReturnOK = ScriptEpilogue(cx, regs.fp(), interpReturnOK); interpReturnOK = ScriptEpilogue(cx, regs.fp(), interpReturnOK);
/* The JIT inlines ScriptEpilogue. */ /* The JIT inlines ScriptEpilogue. */
@ -3499,7 +3530,7 @@ do_incop:
} else { } else {
/* We need an extra root for the result. */ /* We need an extra root for the result. */
PUSH_NULL(); PUSH_NULL();
if (!DoIncDec(cx, cs, &regs.sp[-2], &regs.sp[-1])) if (!js_DoIncDec(cx, cs, &regs.sp[-2], &regs.sp[-1]))
goto error; goto error;
{ {
@ -3571,7 +3602,7 @@ BEGIN_CASE(JSOP_LOCALINC)
PUSH_INT32(tmp + incr2); PUSH_INT32(tmp + incr2);
} else { } else {
PUSH_COPY(*vp); PUSH_COPY(*vp);
if (!DoIncDec(cx, &js_CodeSpec[op], &regs.sp[-1], vp)) if (!js_DoIncDec(cx, &js_CodeSpec[op], &regs.sp[-1], vp))
goto error; goto error;
TypeScript::MonitorOverflow(cx, script, regs.pc); TypeScript::MonitorOverflow(cx, script, regs.pc);
} }
@ -3777,7 +3808,7 @@ BEGIN_CASE(JSOP_CALLPROP)
if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) { if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) {
LOAD_ATOM(0, atom); LOAD_ATOM(0, atom);
regs.sp[-2].setString(atom); regs.sp[-2].setString(atom);
if (!OnUnknownMethod(cx, regs.sp - 2)) if (!js_OnUnknownMethod(cx, regs.sp - 2))
goto error; goto error;
} }
#endif #endif
@ -4053,10 +4084,10 @@ BEGIN_CASE(JSOP_CALLELEM)
#if JS_HAS_NO_SUCH_METHOD #if JS_HAS_NO_SUCH_METHOD
if (JS_UNLIKELY(regs.sp[-2].isPrimitive()) && thisv.isObject()) { if (JS_UNLIKELY(regs.sp[-2].isPrimitive()) && thisv.isObject()) {
/* For OnUnknownMethod, sp[-2] is the index, and sp[-1] is the object missing it. */ /* For js_OnUnknownMethod, sp[-2] is the index, and sp[-1] is the object missing it. */
regs.sp[-2] = regs.sp[-1]; regs.sp[-2] = regs.sp[-1];
regs.sp[-1].setObject(*thisObj); regs.sp[-1].setObject(*thisObj);
if (!OnUnknownMethod(cx, regs.sp - 2)) if (!js_OnUnknownMethod(cx, regs.sp - 2))
goto error; goto error;
} else } else
#endif #endif
@ -4292,7 +4323,7 @@ BEGIN_CASE(JSOP_CALLNAME)
} else { } else {
shape = (Shape *)prop; shape = (Shape *)prop;
JSObject *normalized = obj; JSObject *normalized = obj;
if (normalized->getClass() == &WithClass && !shape->hasDefaultGetter()) if (normalized->getClass() == &js_WithClass && !shape->hasDefaultGetter())
normalized = js_UnwrapWithObject(cx, normalized); normalized = js_UnwrapWithObject(cx, normalized);
NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval); NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval);
} }
@ -4990,7 +5021,7 @@ BEGIN_CASE(JSOP_LAMBDA)
const Value &lref = regs.sp[-1]; const Value &lref = regs.sp[-1];
JS_ASSERT(lref.isObject()); JS_ASSERT(lref.isObject());
JSObject *obj2 = &lref.toObject(); JSObject *obj2 = &lref.toObject();
JS_ASSERT(obj2->isObject()); JS_ASSERT(obj2->getClass() == &js_ObjectClass);
#endif #endif
fun->setMethodAtom(script->getAtom(GET_FULL_INDEX(pc2 - regs.pc))); fun->setMethodAtom(script->getAtom(GET_FULL_INDEX(pc2 - regs.pc)));
@ -5207,7 +5238,7 @@ BEGIN_CASE(JSOP_NEWINIT)
obj = NewDenseEmptyArray(cx); obj = NewDenseEmptyArray(cx);
} else { } else {
gc::AllocKind kind = GuessObjectGCKind(0, false); gc::AllocKind kind = GuessObjectGCKind(0, false);
obj = NewBuiltinClassInstance(cx, &ObjectClass, kind); obj = NewBuiltinClassInstance(cx, &js_ObjectClass, kind);
} }
if (!obj) if (!obj)
@ -5793,7 +5824,7 @@ BEGIN_CASE(JSOP_ENDFILTER)
bool cond = !regs.sp[-1].isMagic(); bool cond = !regs.sp[-1].isMagic();
if (cond) { if (cond) {
/* Exit the "with" block left from the previous iteration. */ /* Exit the "with" block left from the previous iteration. */
LeaveWith(cx); js_LeaveWith(cx);
} }
if (!js_StepXMLListFilter(cx, cond)) if (!js_StepXMLListFilter(cx, cond))
goto error; goto error;
@ -5803,7 +5834,7 @@ BEGIN_CASE(JSOP_ENDFILTER)
* temporaries. * temporaries.
*/ */
JS_ASSERT(IsXML(regs.sp[-1])); JS_ASSERT(IsXML(regs.sp[-1]));
if (!EnterWith(cx, -2, JSOP_ENDFILTER, JSOP_ENDFILTER_LENGTH)) if (!js_EnterWith(cx, -2, JSOP_ENDFILTER, JSOP_ENDFILTER_LENGTH))
goto error; goto error;
regs.sp--; regs.sp--;
len = GET_JUMP_OFFSET(regs.pc); len = GET_JUMP_OFFSET(regs.pc);
@ -5930,9 +5961,10 @@ BEGIN_CASE(JSOP_ENTERBLOCK)
* static scope. * static scope.
*/ */
JSObject *obj2 = &regs.fp()->scopeChain(); JSObject *obj2 = &regs.fp()->scopeChain();
while (obj2->isWith()) Class *clasp;
while ((clasp = obj2->getClass()) == &js_WithClass)
obj2 = obj2->getParent(); obj2 = obj2->getParent();
if (obj2->isBlock() && if (clasp == &js_BlockClass &&
obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, regs.fp())) { obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, regs.fp())) {
JSObject *youngestProto = obj2->getProto(); JSObject *youngestProto = obj2->getProto();
JS_ASSERT(youngestProto->isStaticBlock()); JS_ASSERT(youngestProto->isStaticBlock());
@ -6197,7 +6229,7 @@ END_CASE(JSOP_ARRAYPUSH)
*/ */
regs.pc = (script)->main() + tn->start + tn->length; regs.pc = (script)->main() + tn->start + tn->length;
JSBool ok = UnwindScope(cx, tn->stackDepth, JS_TRUE); JSBool ok = js_UnwindScope(cx, tn->stackDepth, JS_TRUE);
JS_ASSERT(regs.sp == regs.fp()->base() + tn->stackDepth); JS_ASSERT(regs.sp == regs.fp()->base() + tn->stackDepth);
if (!ok) { if (!ok) {
/* /*
@ -6267,12 +6299,12 @@ END_CASE(JSOP_ARRAYPUSH)
forced_return: forced_return:
/* /*
* Unwind the scope making sure that interpReturnOK stays false even when * Unwind the scope making sure that interpReturnOK stays false even when
* UnwindScope returns true. * js_UnwindScope returns true.
* *
* When a trap handler returns JSTRAP_RETURN, we jump here with * When a trap handler returns JSTRAP_RETURN, we jump here with
* interpReturnOK set to true bypassing any finally blocks. * interpReturnOK set to true bypassing any finally blocks.
*/ */
interpReturnOK &= UnwindScope(cx, 0, interpReturnOK || cx->isExceptionPending()); interpReturnOK &= js_UnwindScope(cx, 0, interpReturnOK || cx->isExceptionPending());
JS_ASSERT(regs.sp == regs.fp()->base()); JS_ASSERT(regs.sp == regs.fp()->base());
if (entryFrame != regs.fp()) if (entryFrame != regs.fp())
@ -6306,7 +6338,7 @@ END_CASE(JSOP_ARRAYPUSH)
#endif #endif
JS_ASSERT_IF(!regs.fp()->isGeneratorFrame(), JS_ASSERT_IF(!regs.fp()->isGeneratorFrame(),
!IsActiveWithOrBlock(cx, regs.fp()->scopeChain(), 0)); !js_IsActiveWithOrBlock(cx, &regs.fp()->scopeChain(), 0));
#ifdef JS_METHODJIT #ifdef JS_METHODJIT
/* /*
@ -6326,3 +6358,5 @@ END_CASE(JSOP_ARRAYPUSH)
} }
goto error; goto error;
} }
} /* namespace js */

Просмотреть файл

@ -360,19 +360,34 @@ class InterpreterFrames {
const InterruptEnablerBase &enabler; const InterruptEnablerBase &enabler;
}; };
} /* namespace js */
extern JS_REQUIRES_STACK JSBool
js_EnterWith(JSContext *cx, jsint stackIndex, JSOp op, size_t oplen);
extern JS_REQUIRES_STACK void
js_LeaveWith(JSContext *cx);
/*
* Find the results of incrementing or decrementing *vp. For pre-increments,
* both *vp and *vp2 will contain the result on return. For post-increments,
* vp will contain the original value converted to a number and vp2 will get
* the result. Both vp and vp2 must be roots.
*/
extern JSBool
js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, js::Value *vp, js::Value *vp2);
/* /*
* Unwind block and scope chains to match the given depth. The function sets * Unwind block and scope chains to match the given depth. The function sets
* fp->sp on return to stackDepth. * fp->sp on return to stackDepth.
*/ */
extern bool extern JS_REQUIRES_STACK JSBool
UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind); js_UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind);
extern bool extern JSBool
OnUnknownMethod(JSContext *cx, js::Value *vp); js_OnUnknownMethod(JSContext *cx, js::Value *vp);
extern bool extern JS_REQUIRES_STACK js::Class *
IsActiveWithOrBlock(JSContext *cx, JSObject &obj, int stackDepth); js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth);
} /* namespace js */
#endif /* jsinterp_h___ */ #endif /* jsinterp_h___ */

Просмотреть файл

@ -182,7 +182,7 @@ class PrimitiveBehavior<JSString *> {
public: public:
static inline bool isType(const Value &v) { return v.isString(); } static inline bool isType(const Value &v) { return v.isString(); }
static inline JSString *extract(const Value &v) { return v.toString(); } static inline JSString *extract(const Value &v) { return v.toString(); }
static inline Class *getClass() { return &StringClass; } static inline Class *getClass() { return &js_StringClass; }
}; };
template<> template<>
@ -190,7 +190,7 @@ class PrimitiveBehavior<bool> {
public: public:
static inline bool isType(const Value &v) { return v.isBoolean(); } static inline bool isType(const Value &v) { return v.isBoolean(); }
static inline bool extract(const Value &v) { return v.toBoolean(); } static inline bool extract(const Value &v) { return v.toBoolean(); }
static inline Class *getClass() { return &BooleanClass; } static inline Class *getClass() { return &js_BooleanClass; }
}; };
template<> template<>
@ -198,7 +198,7 @@ class PrimitiveBehavior<double> {
public: public:
static inline bool isType(const Value &v) { return v.isNumber(); } static inline bool isType(const Value &v) { return v.isNumber(); }
static inline double extract(const Value &v) { return v.toNumber(); } static inline double extract(const Value &v) { return v.toNumber(); }
static inline Class *getClass() { return &NumberClass; } static inline Class *getClass() { return &js_NumberClass; }
}; };
} // namespace detail } // namespace detail

Просмотреть файл

@ -90,7 +90,7 @@ static void iterator_finalize(JSContext *cx, JSObject *obj);
static void iterator_trace(JSTracer *trc, JSObject *obj); static void iterator_trace(JSTracer *trc, JSObject *obj);
static JSObject *iterator_iterator(JSContext *cx, JSObject *obj, JSBool keysonly); static JSObject *iterator_iterator(JSContext *cx, JSObject *obj, JSBool keysonly);
Class js::IteratorClass = { Class js_IteratorClass = {
"Iterator", "Iterator",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_PRIVATE |
JSCLASS_CONCURRENT_FINALIZER | JSCLASS_CONCURRENT_FINALIZER |
@ -130,7 +130,7 @@ NativeIterator::mark(JSTracer *trc)
static void static void
iterator_finalize(JSContext *cx, JSObject *obj) iterator_finalize(JSContext *cx, JSObject *obj)
{ {
JS_ASSERT(obj->isIterator()); JS_ASSERT(obj->getClass() == &js_IteratorClass);
NativeIterator *ni = obj->getNativeIterator(); NativeIterator *ni = obj->getNativeIterator();
if (ni) { if (ni) {
@ -418,12 +418,12 @@ NewIteratorObject(JSContext *cx, uintN flags)
EmptyShape *emptyEnumeratorShape = EmptyShape::getEmptyEnumeratorShape(cx); EmptyShape *emptyEnumeratorShape = EmptyShape::getEmptyEnumeratorShape(cx);
if (!emptyEnumeratorShape) if (!emptyEnumeratorShape)
return NULL; return NULL;
obj->init(cx, &IteratorClass, &types::emptyTypeObject, NULL, NULL, false); obj->init(cx, &js_IteratorClass, &types::emptyTypeObject, NULL, NULL, false);
obj->setMap(emptyEnumeratorShape); obj->setMap(emptyEnumeratorShape);
return obj; return obj;
} }
return NewBuiltinClassInstance(cx, &IteratorClass); return NewBuiltinClassInstance(cx, &js_IteratorClass);
} }
NativeIterator * NativeIterator *
@ -571,7 +571,7 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
if (obj) { if (obj) {
/* Enumerate Iterator.prototype directly. */ /* Enumerate Iterator.prototype directly. */
JSIteratorOp op = obj->getClass()->ext.iteratorObject; JSIteratorOp op = obj->getClass()->ext.iteratorObject;
if (op && (obj->getClass() != &IteratorClass || obj->getNativeIterator())) { if (op && (obj->getClass() != &js_IteratorClass || obj->getNativeIterator())) {
JSObject *iterobj = op(cx, obj, !(flags & JSITER_FOREACH)); JSObject *iterobj = op(cx, obj, !(flags & JSITER_FOREACH));
if (!iterobj) if (!iterobj)
return false; return false;
@ -718,8 +718,8 @@ iterator_next(JSContext *cx, uintN argc, Value *vp)
JSObject *obj = ToObject(cx, &vp[1]); JSObject *obj = ToObject(cx, &vp[1]);
if (!obj) if (!obj)
return false; return false;
if (!obj->isIterator()) { if (obj->getClass() != &js_IteratorClass) {
ReportIncompatibleMethod(cx, vp, &IteratorClass); ReportIncompatibleMethod(cx, vp, &js_IteratorClass);
return false; return false;
} }
@ -792,7 +792,8 @@ js_CloseIterator(JSContext *cx, JSObject *obj)
{ {
cx->iterValue.setMagic(JS_NO_ITER_VALUE); cx->iterValue.setMagic(JS_NO_ITER_VALUE);
if (obj->isIterator()) { Class *clasp = obj->getClass();
if (clasp == &js_IteratorClass) {
/* Remove enumerators from the active list, which is a stack. */ /* Remove enumerators from the active list, which is a stack. */
NativeIterator *ni = obj->getNativeIterator(); NativeIterator *ni = obj->getNativeIterator();
@ -811,7 +812,7 @@ js_CloseIterator(JSContext *cx, JSObject *obj)
} }
} }
#if JS_HAS_GENERATORS #if JS_HAS_GENERATORS
else if (obj->isGenerator()) { else if (clasp == &js_GeneratorClass) {
return CloseGenerator(cx, obj); return CloseGenerator(cx, obj);
} }
#endif #endif
@ -942,7 +943,7 @@ js_IteratorMore(JSContext *cx, JSObject *iterobj, Value *rval)
{ {
/* Fast path for native iterators */ /* Fast path for native iterators */
NativeIterator *ni = NULL; NativeIterator *ni = NULL;
if (iterobj->isIterator()) { if (iterobj->getClass() == &js_IteratorClass) {
/* Key iterators are handled by fast-paths. */ /* Key iterators are handled by fast-paths. */
ni = iterobj->getNativeIterator(); ni = iterobj->getNativeIterator();
if (ni) { if (ni) {
@ -970,7 +971,7 @@ js_IteratorMore(JSContext *cx, JSObject *iterobj, Value *rval)
return false; return false;
if (!Invoke(cx, ObjectValue(*iterobj), *rval, 0, NULL, rval)) { if (!Invoke(cx, ObjectValue(*iterobj), *rval, 0, NULL, rval)) {
/* Check for StopIteration. */ /* Check for StopIteration. */
if (!cx->isExceptionPending() || !IsStopIteration(cx->getPendingException())) if (!cx->isExceptionPending() || !js_ValueIsStopIteration(cx->getPendingException()))
return false; return false;
cx->clearPendingException(); cx->clearPendingException();
@ -999,7 +1000,7 @@ JSBool
js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval) js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
{ {
/* Fast path for native iterators */ /* Fast path for native iterators */
if (iterobj->isIterator()) { if (iterobj->getClass() == &js_IteratorClass) {
/* /*
* Implement next directly as all the methods of the native iterator are * Implement next directly as all the methods of the native iterator are
* read-only and permanent. * read-only and permanent.
@ -1038,11 +1039,11 @@ js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
static JSBool static JSBool
stopiter_hasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp) stopiter_hasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
{ {
*bp = IsStopIteration(*v); *bp = js_ValueIsStopIteration(*v);
return JS_TRUE; return JS_TRUE;
} }
Class js::StopIterationClass = { Class js_StopIterationClass = {
js_StopIteration_str, js_StopIteration_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration) | JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration) |
JSCLASS_FREEZE_PROTO, JSCLASS_FREEZE_PROTO,
@ -1110,7 +1111,7 @@ generator_trace(JSTracer *trc, JSObject *obj)
MarkStackRangeConservatively(trc, fp->slots(), gen->regs.sp); MarkStackRangeConservatively(trc, fp->slots(), gen->regs.sp);
} }
Class js::GeneratorClass = { Class js_GeneratorClass = {
js_Generator_str, js_Generator_str,
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Generator) | JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Generator) |
JSCLASS_IS_ANONYMOUS, JSCLASS_IS_ANONYMOUS,
@ -1149,7 +1150,7 @@ Class js::GeneratorClass = {
JS_REQUIRES_STACK JSObject * JS_REQUIRES_STACK JSObject *
js_NewGenerator(JSContext *cx) js_NewGenerator(JSContext *cx)
{ {
JSObject *obj = NewBuiltinClassInstance(cx, &GeneratorClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_GeneratorClass);
if (!obj) if (!obj)
return NULL; return NULL;
@ -1308,7 +1309,7 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
static JS_REQUIRES_STACK JSBool static JS_REQUIRES_STACK JSBool
CloseGenerator(JSContext *cx, JSObject *obj) CloseGenerator(JSContext *cx, JSObject *obj)
{ {
JS_ASSERT(obj->isGenerator()); JS_ASSERT(obj->getClass() == &js_GeneratorClass);
JSGenerator *gen = (JSGenerator *) obj->getPrivate(); JSGenerator *gen = (JSGenerator *) obj->getPrivate();
if (!gen) { if (!gen) {
@ -1333,8 +1334,8 @@ generator_op(JSContext *cx, JSGeneratorOp op, Value *vp, uintN argc)
JSObject *obj = ToObject(cx, &vp[1]); JSObject *obj = ToObject(cx, &vp[1]);
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
if (!obj->isGenerator()) { if (obj->getClass() != &js_GeneratorClass) {
ReportIncompatibleMethod(cx, vp, &GeneratorClass); ReportIncompatibleMethod(cx, vp, &js_GeneratorClass);
return JS_FALSE; return JS_FALSE;
} }
@ -1425,11 +1426,11 @@ static JSFunctionSpec generator_methods[] = {
static bool static bool
InitIteratorClass(JSContext *cx, GlobalObject *global) InitIteratorClass(JSContext *cx, GlobalObject *global)
{ {
JSObject *iteratorProto = global->createBlankPrototype(cx, &IteratorClass); JSObject *iteratorProto = global->createBlankPrototype(cx, &js_IteratorClass);
if (!iteratorProto) if (!iteratorProto)
return false; return false;
JSFunction *ctor = global->createConstructor(cx, Iterator, &IteratorClass, JSFunction *ctor = global->createConstructor(cx, Iterator, &js_IteratorClass,
CLASS_ATOM(cx, Iterator), 2); CLASS_ATOM(cx, Iterator), 2);
if (!ctor) if (!ctor)
return false; return false;
@ -1447,7 +1448,7 @@ static bool
InitGeneratorClass(JSContext *cx, GlobalObject *global) InitGeneratorClass(JSContext *cx, GlobalObject *global)
{ {
#if JS_HAS_GENERATORS #if JS_HAS_GENERATORS
JSObject *proto = global->createBlankPrototype(cx, &GeneratorClass); JSObject *proto = global->createBlankPrototype(cx, &js_GeneratorClass);
if (!proto) if (!proto)
return false; return false;
@ -1464,7 +1465,7 @@ InitGeneratorClass(JSContext *cx, GlobalObject *global)
static JSObject * static JSObject *
InitStopIterationClass(JSContext *cx, GlobalObject *global) InitStopIterationClass(JSContext *cx, GlobalObject *global)
{ {
JSObject *proto = global->createBlankPrototype(cx, &StopIterationClass); JSObject *proto = global->createBlankPrototype(cx, &js_StopIterationClass);
if (!proto || !proto->freeze(cx)) if (!proto || !proto->freeze(cx))
return NULL; return NULL;
@ -1472,7 +1473,7 @@ InitStopIterationClass(JSContext *cx, GlobalObject *global)
if (!DefineConstructorAndPrototype(cx, global, JSProto_StopIteration, proto, proto)) if (!DefineConstructorAndPrototype(cx, global, JSProto_StopIteration, proto, proto))
return NULL; return NULL;
MarkStandardClassInitializedNoProto(global, &StopIterationClass); MarkStandardClassInitializedNoProto(global, &js_StopIterationClass);
return proto; return proto;
} }

Просмотреть файл

@ -231,16 +231,16 @@ js_LiveFrameIfGenerator(js::StackFrame *fp)
#endif #endif
namespace js { extern js::Class js_GeneratorClass;
extern js::Class js_IteratorClass;
extern js::Class js_StopIterationClass;
static inline bool static inline bool
IsStopIteration(const js::Value &v) js_ValueIsStopIteration(const js::Value &v)
{ {
return v.isObject() && v.toObject().isStopIteration(); return v.isObject() && v.toObject().getClass() == &js_StopIterationClass;
} }
} /* namespace js */
extern JSObject * extern JSObject *
js_InitIteratorClasses(JSContext *cx, JSObject *obj); js_InitIteratorClasses(JSContext *cx, JSObject *obj);

Просмотреть файл

@ -106,7 +106,7 @@ MathCache::MathCache() {
JS_ASSERT(hash(-0.0) != hash(+0.0)); JS_ASSERT(hash(-0.0) != hash(+0.0));
} }
Class js::MathClass = { Class js_MathClass = {
js_Math_str, js_Math_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_Math), JSCLASS_HAS_CACHED_PROTO(JSProto_Math),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -865,7 +865,7 @@ js_IsMathFunction(JSNative native)
JSObject * JSObject *
js_InitMathClass(JSContext *cx, JSObject *obj) js_InitMathClass(JSContext *cx, JSObject *obj)
{ {
JSObject *Math = NewNonFunction<WithProto::Class>(cx, &MathClass, NULL, obj); JSObject *Math = NewNonFunction<WithProto::Class>(cx, &js_MathClass, NULL, obj);
if (!Math || !Math->setSingletonType(cx)) if (!Math || !Math->setSingletonType(cx))
return NULL; return NULL;
@ -879,7 +879,7 @@ js_InitMathClass(JSContext *cx, JSObject *obj)
if (!JS_DefineConstDoubles(cx, Math, math_constants)) if (!JS_DefineConstDoubles(cx, Math, math_constants))
return NULL; return NULL;
MarkStandardClassInitializedNoProto(obj, &MathClass); MarkStandardClassInitializedNoProto(obj, &js_MathClass);
return Math; return Math;
} }

Просмотреть файл

@ -82,6 +82,8 @@ class MathCache
* JS math functions. * JS math functions.
*/ */
extern js::Class js_MathClass;
extern JSObject * extern JSObject *
js_InitMathClass(JSContext *cx, JSObject *obj); js_InitMathClass(JSContext *cx, JSObject *obj);

Просмотреть файл

@ -559,7 +559,7 @@ static JSFunctionSpec number_functions[] = {
JS_FS_END JS_FS_END
}; };
Class js::NumberClass = { Class js_NumberClass = {
js_Number_str, js_Number_str,
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Number), JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Number),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -588,7 +588,7 @@ Number(JSContext *cx, uintN argc, Value *vp)
if (!isConstructing) if (!isConstructing)
return true; return true;
JSObject *obj = NewBuiltinClassInstance(cx, &NumberClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_NumberClass);
if (!obj) if (!obj)
return false; return false;
obj->setPrimitiveThis(vp[0]); obj->setPrimitiveThis(vp[0]);
@ -612,7 +612,7 @@ num_toSource(JSContext *cx, uintN argc, Value *vp)
} }
char buf[64]; char buf[64];
JS_snprintf(buf, sizeof buf, "(new %s(%s))", NumberClass.name, numStr); JS_snprintf(buf, sizeof buf, "(new %s(%s))", js_NumberClass.name, numStr);
JSString *str = js_NewStringCopyZ(cx, buf); JSString *str = js_NewStringCopyZ(cx, buf);
if (!str) if (!str)
return false; return false;
@ -1106,7 +1106,7 @@ js_InitNumberClass(JSContext *cx, JSObject *obj)
/* XXX must do at least once per new thread, so do it per JSContext... */ /* XXX must do at least once per new thread, so do it per JSContext... */
FIX_FPU(); FIX_FPU();
proto = js_InitClass(cx, obj, NULL, &NumberClass, Number, 1, proto = js_InitClass(cx, obj, NULL, &js_NumberClass, Number, 1,
NULL, number_methods, NULL, NULL); NULL, number_methods, NULL, NULL);
if (!proto || !(ctor = JS_GetConstructor(cx, proto))) if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
return NULL; return NULL;

Просмотреть файл

@ -160,6 +160,14 @@ FinishRuntimeNumberState(JSRuntime *rt);
} /* namespace js */ } /* namespace js */
/* Initialize the Number class, returning its prototype object. */ /* Initialize the Number class, returning its prototype object. */
extern js::Class js_NumberClass;
inline bool
JSObject::isNumber() const
{
return getClass() == &js_NumberClass;
}
extern JSObject * extern JSObject *
js_InitNumberClass(JSContext *cx, JSObject *obj); js_InitNumberClass(JSContext *cx, JSObject *obj);

Просмотреть файл

@ -115,7 +115,7 @@ using namespace js::types;
JS_FRIEND_DATA(js::Shape) Shape::sharedNonNative(SHAPELESS); JS_FRIEND_DATA(js::Shape) Shape::sharedNonNative(SHAPELESS);
Class js::ObjectClass = { Class js_ObjectClass = {
js_Object_str, js_Object_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_Object), JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -1800,7 +1800,7 @@ PropDesc::initFromPropertyDescriptor(const PropertyDescriptor &desc)
bool bool
PropDesc::makeObject(JSContext *cx) PropDesc::makeObject(JSContext *cx)
{ {
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_ObjectClass);
if (!obj) if (!obj)
return false; return false;
@ -2630,7 +2630,7 @@ obj_create(JSContext *cx, uintN argc, Value *vp)
* Use the callee's global as the parent of the new object to avoid dynamic * Use the callee's global as the parent of the new object to avoid dynamic
* scoping (i.e., using the caller's global). * scoping (i.e., using the caller's global).
*/ */
JSObject *obj = NewNonFunction<WithProto::Given>(cx, &ObjectClass, proto, JSObject *obj = NewNonFunction<WithProto::Given>(cx, &js_ObjectClass, proto,
vp->toObject().getGlobal()); vp->toObject().getGlobal());
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
@ -2913,8 +2913,8 @@ js_Object(JSContext *cx, uintN argc, Value *vp)
if (!obj) { if (!obj) {
/* Make an object whether this was called with 'new' or not. */ /* Make an object whether this was called with 'new' or not. */
JS_ASSERT(!argc || vp[2].isNull() || vp[2].isUndefined()); JS_ASSERT(!argc || vp[2].isNull() || vp[2].isUndefined());
gc::AllocKind kind = NewObjectGCKind(cx, &ObjectClass); gc::AllocKind kind = NewObjectGCKind(cx, &js_ObjectClass);
obj = NewBuiltinClassInstance(cx, &ObjectClass, kind); obj = NewBuiltinClassInstance(cx, &js_ObjectClass, kind);
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
TypeObject *type = GetTypeCallerInitObject(cx, JSProto_Object); TypeObject *type = GetTypeCallerInitObject(cx, JSProto_Object);
@ -2966,8 +2966,8 @@ js_CreateThis(JSContext *cx, JSObject *callee)
{ {
Class *clasp = callee->getClass(); Class *clasp = callee->getClass();
Class *newclasp = &ObjectClass; Class *newclasp = &js_ObjectClass;
if (clasp == &FunctionClass) { if (clasp == &js_FunctionClass) {
JSFunction *fun = callee->getFunctionPrivate(); JSFunction *fun = callee->getFunctionPrivate();
if (fun->isNative() && fun->u.n.clasp) if (fun->isNative() && fun->u.n.clasp)
newclasp = fun->u.n.clasp; newclasp = fun->u.n.clasp;
@ -3002,7 +3002,7 @@ CreateThisForFunctionWithType(JSContext *cx, types::TypeObject *type, JSObject *
return res; return res;
} }
gc::AllocKind kind = NewObjectGCKind(cx, &ObjectClass); gc::AllocKind kind = NewObjectGCKind(cx, &js_ObjectClass);
return NewObjectWithType(cx, type, parent, kind); return NewObjectWithType(cx, type, parent, kind);
} }
@ -3018,8 +3018,8 @@ js_CreateThisForFunctionWithProto(JSContext *cx, JSObject *callee, JSObject *pro
return NULL; return NULL;
res = CreateThisForFunctionWithType(cx, type, callee->getParent()); res = CreateThisForFunctionWithType(cx, type, callee->getParent());
} else { } else {
gc::AllocKind kind = NewObjectGCKind(cx, &ObjectClass); gc::AllocKind kind = NewObjectGCKind(cx, &js_ObjectClass);
res = NewNonFunction<WithProto::Class>(cx, &ObjectClass, proto, callee->getParent(), kind); res = NewNonFunction<WithProto::Class>(cx, &js_ObjectClass, proto, callee->getParent(), kind);
} }
if (res && cx->typeInferenceEnabled()) if (res && cx->typeInferenceEnabled())
@ -3065,8 +3065,8 @@ js_CreateThisForFunction(JSContext *cx, JSObject *callee, bool newType)
JSObject* FASTCALL JSObject* FASTCALL
js_Object_tn(JSContext* cx, JSObject* proto) js_Object_tn(JSContext* cx, JSObject* proto)
{ {
JS_ASSERT(!(ObjectClass.flags & JSCLASS_HAS_PRIVATE)); JS_ASSERT(!(js_ObjectClass.flags & JSCLASS_HAS_PRIVATE));
return NewObjectWithClassProto(cx, &ObjectClass, proto, FINALIZE_OBJECT8); return NewObjectWithClassProto(cx, &js_ObjectClass, proto, FINALIZE_OBJECT8);
} }
JS_DEFINE_TRCINFO_1(js_Object, JS_DEFINE_TRCINFO_1(js_Object,
@ -3078,7 +3078,7 @@ js_InitializerObject(JSContext* cx, JSObject *proto, JSObject *baseobj)
{ {
if (!baseobj) { if (!baseobj) {
gc::AllocKind kind = GuessObjectGCKind(0, false); gc::AllocKind kind = GuessObjectGCKind(0, false);
return NewObjectWithClassProto(cx, &ObjectClass, proto, kind); return NewObjectWithClassProto(cx, &js_ObjectClass, proto, kind);
} }
/* :FIXME: bug 637856 new Objects do not have the right type when created on trace. */ /* :FIXME: bug 637856 new Objects do not have the right type when created on trace. */
@ -3129,8 +3129,8 @@ js_CreateThisFromTrace(JSContext *cx, JSObject *ctor, uintN protoSlot)
return NULL; return NULL;
} }
gc::AllocKind kind = NewObjectGCKind(cx, &ObjectClass); gc::AllocKind kind = NewObjectGCKind(cx, &js_ObjectClass);
return NewNativeClassInstance(cx, &ObjectClass, proto, parent, kind); return NewNativeClassInstance(cx, &js_ObjectClass, proto, parent, kind);
} }
JS_DEFINE_CALLINFO_3(extern, CONSTRUCTOR_RETRY, js_CreateThisFromTrace, CONTEXT, OBJECT, UINTN, 0, JS_DEFINE_CALLINFO_3(extern, CONSTRUCTOR_RETRY, js_CreateThisFromTrace, CONTEXT, OBJECT, UINTN, 0,
nanojit::ACCSET_STORE_ANY) nanojit::ACCSET_STORE_ANY)
@ -3309,7 +3309,7 @@ with_ThisObject(JSContext *cx, JSObject *obj)
return obj->getWithThis(); return obj->getWithThis();
} }
Class js::WithClass = { Class js_WithClass = {
"With", "With",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS, JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS,
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -3359,7 +3359,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
StackFrame *priv = js_FloatingFrameIfGenerator(cx, cx->fp()); StackFrame *priv = js_FloatingFrameIfGenerator(cx, cx->fp());
obj->init(cx, &WithClass, type, parent, priv, false); obj->init(cx, &js_WithClass, type, parent, priv, false);
EmptyShape *emptyWithShape = EmptyShape::getEmptyWithShape(cx); EmptyShape *emptyWithShape = EmptyShape::getEmptyWithShape(cx);
if (!emptyWithShape) if (!emptyWithShape)
@ -3393,7 +3393,7 @@ js_NewBlockObject(JSContext *cx)
EmptyShape *emptyBlockShape = EmptyShape::getEmptyBlockShape(cx); EmptyShape *emptyBlockShape = EmptyShape::getEmptyBlockShape(cx);
if (!emptyBlockShape) if (!emptyBlockShape)
return NULL; return NULL;
blockObj->init(cx, &BlockClass, &emptyTypeObject, NULL, NULL, false); blockObj->init(cx, &js_BlockClass, &emptyTypeObject, NULL, NULL, false);
blockObj->setMap(emptyBlockShape); blockObj->setMap(emptyBlockShape);
return blockObj; return blockObj;
@ -3483,7 +3483,7 @@ block_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
} }
/* Values are in slots immediately following the class-reserved ones. */ /* Values are in slots immediately following the class-reserved ones. */
JS_ASSERT(obj->getSlot(JSSLOT_FREE(&BlockClass) + index) == *vp); JS_ASSERT(obj->getSlot(JSSLOT_FREE(&js_BlockClass) + index) == *vp);
return true; return true;
} }
@ -3516,7 +3516,7 @@ JSObject::defineBlockVariable(JSContext *cx, jsid id, intN index)
JS_ASSERT(isStaticBlock()); JS_ASSERT(isStaticBlock());
/* Use JSPROP_ENUMERATE to aid the disassembler. */ /* Use JSPROP_ENUMERATE to aid the disassembler. */
uint32 slot = JSSLOT_FREE(&BlockClass) + index; uint32 slot = JSSLOT_FREE(&js_BlockClass) + index;
const Shape *shape = addProperty(cx, id, const Shape *shape = addProperty(cx, id,
block_getProperty, block_setProperty, block_getProperty, block_setProperty,
slot, JSPROP_ENUMERATE | JSPROP_PERMANENT, slot, JSPROP_ENUMERATE | JSPROP_PERMANENT,
@ -3985,7 +3985,7 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
#endif #endif
Class js::BlockClass = { Class js_BlockClass = {
"Block", "Block",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_IS_ANONYMOUS, JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_IS_ANONYMOUS,
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -4000,7 +4000,7 @@ Class js::BlockClass = {
JSObject * JSObject *
js_InitObjectClass(JSContext *cx, JSObject *obj) js_InitObjectClass(JSContext *cx, JSObject *obj)
{ {
JSObject *proto = js_InitClass(cx, obj, NULL, &ObjectClass, js_Object, 1, JSObject *proto = js_InitClass(cx, obj, NULL, &js_ObjectClass, js_Object, 1,
object_props, object_methods, NULL, object_static_methods); object_props, object_methods, NULL, object_static_methods);
if (!proto) if (!proto)
return NULL; return NULL;
@ -4102,10 +4102,10 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt
* otherwise-uninitialized global. * otherwise-uninitialized global.
* *
* 3. NewObject allocating a JSFunction-sized GC-thing when clasp is * 3. NewObject allocating a JSFunction-sized GC-thing when clasp is
* &FunctionClass, not a JSObject-sized (smaller) GC-thing. * &js_FunctionClass, not a JSObject-sized (smaller) GC-thing.
* *
* The JS_NewObjectForGivenProto and JS_NewObject APIs also allow clasp to * The JS_NewObjectForGivenProto and JS_NewObject APIs also allow clasp to
* be &FunctionClass (we could break compatibility easily). But fixing * be &js_FunctionClass (we could break compatibility easily). But fixing
* (3) is not enough without addressing the bootstrapping dependency on (1) * (3) is not enough without addressing the bootstrapping dependency on (1)
* and (2). * and (2).
*/ */
@ -4124,7 +4124,7 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt
if (!proto->setSingletonType(cx)) if (!proto->setSingletonType(cx))
return NULL; return NULL;
if (clasp == &ArrayClass && !proto->makeDenseArraySlow(cx)) if (clasp == &js_ArrayClass && !proto->makeDenseArraySlow(cx))
return NULL; return NULL;
TypeObject *type = proto->getNewType(cx); TypeObject *type = proto->getNewType(cx);
@ -5098,7 +5098,7 @@ DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value,
if (!shape) { if (!shape) {
/* Add a new property, or replace an existing one of the same id. */ /* Add a new property, or replace an existing one of the same id. */
if (defineHow & DNP_SET_METHOD) { if (defineHow & DNP_SET_METHOD) {
JS_ASSERT(clasp == &ObjectClass); JS_ASSERT(clasp == &js_ObjectClass);
JS_ASSERT(IsFunctionObject(value)); JS_ASSERT(IsFunctionObject(value));
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER))); JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
JS_ASSERT(!getter && !setter); JS_ASSERT(!getter && !setter);
@ -5400,9 +5400,10 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
if (prop) { if (prop) {
#ifdef DEBUG #ifdef DEBUG
if (parent) { if (parent) {
Class *clasp = obj->getClass();
JS_ASSERT(pobj->isNative()); JS_ASSERT(pobj->isNative());
JS_ASSERT(pobj->getClass() == obj->getClass()); JS_ASSERT(pobj->getClass() == clasp);
if (obj->isBlock()) { if (clasp == &js_BlockClass) {
/* /*
* A block instance on the scope chain is immutable and * A block instance on the scope chain is immutable and
* shares its shape with the compile-time prototype. Thus * shares its shape with the compile-time prototype. Thus
@ -6295,9 +6296,9 @@ DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
Class *clasp = obj->getClass(); Class *clasp = obj->getClass();
if (hint == JSTYPE_STRING) { if (hint == JSTYPE_STRING) {
/* Optimize (new String(...)).toString(). */ /* Optimize (new String(...)).toString(). */
if (clasp == &StringClass && if (clasp == &js_StringClass &&
ClassMethodIsNative(cx, obj, ClassMethodIsNative(cx, obj,
&StringClass, &js_StringClass,
ATOM_TO_JSID(cx->runtime->atomState.toStringAtom), ATOM_TO_JSID(cx->runtime->atomState.toStringAtom),
js_str_toString)) { js_str_toString)) {
*vp = obj->getPrimitiveThis(); *vp = obj->getPrimitiveThis();
@ -6315,12 +6316,12 @@ DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
return true; return true;
} else { } else {
/* Optimize (new String(...)).valueOf(). */ /* Optimize (new String(...)).valueOf(). */
if ((clasp == &StringClass && if ((clasp == &js_StringClass &&
ClassMethodIsNative(cx, obj, &StringClass, ClassMethodIsNative(cx, obj, &js_StringClass,
ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom), ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom),
js_str_toString)) || js_str_toString)) ||
(clasp == &NumberClass && (clasp == &js_NumberClass &&
ClassMethodIsNative(cx, obj, &NumberClass, ClassMethodIsNative(cx, obj, &js_NumberClass,
ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom), ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom),
js_num_valueOf))) { js_num_valueOf))) {
*vp = obj->getPrimitiveThis(); *vp = obj->getPrimitiveThis();
@ -6389,7 +6390,7 @@ CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
JSSecurityCallbacks *callbacks; JSSecurityCallbacks *callbacks;
CheckAccessOp check; CheckAccessOp check;
while (JS_UNLIKELY(obj->isWith())) while (JS_UNLIKELY(obj->getClass() == &js_WithClass))
obj = obj->getProto(); obj = obj->getProto();
writing = (mode & JSACC_WRITE) != 0; writing = (mode & JSACC_WRITE) != 0;
@ -6541,7 +6542,7 @@ PrimitiveToObject(JSContext *cx, const Value &v)
return StringObject::create(cx, v.toString()); return StringObject::create(cx, v.toString());
JS_ASSERT(v.isNumber() || v.isBoolean()); JS_ASSERT(v.isNumber() || v.isBoolean());
Class *clasp = v.isNumber() ? &NumberClass : &BooleanClass; Class *clasp = v.isNumber() ? &js_NumberClass : &js_BooleanClass;
JSObject *obj = NewBuiltinClassInstance(cx, clasp); JSObject *obj = NewBuiltinClassInstance(cx, clasp);
if (!obj) if (!obj)
return NULL; return NULL;
@ -6939,7 +6940,7 @@ dumpValue(const Value &v)
Class *clasp = obj->getClass(); Class *clasp = obj->getClass();
fprintf(stderr, "<%s%s at %p>", fprintf(stderr, "<%s%s at %p>",
clasp->name, clasp->name,
(clasp == &ObjectClass) ? "" : " object", (clasp == &js_ObjectClass) ? "" : " object",
(void *) obj); (void *) obj);
} else if (v.isBoolean()) { } else if (v.isBoolean()) {
if (v.toBoolean()) if (v.toBoolean())

Просмотреть файл

@ -59,15 +59,11 @@
#include "jsvector.h" #include "jsvector.h"
#include "jscell.h" #include "jscell.h"
namespace nanojit { class ValidateWriter; }
namespace js { namespace js {
class AutoPropDescArrayRooter;
class JSProxyHandler; class JSProxyHandler;
class RegExp; class AutoPropDescArrayRooter;
struct GCMarker; struct GCMarker;
struct NativeIterator;
namespace mjit { class Compiler; } namespace mjit { class Compiler; }
@ -288,54 +284,26 @@ js_TypeOf(JSContext *cx, JSObject *obj);
namespace js { namespace js {
/* ES5 8.12.8. */ struct NativeIterator;
extern JSBool class RegExp;
DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
extern JS_FRIEND_DATA(Class) AnyNameClass;
extern JS_FRIEND_DATA(Class) AttributeNameClass;
extern JS_FRIEND_DATA(Class) CallClass;
extern JS_FRIEND_DATA(Class) DeclEnvClass;
extern JS_FRIEND_DATA(Class) FunctionClass;
extern JS_FRIEND_DATA(Class) FunctionProxyClass;
extern JS_FRIEND_DATA(Class) NamespaceClass;
extern JS_FRIEND_DATA(Class) OuterWindowProxyClass;
extern JS_FRIEND_DATA(Class) ObjectProxyClass;
extern JS_FRIEND_DATA(Class) QNameClass;
extern JS_FRIEND_DATA(Class) ScriptClass;
extern JS_FRIEND_DATA(Class) XMLClass;
extern Class ArrayClass;
extern Class ArrayBufferClass;
extern Class BlockClass;
extern Class BooleanClass;
extern Class CallableObjectClass;
extern Class DateClass;
extern Class ErrorClass;
extern Class GeneratorClass;
extern Class IteratorClass;
extern Class JSONClass;
extern Class MathClass;
extern Class NumberClass;
extern Class NormalArgumentsObjectClass;
extern Class ObjectClass;
extern Class ProxyClass;
extern Class RegExpClass;
extern Class SlowArrayClass;
extern Class StopIterationClass;
extern Class StringClass;
extern Class StrictArgumentsObjectClass;
extern Class WeakMapClass;
extern Class WithClass;
extern Class XMLFilterClass;
class ArgumentsObject;
class GlobalObject; class GlobalObject;
class ArgumentsObject;
class NormalArgumentsObject; class NormalArgumentsObject;
class StrictArgumentsObject; class StrictArgumentsObject;
class StringObject; class StringObject;
} /* namespace js */ /* ES5 8.12.8. */
extern JSBool
DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
}
struct JSFunction;
namespace nanojit {
class ValidateWriter;
}
/* /*
* JSObject struct, with members sized to fit in 32 bytes on 32-bit targets, * JSObject struct, with members sized to fit in 32 bytes on 32-bit targets,
@ -408,9 +376,9 @@ struct JSObject : js::gc::Cell {
*/ */
js::Shape *lastProp; js::Shape *lastProp;
private:
js::Class *clasp; js::Class *clasp;
private:
inline void setLastProperty(const js::Shape *shape); inline void setLastProperty(const js::Shape *shape);
inline void removeLastProperty(); inline void removeLastProperty();
@ -502,7 +470,6 @@ struct JSObject : js::gc::Cell {
inline bool isNative() const; inline bool isNative() const;
inline bool isNewborn() const; inline bool isNewborn() const;
void setClass(js::Class *c) { clasp = c; }
js::Class *getClass() const { return clasp; } js::Class *getClass() const { return clasp; }
JSClass *getJSClass() const { return Jsvalify(clasp); } JSClass *getJSClass() const { return Jsvalify(clasp); }
@ -1231,10 +1198,10 @@ struct JSObject : js::gc::Cell {
/* /*
* Slots for XML-related classes are as follows: * Slots for XML-related classes are as follows:
* - NamespaceClass.base reserves the *_NAME_* and *_NAMESPACE_* slots. * - js_NamespaceClass.base reserves the *_NAME_* and *_NAMESPACE_* slots.
* - QNameClass.base, AttributeNameClass, AnyNameClass reserve * - js_QNameClass.base, js_AttributeNameClass, js_AnyNameClass reserve
* the *_NAME_* and *_QNAME_* slots. * the *_NAME_* and *_QNAME_* slots.
* - Others (XMLClass, js_XMLFilterClass) don't reserve any slots. * - Others (js_XMLClass, js_XMLFilterClass) don't reserve any slots.
*/ */
private: private:
static const uint32 JSSLOT_NAME_PREFIX = 0; // shared static const uint32 JSSLOT_NAME_PREFIX = 0; // shared
@ -1464,57 +1431,43 @@ struct JSObject : js::gc::Cell {
inline bool canHaveMethodBarrier() const; inline bool canHaveMethodBarrier() const;
inline bool isArguments() const { return isNormalArguments() || isStrictArguments(); } inline bool isArguments() const;
inline bool isArrayBuffer() const { return clasp == &js::ArrayBufferClass; } inline bool isNormalArguments() const;
inline bool isNormalArguments() const { return clasp == &js::NormalArgumentsObjectClass; } inline bool isStrictArguments() const;
inline bool isStrictArguments() const { return clasp == &js::StrictArgumentsObjectClass; } inline bool isArray() const;
inline bool isArray() const { return isSlowArray() || isDenseArray(); } inline bool isDenseArray() const;
inline bool isDenseArray() const { return clasp == &js::ArrayClass; } inline bool isSlowArray() const;
inline bool isSlowArray() const { return clasp == &js::SlowArrayClass; } inline bool isNumber() const;
inline bool isNumber() const { return clasp == &js::NumberClass; } inline bool isBoolean() const;
inline bool isBoolean() const { return clasp == &js::BooleanClass; } inline bool isString() const;
inline bool isString() const { return clasp == &js::StringClass; } inline bool isPrimitive() const;
inline bool isPrimitive() const { return isNumber() || isString() || isBoolean(); } inline bool isDate() const;
inline bool isDate() const { return clasp == &js::DateClass; } inline bool isFunction() const;
inline bool isFunction() const { return clasp == &js::FunctionClass; } inline bool isObject() const;
inline bool isObject() const { return clasp == &js::ObjectClass; } inline bool isWith() const;
inline bool isWith() const { return clasp == &js::WithClass; } inline bool isBlock() const;
inline bool isBlock() const { return clasp == &js::BlockClass; } inline bool isStaticBlock() const;
inline bool isStaticBlock() const { return isBlock() && !getProto(); } inline bool isClonedBlock() const;
inline bool isClonedBlock() const { return isBlock() && !!getProto(); } inline bool isCall() const;
inline bool isCall() const { return clasp == &js::CallClass; } inline bool isRegExp() const;
inline bool isDeclEnv() const { return clasp == &js::DeclEnvClass; } inline bool isScript() const;
inline bool isRegExp() const { return clasp == &js::RegExpClass; } inline bool isError() const;
inline bool isScript() const { return clasp == &js::ScriptClass; } inline bool isXML() const;
inline bool isGenerator() const { return clasp == &js::GeneratorClass; } inline bool isXMLId() const;
inline bool isIterator() const { return clasp == &js::IteratorClass; } inline bool isNamespace() const;
inline bool isStopIteration() const { return clasp == &js::StopIterationClass; } inline bool isQName() const;
inline bool isError() const { return clasp == &js::ErrorClass; } inline bool isWeakMap() const;
inline bool isXML() const { return clasp == &js::XMLClass; }
inline bool isNamespace() const { return clasp == &js::NamespaceClass; }
inline bool isWeakMap() const { return clasp == &js::WeakMapClass; }
inline bool isFunctionProxy() const { return clasp == &js::FunctionProxyClass; }
inline bool isProxy() const { return isObjectProxy() || isFunctionProxy(); }
inline bool isXMLId() const { inline bool isProxy() const;
return clasp == &js::QNameClass || clasp == &js::AttributeNameClass || clasp == &js::AnyNameClass; inline bool isObjectProxy() const;
} inline bool isFunctionProxy() const;
inline bool isQName() const { inline bool isArrayBuffer() const;
return clasp == &js::QNameClass || clasp == &js::AttributeNameClass || clasp == &js::AnyNameClass;
}
inline bool isObjectProxy() const {
return clasp == &js::ObjectProxyClass || clasp == &js::OuterWindowProxyClass;
}
JS_FRIEND_API(bool) isWrapper() const; JS_FRIEND_API(bool) isWrapper() const;
bool isCrossCompartmentWrapper() const; bool isCrossCompartmentWrapper() const;
JS_FRIEND_API(JSObject *) unwrap(uintN *flagsp = NULL); JS_FRIEND_API(JSObject *) unwrap(uintN *flagsp = NULL);
inline void initArrayClass(); inline void initArrayClass();
/*** For jit compiler: ***/
static size_t offsetOfClassPointer() { return offsetof(JSObject, clasp); }
}; };
/* Check alignment for any fixed slots allocated after the object. */ /* Check alignment for any fixed slots allocated after the object. */
@ -1613,8 +1566,42 @@ class ValueArray {
ValueArray(js::Value *v, size_t c) : array(v), length(c) {} ValueArray(js::Value *v, size_t c) : array(v), length(c) {}
}; };
extern js::Class js_ArrayClass, js_SlowArrayClass, js_ArrayBufferClass;
inline bool
JSObject::isDenseArray() const
{
return getClass() == &js_ArrayClass;
}
inline bool
JSObject::isSlowArray() const
{
return getClass() == &js_SlowArrayClass;
}
inline bool
JSObject::isArray() const
{
return isDenseArray() || isSlowArray();
}
inline bool
JSObject::isArrayBuffer() const
{
return getClass() == &js_ArrayBufferClass;
}
extern js::Class js_ObjectClass;
extern js::Class js_WithClass;
extern js::Class js_BlockClass;
inline bool JSObject::isObject() const { return getClass() == &js_ObjectClass; }
inline bool JSObject::isWith() const { return getClass() == &js_WithClass; }
inline bool JSObject::isBlock() const { return getClass() == &js_BlockClass; }
/* /*
* Block scope object macros. The slots reserved by BlockClass are: * Block scope object macros. The slots reserved by js_BlockClass are:
* *
* private StackFrame * active frame pointer or null * private StackFrame * active frame pointer or null
* JSSLOT_BLOCK_DEPTH int depth of block slots in frame * JSSLOT_BLOCK_DEPTH int depth of block slots in frame
@ -1838,6 +1825,9 @@ extern JSBool
js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id,
const js::Value &descriptor, JSBool *bp); const js::Value &descriptor, JSBool *bp);
extern JS_FRIEND_DATA(js::Class) js_CallClass;
extern JS_FRIEND_DATA(js::Class) js_DeclEnvClass;
namespace js { namespace js {
/* /*
@ -1906,9 +1896,9 @@ IsCacheableNonGlobalScope(JSObject *obj)
JS_ASSERT(obj->getParent()); JS_ASSERT(obj->getParent());
js::Class *clasp = obj->getClass(); js::Class *clasp = obj->getClass();
bool cacheable = (clasp == &CallClass || bool cacheable = (clasp == &js_CallClass ||
clasp == &BlockClass || clasp == &js_BlockClass ||
clasp == &DeclEnvClass); clasp == &js_DeclEnvClass);
JS_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty); JS_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty);
return cacheable; return cacheable;

Просмотреть файл

@ -198,7 +198,7 @@ JSObject::finalize(JSContext *cx)
inline void inline void
JSObject::initCall(JSContext *cx, const js::Bindings &bindings, JSObject *parent) JSObject::initCall(JSContext *cx, const js::Bindings &bindings, JSObject *parent)
{ {
init(cx, &js::CallClass, &js::types::emptyTypeObject, parent, NULL, false); init(cx, &js_CallClass, &js::types::emptyTypeObject, parent, NULL, false);
lastProp = bindings.lastShape(); lastProp = bindings.lastShape();
/* /*
@ -218,7 +218,7 @@ JSObject::initCall(JSContext *cx, const js::Bindings &bindings, JSObject *parent
inline void inline void
JSObject::initClonedBlock(JSContext *cx, js::types::TypeObject *type, js::StackFrame *frame) JSObject::initClonedBlock(JSContext *cx, js::types::TypeObject *type, js::StackFrame *frame)
{ {
init(cx, &js::BlockClass, type, NULL, frame, false); init(cx, &js_BlockClass, type, NULL, frame, false);
/* Cloned blocks copy their prototype's map; it had better be shareable. */ /* Cloned blocks copy their prototype's map; it had better be shareable. */
JS_ASSERT(!getProto()->inDictionaryMode() || getProto()->lastProp->frozen()); JS_ASSERT(!getProto()->inDictionaryMode() || getProto()->lastProp->frozen());
@ -382,6 +382,12 @@ JSObject::canHaveMethodBarrier() const
return isObject() || isFunction() || isPrimitive() || isDate(); return isObject() || isFunction() || isPrimitive() || isDate();
} }
inline bool
JSObject::isPrimitive() const
{
return isNumber() || isString() || isBoolean();
}
inline const js::Value & inline const js::Value &
JSObject::getPrimitiveThis() const JSObject::getPrimitiveThis() const
{ {
@ -905,7 +911,7 @@ JSObject::init(JSContext *cx, js::Class *aclasp, js::types::TypeObject *type,
clasp = aclasp; clasp = aclasp;
flags = capacity << FIXED_SLOTS_SHIFT; flags = capacity << FIXED_SLOTS_SHIFT;
JS_ASSERT(denseArray == (aclasp == &js::ArrayClass)); JS_ASSERT(denseArray == (aclasp == &js_ArrayClass));
#ifdef DEBUG #ifdef DEBUG
/* /*
@ -1162,10 +1168,22 @@ js_IsCallable(const js::Value &v)
return v.isObject() && v.toObject().isCallable(); return v.isObject() && v.toObject().isCallable();
} }
inline bool
JSObject::isStaticBlock() const
{
return isBlock() && !getProto();
}
inline bool
JSObject::isClonedBlock() const
{
return isBlock() && !!getProto();
}
inline JSObject * inline JSObject *
js_UnwrapWithObject(JSContext *cx, JSObject *withobj) js_UnwrapWithObject(JSContext *cx, JSObject *withobj)
{ {
JS_ASSERT(withobj->isWith()); JS_ASSERT(withobj->getClass() == &js_WithClass);
return withobj->getProto(); return withobj->getProto();
} }
@ -1301,7 +1319,7 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto,
* Default parent to the parent of the prototype, which was set from * Default parent to the parent of the prototype, which was set from
* the parent of the prototype's constructor. * the parent of the prototype's constructor.
*/ */
bool denseArray = (clasp == &ArrayClass); bool denseArray = (clasp == &js_ArrayClass);
obj->init(cx, clasp, type, parent, NULL, denseArray); obj->init(cx, clasp, type, parent, NULL, denseArray);
JS_ASSERT(type->canProvideEmptyShape(clasp)); JS_ASSERT(type->canProvideEmptyShape(clasp));
@ -1469,7 +1487,7 @@ NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
*/ */
obj->init(cx, clasp, type, obj->init(cx, clasp, type,
(!parent && proto) ? proto->getParent() : parent, (!parent && proto) ? proto->getParent() : parent,
NULL, clasp == &ArrayClass); NULL, clasp == &js_ArrayClass);
if (clasp->isNative()) { if (clasp->isNative()) {
if (!InitScopeForObject(cx, obj, clasp, type, kind)) { if (!InitScopeForObject(cx, obj, clasp, type, kind)) {
@ -1492,14 +1510,14 @@ NewFunction(JSContext *cx, js::GlobalObject &global)
JSObject *proto; JSObject *proto;
if (!js_GetClassPrototype(cx, &global, JSProto_Function, &proto)) if (!js_GetClassPrototype(cx, &global, JSProto_Function, &proto))
return NULL; return NULL;
return detail::NewObject<WithProto::Given, true>(cx, &FunctionClass, proto, &global, return detail::NewObject<WithProto::Given, true>(cx, &js_FunctionClass, proto, &global,
gc::FINALIZE_OBJECT2); gc::FINALIZE_OBJECT2);
} }
static JS_ALWAYS_INLINE JSObject * static JS_ALWAYS_INLINE JSObject *
NewFunction(JSContext *cx, JSObject *parent) NewFunction(JSContext *cx, JSObject *parent)
{ {
return detail::NewObject<WithProto::Class, true>(cx, &FunctionClass, NULL, parent, return detail::NewObject<WithProto::Class, true>(cx, &js_FunctionClass, NULL, parent,
gc::FINALIZE_OBJECT2); gc::FINALIZE_OBJECT2);
} }
@ -1524,7 +1542,7 @@ static JS_ALWAYS_INLINE JSObject *
NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent, NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
gc::AllocKind kind) gc::AllocKind kind)
{ {
if (clasp == &FunctionClass) if (clasp == &js_FunctionClass)
return detail::NewObject<withProto, true>(cx, clasp, proto, parent, kind); return detail::NewObject<withProto, true>(cx, clasp, proto, parent, kind);
return detail::NewObject<withProto, false>(cx, clasp, proto, parent, kind); return detail::NewObject<withProto, false>(cx, clasp, proto, parent, kind);
} }
@ -1546,7 +1564,7 @@ NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc::
{ {
JS_ASSERT(type == type->proto->newType); JS_ASSERT(type == type->proto->newType);
if (CanBeFinalizedInBackground(kind, &ObjectClass)) if (CanBeFinalizedInBackground(kind, &js_ObjectClass))
kind = GetBackgroundAllocKind(kind); kind = GetBackgroundAllocKind(kind);
JSObject* obj = js_NewGCObject(cx, kind); JSObject* obj = js_NewGCObject(cx, kind);
@ -1557,11 +1575,11 @@ NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc::
* Default parent to the parent of the prototype, which was set from * Default parent to the parent of the prototype, which was set from
* the parent of the prototype's constructor. * the parent of the prototype's constructor.
*/ */
obj->init(cx, &ObjectClass, type, obj->init(cx, &js_ObjectClass, type,
(!parent && type->proto) ? type->proto->getParent() : parent, (!parent && type->proto) ? type->proto->getParent() : parent,
NULL, false); NULL, false);
if (!InitScopeForObject(cx, obj, &ObjectClass, type, kind)) { if (!InitScopeForObject(cx, obj, &js_ObjectClass, type, kind)) {
obj = NULL; obj = NULL;
goto out; goto out;
} }
@ -1595,9 +1613,9 @@ GuessObjectGCKind(size_t numSlots, bool isArray)
static inline gc::AllocKind static inline gc::AllocKind
NewObjectGCKind(JSContext *cx, js::Class *clasp) NewObjectGCKind(JSContext *cx, js::Class *clasp)
{ {
if (clasp == &ArrayClass || clasp == &SlowArrayClass) if (clasp == &js_ArrayClass || clasp == &js_SlowArrayClass)
return gc::FINALIZE_OBJECT8; return gc::FINALIZE_OBJECT8;
if (clasp == &FunctionClass) if (clasp == &js_FunctionClass)
return gc::FINALIZE_OBJECT2; return gc::FINALIZE_OBJECT2;
return gc::FINALIZE_OBJECT4; return gc::FINALIZE_OBJECT4;
} }
@ -1628,10 +1646,10 @@ NewObjectWithClassProto(JSContext *cx, Class *clasp, JSObject *proto,
static inline JSObject * static inline JSObject *
CopyInitializerObject(JSContext *cx, JSObject *baseobj, types::TypeObject *type) CopyInitializerObject(JSContext *cx, JSObject *baseobj, types::TypeObject *type)
{ {
JS_ASSERT(baseobj->getClass() == &ObjectClass); JS_ASSERT(baseobj->getClass() == &js_ObjectClass);
JS_ASSERT(!baseobj->inDictionaryMode()); JS_ASSERT(!baseobj->inDictionaryMode());
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, baseobj->getAllocKind()); JSObject *obj = NewBuiltinClassInstance(cx, &js_ObjectClass, baseobj->getAllocKind());
if (!obj || !obj->ensureSlots(cx, baseobj->numSlots())) if (!obj || !obj->ensureSlots(cx, baseobj->numSlots()))
return NULL; return NULL;

Просмотреть файл

@ -74,7 +74,7 @@ using namespace js;
using namespace js::gc; using namespace js::gc;
using namespace js::types; using namespace js::types;
Class js::JSONClass = { Class js_JSONClass = {
js_JSON_str, js_JSON_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_JSON), JSCLASS_HAS_CACHED_PROTO(JSProto_JSON),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -344,17 +344,17 @@ PreprocessValue(JSContext *cx, JSObject *holder, jsid key, Value *vp, StringifyC
if (vp->isObject()) { if (vp->isObject()) {
JSObject *obj = &vp->toObject(); JSObject *obj = &vp->toObject();
Class *clasp = obj->getClass(); Class *clasp = obj->getClass();
if (clasp == &NumberClass) { if (clasp == &js_NumberClass) {
double d; double d;
if (!ToNumber(cx, *vp, &d)) if (!ToNumber(cx, *vp, &d))
return false; return false;
vp->setNumber(d); vp->setNumber(d);
} else if (clasp == &StringClass) { } else if (clasp == &js_StringClass) {
JSString *str = js_ValueToString(cx, *vp); JSString *str = js_ValueToString(cx, *vp);
if (!str) if (!str)
return false; return false;
vp->setString(str); vp->setString(str);
} else if (clasp == &BooleanClass) { } else if (clasp == &js_BooleanClass) {
*vp = obj->getPrimitiveThis(); *vp = obj->getPrimitiveThis();
JS_ASSERT(vp->isBoolean()); JS_ASSERT(vp->isBoolean());
} }
@ -725,7 +725,7 @@ js_Stringify(JSContext *cx, Value *vp, JSObject *replacer, Value space, StringBu
} }
/* Step 9. */ /* Step 9. */
JSObject *wrapper = NewBuiltinClassInstance(cx, &ObjectClass); JSObject *wrapper = NewBuiltinClassInstance(cx, &js_ObjectClass);
if (!wrapper) if (!wrapper)
return false; return false;
@ -856,7 +856,7 @@ static bool
Revive(JSContext *cx, const Value &reviver, Value *vp) Revive(JSContext *cx, const Value &reviver, Value *vp)
{ {
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_ObjectClass);
if (!obj) if (!obj)
return false; return false;
@ -910,7 +910,7 @@ static JSFunctionSpec json_static_methods[] = {
JSObject * JSObject *
js_InitJSONClass(JSContext *cx, JSObject *obj) js_InitJSONClass(JSContext *cx, JSObject *obj)
{ {
JSObject *JSON = NewNonFunction<WithProto::Class>(cx, &JSONClass, NULL, obj); JSObject *JSON = NewNonFunction<WithProto::Class>(cx, &js_JSONClass, NULL, obj);
if (!JSON || !JSON->setSingletonType(cx)) if (!JSON || !JSON->setSingletonType(cx))
return NULL; return NULL;
@ -921,7 +921,7 @@ js_InitJSONClass(JSContext *cx, JSObject *obj)
if (!JS_DefineFunctions(cx, JSON, json_static_methods)) if (!JS_DefineFunctions(cx, JSON, json_static_methods))
return NULL; return NULL;
MarkStandardClassInitializedNoProto(obj, &JSONClass); MarkStandardClassInitializedNoProto(obj, &js_JSONClass);
return JSON; return JSON;
} }

Просмотреть файл

@ -46,6 +46,8 @@
#define JSON_MAX_DEPTH 2048 #define JSON_MAX_DEPTH 2048
#define JSON_PARSER_BUFSIZE 1024 #define JSON_PARSER_BUFSIZE 1024
extern js::Class js_JSONClass;
extern JSObject * extern JSObject *
js_InitJSONClass(JSContext *cx, JSObject *obj); js_InitJSONClass(JSContext *cx, JSObject *obj);

Просмотреть файл

@ -634,7 +634,7 @@ JSONParser::parse(Value *vp)
} }
case ObjectOpen: { case ObjectOpen: {
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_ObjectClass);
if (!obj || !valueStack.append(ObjectValue(*obj))) if (!obj || !valueStack.append(ObjectValue(*obj)))
return false; return false;
token = advanceAfterObjectOpen(); token = advanceAfterObjectOpen();

Просмотреть файл

@ -366,7 +366,7 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
JSObject *obj = JSVAL_TO_OBJECT(v); JSObject *obj = JSVAL_TO_OBJECT(v);
Class *clasp = obj->getClass(); Class *clasp = obj->getClass();
if (clasp == &BlockClass) { if (clasp == &js_BlockClass) {
char *source = JS_sprintf_append(NULL, "depth %d {", OBJ_BLOCK_DEPTH(cx, obj)); char *source = JS_sprintf_append(NULL, "depth %d {", OBJ_BLOCK_DEPTH(cx, obj));
if (!source) if (!source)
return false; return false;
@ -393,7 +393,7 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
return true; return true;
} }
if (clasp == &FunctionClass) { if (clasp == &js_FunctionClass) {
JSFunction *fun = obj->getFunctionPrivate(); JSFunction *fun = obj->getFunctionPrivate();
JSString *str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT); JSString *str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
if (!str) if (!str)
@ -401,7 +401,7 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
return bytes->encode(cx, str); return bytes->encode(cx, str);
} }
if (clasp == &RegExpClass) { if (clasp == &js_RegExpClass) {
AutoValueRooter tvr(cx); AutoValueRooter tvr(cx);
if (!js_regexp_toString(cx, obj, tvr.addr())) if (!js_regexp_toString(cx, obj, tvr.addr()))
return false; return false;

Просмотреть файл

@ -354,13 +354,13 @@ Probes::resizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize)
#ifdef INCLUDE_MOZILLA_DTRACE #ifdef INCLUDE_MOZILLA_DTRACE
static const char *ObjectClassname(JSObject *obj) { static const char *ObjectClassname(JSObject *obj) {
if (!obj) if (! obj)
return "(null object)"; return "(null object)";
Class *clasp = obj->getClass(); Class *clasp = obj->getClass();
if (!clasp) if (! clasp)
return "(null)"; return "(null)";
const char *class_name = clasp->name; const char *class_name = clasp->name;
if (!class_name) if (! class_name)
return "(null class name)"; return "(null class name)";
return class_name; return class_name;
} }

Просмотреть файл

@ -57,6 +57,8 @@
using namespace js; using namespace js;
using namespace js::gc; using namespace js::gc;
namespace js {
static inline const Value & static inline const Value &
GetCall(JSObject *proxy) { GetCall(JSObject *proxy) {
JS_ASSERT(proxy->isFunctionProxy()); JS_ASSERT(proxy->isFunctionProxy());
@ -411,7 +413,7 @@ ValueToBool(JSContext *cx, const Value &v, bool *bp)
return true; return true;
} }
static bool bool
ArrayToIdVector(JSContext *cx, const Value &array, AutoIdVector &props) ArrayToIdVector(JSContext *cx, const Value &array, AutoIdVector &props)
{ {
JS_ASSERT(props.length() == 0); JS_ASSERT(props.length() == 0);
@ -1025,7 +1027,7 @@ proxy_TypeOf(JSContext *cx, JSObject *proxy)
return JSProxy::typeOf(cx, proxy); return JSProxy::typeOf(cx, proxy);
} }
JS_FRIEND_DATA(Class) js::ObjectProxyClass = { JS_FRIEND_API(Class) ObjectProxyClass = {
"Proxy", "Proxy",
Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(3), Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(3),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -1060,7 +1062,7 @@ JS_FRIEND_DATA(Class) js::ObjectProxyClass = {
} }
}; };
JS_FRIEND_DATA(Class) js::OuterWindowProxyClass = { JS_FRIEND_API(Class) OuterWindowProxyClass = {
"Proxy", "Proxy",
Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(3), Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(3),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -1100,7 +1102,7 @@ JS_FRIEND_DATA(Class) js::OuterWindowProxyClass = {
} }
}; };
static JSBool JSBool
proxy_Call(JSContext *cx, uintN argc, Value *vp) proxy_Call(JSContext *cx, uintN argc, Value *vp)
{ {
JSObject *proxy = &JS_CALLEE(cx, vp).toObject(); JSObject *proxy = &JS_CALLEE(cx, vp).toObject();
@ -1108,7 +1110,7 @@ proxy_Call(JSContext *cx, uintN argc, Value *vp)
return JSProxy::call(cx, proxy, argc, vp); return JSProxy::call(cx, proxy, argc, vp);
} }
static JSBool JSBool
proxy_Construct(JSContext *cx, uintN argc, Value *vp) proxy_Construct(JSContext *cx, uintN argc, Value *vp)
{ {
JSObject *proxy = &JS_CALLEE(cx, vp).toObject(); JSObject *proxy = &JS_CALLEE(cx, vp).toObject();
@ -1117,7 +1119,7 @@ proxy_Construct(JSContext *cx, uintN argc, Value *vp)
return ok; return ok;
} }
JS_FRIEND_DATA(Class) js::FunctionProxyClass = { JS_FRIEND_API(Class) FunctionProxyClass = {
"Proxy", "Proxy",
Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(5), Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(5),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -1133,7 +1135,7 @@ JS_FRIEND_DATA(Class) js::FunctionProxyClass = {
proxy_Call, proxy_Call,
proxy_Construct, proxy_Construct,
NULL, /* xdrObject */ NULL, /* xdrObject */
FunctionClass.hasInstance, js_FunctionClass.hasInstance,
proxy_TraceFunction, /* trace */ proxy_TraceFunction, /* trace */
JS_NULL_CLASS_EXT, JS_NULL_CLASS_EXT,
{ {
@ -1153,7 +1155,7 @@ JS_FRIEND_DATA(Class) js::FunctionProxyClass = {
}; };
JS_FRIEND_API(JSObject *) JS_FRIEND_API(JSObject *)
js::NewProxyObject(JSContext *cx, JSProxyHandler *handler, const Value &priv, JSObject *proto, NewProxyObject(JSContext *cx, JSProxyHandler *handler, const Value &priv, JSObject *proto,
JSObject *parent, JSObject *call, JSObject *construct) JSObject *parent, JSObject *call, JSObject *construct)
{ {
JS_ASSERT_IF(proto, cx->compartment == proto->compartment()); JS_ASSERT_IF(proto, cx->compartment == proto->compartment());
@ -1309,6 +1311,8 @@ static JSFunctionSpec static_methods[] = {
JS_FS_END JS_FS_END
}; };
extern Class CallableObjectClass;
static const uint32 JSSLOT_CALLABLE_CALL = 0; static const uint32 JSSLOT_CALLABLE_CALL = 0;
static const uint32 JSSLOT_CALLABLE_CONSTRUCT = 1; static const uint32 JSSLOT_CALLABLE_CONSTRUCT = 1;
@ -1351,7 +1355,7 @@ callable_Construct(JSContext *cx, uintN argc, Value *vp)
return false; return false;
} }
JSObject *newobj = NewNativeClassInstance(cx, &ObjectClass, proto, proto->getParent()); JSObject *newobj = NewNativeClassInstance(cx, &js_ObjectClass, proto, proto->getParent());
if (!newobj) if (!newobj)
return false; return false;
@ -1372,7 +1376,7 @@ callable_Construct(JSContext *cx, uintN argc, Value *vp)
return ok; return ok;
} }
Class js::CallableObjectClass = { Class CallableObjectClass = {
"Function", "Function",
JSCLASS_HAS_RESERVED_SLOTS(2), JSCLASS_HAS_RESERVED_SLOTS(2),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -1390,7 +1394,7 @@ Class js::CallableObjectClass = {
}; };
JS_FRIEND_API(JSBool) JS_FRIEND_API(JSBool)
js::FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp) FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp)
{ {
if (OperationInProgress(cx, proxy)) { if (OperationInProgress(cx, proxy)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROXY_FIX); JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROXY_FIX);
@ -1411,7 +1415,7 @@ js::FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp)
JSObject *proto = proxy->getProto(); JSObject *proto = proxy->getProto();
JSObject *parent = proxy->getParent(); JSObject *parent = proxy->getParent();
Class *clasp = proxy->isFunctionProxy() ? &CallableObjectClass : &ObjectClass; Class *clasp = proxy->isFunctionProxy() ? &CallableObjectClass : &js_ObjectClass;
/* /*
* Make a blank object from the recipe fix provided to us. This must have * Make a blank object from the recipe fix provided to us. This must have
@ -1444,7 +1448,9 @@ js::FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp)
return true; return true;
} }
Class js::ProxyClass = { }
Class js_ProxyClass = {
"Proxy", "Proxy",
JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy), JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy),
PropertyStub, /* addProperty */ PropertyStub, /* addProperty */
@ -1459,7 +1465,7 @@ Class js::ProxyClass = {
JS_FRIEND_API(JSObject *) JS_FRIEND_API(JSObject *)
js_InitProxyClass(JSContext *cx, JSObject *obj) js_InitProxyClass(JSContext *cx, JSObject *obj)
{ {
JSObject *module = NewNonFunction<WithProto::Class>(cx, &ProxyClass, NULL, obj); JSObject *module = NewNonFunction<WithProto::Class>(cx, &js_ProxyClass, NULL, obj);
if (!module || !module->setSingletonType(cx)) if (!module || !module->setSingletonType(cx))
return NULL; return NULL;
@ -1470,7 +1476,7 @@ js_InitProxyClass(JSContext *cx, JSObject *obj)
if (!JS_DefineFunctions(cx, module, static_methods)) if (!JS_DefineFunctions(cx, module, static_methods))
return NULL; return NULL;
MarkStandardClassInitializedNoProto(obj, &ProxyClass); MarkStandardClassInitializedNoProto(obj, &js_ProxyClass);
return module; return module;
} }

Просмотреть файл

@ -142,6 +142,30 @@ const uint32 JSSLOT_PROXY_EXTRA = 2;
const uint32 JSSLOT_PROXY_CALL = 3; const uint32 JSSLOT_PROXY_CALL = 3;
const uint32 JSSLOT_PROXY_CONSTRUCT = 4; const uint32 JSSLOT_PROXY_CONSTRUCT = 4;
extern JS_FRIEND_API(js::Class) ObjectProxyClass;
extern JS_FRIEND_API(js::Class) FunctionProxyClass;
extern JS_FRIEND_API(js::Class) OuterWindowProxyClass;
extern js::Class CallableObjectClass;
}
inline bool
JSObject::isObjectProxy() const
{
return getClass() == &js::ObjectProxyClass ||
getClass() == &js::OuterWindowProxyClass;
}
inline bool
JSObject::isFunctionProxy() const
{
return getClass() == &js::FunctionProxyClass;
}
inline bool
JSObject::isProxy() const
{
return isObjectProxy() || isFunctionProxy();
} }
inline js::JSProxyHandler * inline js::JSProxyHandler *
@ -193,6 +217,8 @@ FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp);
JS_BEGIN_EXTERN_C JS_BEGIN_EXTERN_C
extern js::Class js_ProxyClass;
extern JS_FRIEND_API(JSObject *) extern JS_FRIEND_API(JSObject *)
js_InitProxyClass(JSContext *cx, JSObject *obj); js_InitProxyClass(JSContext *cx, JSObject *obj);

Просмотреть файл

@ -323,7 +323,7 @@ class NodeBuilder
} }
bool newObject(JSObject **dst) { bool newObject(JSObject **dst) {
JSObject *nobj = NewNonFunction<WithProto::Class>(cx, &ObjectClass, NULL, NULL); JSObject *nobj = NewNonFunction<WithProto::Class>(cx, &js_ObjectClass, NULL, NULL);
if (!nobj) if (!nobj)
return false; return false;
@ -633,7 +633,7 @@ NodeBuilder::newNode(ASTType type, TokenPos *pos, JSObject **dst)
Value tv; Value tv;
JSObject *node = NewNonFunction<WithProto::Class>(cx, &ObjectClass, NULL, NULL); JSObject *node = NewNonFunction<WithProto::Class>(cx, &js_ObjectClass, NULL, NULL);
if (!node || if (!node ||
!setNodeLoc(node, pos) || !setNodeLoc(node, pos) ||
!atomValue(nodeTypeNames[type], &tv) || !atomValue(nodeTypeNames[type], &tv) ||
@ -3238,7 +3238,7 @@ JS_BEGIN_EXTERN_C
JS_PUBLIC_API(JSObject *) JS_PUBLIC_API(JSObject *)
JS_InitReflect(JSContext *cx, JSObject *obj) JS_InitReflect(JSContext *cx, JSObject *obj)
{ {
JSObject *Reflect = NewNonFunction<WithProto::Class>(cx, &ObjectClass, NULL, obj); JSObject *Reflect = NewNonFunction<WithProto::Class>(cx, &js_ObjectClass, NULL, obj);
if (!Reflect || !Reflect->setSingletonType(cx)) if (!Reflect || !Reflect->setSingletonType(cx))
return NULL; return NULL;

Просмотреть файл

@ -141,10 +141,11 @@ SwapObjectRegExp(JSContext *cx, JSObject *obj, AlreadyIncRefed<RegExp> newRegExp
JSObject * JS_FASTCALL JSObject * JS_FASTCALL
js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto) js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto)
{ {
JS_ASSERT(obj->isRegExp()); JS_ASSERT(obj->getClass() == &js_RegExpClass);
JS_ASSERT(proto->isRegExp()); JS_ASSERT(proto);
JS_ASSERT(proto->getClass() == &js_RegExpClass);
JSObject *clone = NewNativeClassInstance(cx, &RegExpClass, proto, proto->getParent()); JSObject *clone = NewNativeClassInstance(cx, &js_RegExpClass, proto, proto->getParent());
if (!clone) if (!clone)
return NULL; return NULL;
@ -431,7 +432,7 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
if (!JS_XDRString(xdr, &source) || !JS_XDRUint32(xdr, &flagsword)) if (!JS_XDRString(xdr, &source) || !JS_XDRUint32(xdr, &flagsword))
return false; return false;
if (xdr->mode == JSXDR_DECODE) { if (xdr->mode == JSXDR_DECODE) {
JSObject *obj = NewBuiltinClassInstance(xdr->cx, &RegExpClass); JSObject *obj = NewBuiltinClassInstance(xdr->cx, &js_RegExpClass);
if (!obj) if (!obj)
return false; return false;
obj->clearParent(); obj->clearParent();
@ -459,7 +460,7 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
#endif /* !JS_HAS_XDR */ #endif /* !JS_HAS_XDR */
Class js::RegExpClass = { js::Class js_RegExpClass = {
js_RegExp_str, js_RegExp_str,
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::REGEXP_CLASS_RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(JSObject::REGEXP_CLASS_RESERVED_SLOTS) |
@ -489,7 +490,7 @@ JSBool
js_regexp_toString(JSContext *cx, JSObject *obj, Value *vp) js_regexp_toString(JSContext *cx, JSObject *obj, Value *vp)
{ {
if (!obj->isRegExp()) { if (!obj->isRegExp()) {
ReportIncompatibleMethod(cx, vp, &RegExpClass); ReportIncompatibleMethod(cx, vp, &js_RegExpClass);
return false; return false;
} }
@ -608,7 +609,7 @@ ExecuteRegExp(JSContext *cx, ExecType execType, uintN argc, Value *vp)
if (!obj) if (!obj)
return false; return false;
if (!obj->isRegExp()) { if (!obj->isRegExp()) {
ReportIncompatibleMethod(cx, vp, &RegExpClass); ReportIncompatibleMethod(cx, vp, &js_RegExpClass);
return false; return false;
} }
@ -702,7 +703,7 @@ CompileRegExpAndSwap(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Valu
return SwapRegExpInternals(cx, obj, rval, cx->runtime->emptyString); return SwapRegExpInternals(cx, obj, rval, cx->runtime->emptyString);
Value sourceValue = argv[0]; Value sourceValue = argv[0];
if (sourceValue.isObject() && sourceValue.toObject().isRegExp()) { if (sourceValue.isObject() && sourceValue.toObject().getClass() == &js_RegExpClass) {
/* /*
* If we get passed in a RegExp object we return a new object with the * If we get passed in a RegExp object we return a new object with the
* same RegExp (internal matcher program) guts. * same RegExp (internal matcher program) guts.
@ -758,7 +759,7 @@ regexp_compile(JSContext *cx, uintN argc, Value *vp)
if (!obj) if (!obj)
return false; return false;
if (!obj->isRegExp()) { if (!obj->isRegExp()) {
ReportIncompatibleMethod(cx, vp, &RegExpClass); ReportIncompatibleMethod(cx, vp, &js_RegExpClass);
return false; return false;
} }
@ -783,7 +784,7 @@ regexp_construct(JSContext *cx, uintN argc, Value *vp)
} }
} }
JSObject *obj = NewBuiltinClassInstance(cx, &RegExpClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_RegExpClass);
if (!obj) if (!obj)
return false; return false;
@ -808,7 +809,7 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj)
GlobalObject *global = obj->asGlobal(); GlobalObject *global = obj->asGlobal();
JSObject *proto = global->createBlankPrototype(cx, &RegExpClass); JSObject *proto = global->createBlankPrototype(cx, &js_RegExpClass);
if (!proto) if (!proto)
return NULL; return NULL;
@ -830,7 +831,7 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj)
if (!DefinePropertiesAndBrand(cx, proto, NULL, regexp_methods)) if (!DefinePropertiesAndBrand(cx, proto, NULL, regexp_methods))
return NULL; return NULL;
JSFunction *ctor = global->createConstructor(cx, regexp_construct, &RegExpClass, JSFunction *ctor = global->createConstructor(cx, regexp_construct, &js_RegExpClass,
CLASS_ATOM(cx, RegExp), 2); CLASS_ATOM(cx, RegExp), 2);
if (!ctor) if (!ctor)
return NULL; return NULL;

Просмотреть файл

@ -52,6 +52,8 @@
#include "jsdhash.h" #include "jsdhash.h"
#endif #endif
extern js::Class js_RegExpClass;
namespace js { namespace js {
class RegExpStatics class RegExpStatics
@ -386,6 +388,12 @@ JSObject::setRegExpSticky(bool sticky)
namespace js { class AutoStringRooter; } namespace js { class AutoStringRooter; }
inline bool
JSObject::isRegExp() const
{
return getClass() == &js_RegExpClass;
}
extern JS_FRIEND_API(JSBool) extern JS_FRIEND_API(JSBool)
js_ObjectIsRegExp(JSObject *obj); js_ObjectIsRegExp(JSObject *obj);

Просмотреть файл

@ -448,7 +448,7 @@ RegExp::createObjectNoStatics(JSContext *cx, const jschar *chars, size_t length,
AlreadyIncRefed<RegExp> re = RegExp::create(cx, str, flags, ts); AlreadyIncRefed<RegExp> re = RegExp::create(cx, str, flags, ts);
if (!re) if (!re)
return NULL; return NULL;
JSObject *obj = NewBuiltinClassInstance(cx, &RegExpClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_RegExpClass);
if (!obj || !obj->initRegExp(cx, re.get())) { if (!obj || !obj->initRegExp(cx, re.get())) {
re->decref(cx); re->decref(cx);
return NULL; return NULL;

Просмотреть файл

@ -288,7 +288,7 @@ Shape::get(JSContext* cx, JSObject *receiver, JSObject* obj, JSObject *pobj, js:
* |with (it) color;| ends up here, as do XML filter-expressions. * |with (it) color;| ends up here, as do XML filter-expressions.
* Avoid exposing the With object to native getters. * Avoid exposing the With object to native getters.
*/ */
if (obj->isWith()) if (obj->getClass() == &js_WithClass)
obj = js_UnwrapWithObject(cx, obj); obj = js_UnwrapWithObject(cx, obj);
return js::CallJSPropertyOp(cx, getterOp(), receiver, SHAPE_USERID(this), vp); return js::CallJSPropertyOp(cx, getterOp(), receiver, SHAPE_USERID(this), vp);
} }
@ -307,7 +307,7 @@ Shape::set(JSContext* cx, JSObject* obj, bool strict, js::Value* vp) const
return js_ReportGetterOnlyAssignment(cx); return js_ReportGetterOnlyAssignment(cx);
/* See the comment in js::Shape::get as to why we check for With. */ /* See the comment in js::Shape::get as to why we check for With. */
if (obj->isWith()) if (obj->getClass() == &js_WithClass)
obj = js_UnwrapWithObject(cx, obj); obj = js_UnwrapWithObject(cx, obj);
return js::CallJSPropertyOpSetter(cx, setterOp(), obj, SHAPE_USERID(this), strict, vp); return js::CallJSPropertyOpSetter(cx, setterOp(), obj, SHAPE_USERID(this), strict, vp);
} }
@ -364,37 +364,37 @@ EmptyShape::EmptyShape(JSCompartment *comp, js::Class *aclasp)
/* static */ inline EmptyShape * /* static */ inline EmptyShape *
EmptyShape::getEmptyArgumentsShape(JSContext *cx) EmptyShape::getEmptyArgumentsShape(JSContext *cx)
{ {
return ensure(cx, &NormalArgumentsObjectClass, &cx->compartment->emptyArgumentsShape); return ensure(cx, &NormalArgumentsObject::jsClass, &cx->compartment->emptyArgumentsShape);
} }
/* static */ inline EmptyShape * /* static */ inline EmptyShape *
EmptyShape::getEmptyBlockShape(JSContext *cx) EmptyShape::getEmptyBlockShape(JSContext *cx)
{ {
return ensure(cx, &BlockClass, &cx->compartment->emptyBlockShape); return ensure(cx, &js_BlockClass, &cx->compartment->emptyBlockShape);
} }
/* static */ inline EmptyShape * /* static */ inline EmptyShape *
EmptyShape::getEmptyCallShape(JSContext *cx) EmptyShape::getEmptyCallShape(JSContext *cx)
{ {
return ensure(cx, &CallClass, &cx->compartment->emptyCallShape); return ensure(cx, &js_CallClass, &cx->compartment->emptyCallShape);
} }
/* static */ inline EmptyShape * /* static */ inline EmptyShape *
EmptyShape::getEmptyDeclEnvShape(JSContext *cx) EmptyShape::getEmptyDeclEnvShape(JSContext *cx)
{ {
return ensure(cx, &DeclEnvClass, &cx->compartment->emptyDeclEnvShape); return ensure(cx, &js_DeclEnvClass, &cx->compartment->emptyDeclEnvShape);
} }
/* static */ inline EmptyShape * /* static */ inline EmptyShape *
EmptyShape::getEmptyEnumeratorShape(JSContext *cx) EmptyShape::getEmptyEnumeratorShape(JSContext *cx)
{ {
return ensure(cx, &IteratorClass, &cx->compartment->emptyEnumeratorShape); return ensure(cx, &js_IteratorClass, &cx->compartment->emptyEnumeratorShape);
} }
/* static */ inline EmptyShape * /* static */ inline EmptyShape *
EmptyShape::getEmptyWithShape(JSContext *cx) EmptyShape::getEmptyWithShape(JSContext *cx)
{ {
return ensure(cx, &WithClass, &cx->compartment->emptyWithShape); return ensure(cx, &js_WithClass, &cx->compartment->emptyWithShape);
} }
} /* namespace js */ } /* namespace js */

Просмотреть файл

@ -668,9 +668,9 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp)
uint32 isBlock; uint32 isBlock;
if (xdr->mode == JSXDR_ENCODE) { if (xdr->mode == JSXDR_ENCODE) {
Class *clasp = (*objp)->getClass(); Class *clasp = (*objp)->getClass();
JS_ASSERT(clasp == &FunctionClass || JS_ASSERT(clasp == &js_FunctionClass ||
clasp == &BlockClass); clasp == &js_BlockClass);
isBlock = (clasp == &BlockClass) ? 1 : 0; isBlock = (clasp == &js_BlockClass) ? 1 : 0;
} }
if (!JS_XDRUint32(xdr, &isBlock)) if (!JS_XDRUint32(xdr, &isBlock))
goto error; goto error;
@ -778,7 +778,7 @@ script_trace(JSTracer *trc, JSObject *obj)
} }
} }
Class js::ScriptClass = { Class js_ScriptClass = {
"Script", "Script",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_CACHED_PROTO(JSProto_Object), JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
@ -1387,7 +1387,7 @@ js_NewScriptObject(JSContext *cx, JSScript *script)
{ {
JS_ASSERT(!script->u.object); JS_ASSERT(!script->u.object);
JSObject *obj = NewNonFunction<WithProto::Class>(cx, &ScriptClass, NULL, NULL); JSObject *obj = NewNonFunction<WithProto::Class>(cx, &js_ScriptClass, NULL, NULL);
if (!obj) if (!obj)
return NULL; return NULL;
obj->setPrivate(script); obj->setPrivate(script);

Просмотреть файл

@ -552,7 +552,7 @@ struct JSScript : public js::gc::Cell {
union { union {
/* /*
* A script object of class ScriptClass, to ensure the script is GC'd. * A script object of class js_ScriptClass, to ensure the script is GC'd.
* - All scripts returned by JSAPI functions (JS_CompileScript, * - All scripts returned by JSAPI functions (JS_CompileScript,
* JS_CompileFile, etc.) have these objects. * JS_CompileFile, etc.) have these objects.
* - Function scripts never have script objects; such scripts are owned * - Function scripts never have script objects; such scripts are owned
@ -843,6 +843,7 @@ StackDepth(JSScript *script)
} \ } \
JS_END_MACRO JS_END_MACRO
extern JS_FRIEND_DATA(js::Class) js_ScriptClass;
extern JSObject * extern JSObject *
js_InitScriptClass(JSContext *cx, JSObject *obj); js_InitScriptClass(JSContext *cx, JSObject *obj);
@ -965,6 +966,12 @@ js_CloneScript(JSContext *cx, JSScript *script);
extern JSBool extern JSBool
js_XDRScript(JSXDRState *xdr, JSScript **scriptp); js_XDRScript(JSXDRState *xdr, JSScript **scriptp);
inline bool
JSObject::isScript() const
{
return getClass() == &js_ScriptClass;
}
inline JSScript * inline JSScript *
JSObject::getScript() const JSObject::getScript() const
{ {

Просмотреть файл

@ -153,7 +153,7 @@ JSScript::getRegExp(size_t index)
JSObjectArray *arr = regexps(); JSObjectArray *arr = regexps();
JS_ASSERT((uint32) index < arr->length); JS_ASSERT((uint32) index < arr->length);
JSObject *obj = arr->vector[index]; JSObject *obj = arr->vector[index];
JS_ASSERT(obj->isRegExp()); JS_ASSERT(obj->getClass() == &js_RegExpClass);
return obj; return obj;
} }

Просмотреть файл

@ -384,7 +384,7 @@ str_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
return JS_TRUE; return JS_TRUE;
} }
Class js::StringClass = { Class js_StringClass = {
js_String_str, js_String_str,
JSCLASS_HAS_RESERVED_SLOTS(StringObject::RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(StringObject::RESERVED_SLOTS) |
JSCLASS_NEW_RESOLVE | JSCLASS_HAS_CACHED_PROTO(JSProto_String), JSCLASS_NEW_RESOLVE | JSCLASS_HAS_CACHED_PROTO(JSProto_String),
@ -401,7 +401,7 @@ Class js::StringClass = {
* Returns a JSString * for the |this| value associated with vp, or throws a * Returns a JSString * for the |this| value associated with vp, or throws a
* TypeError if |this| is null or undefined. This algorithm is the same as * TypeError if |this| is null or undefined. This algorithm is the same as
* calling CheckObjectCoercible(this), then returning ToString(this), as all * calling CheckObjectCoercible(this), then returning ToString(this), as all
* String.prototype.* methods do (other than toString and valueOf). * String.prototype.* methods do.
*/ */
static JS_ALWAYS_INLINE JSString * static JS_ALWAYS_INLINE JSString *
ThisToStringForStringProto(JSContext *cx, Value *vp) ThisToStringForStringProto(JSContext *cx, Value *vp)
@ -413,9 +413,9 @@ ThisToStringForStringProto(JSContext *cx, Value *vp)
if (vp[1].isObject()) { if (vp[1].isObject()) {
JSObject *obj = &vp[1].toObject(); JSObject *obj = &vp[1].toObject();
if (obj->isString() && if (obj->getClass() == &js_StringClass &&
ClassMethodIsNative(cx, obj, ClassMethodIsNative(cx, obj,
&StringClass, &js_StringClass,
ATOM_TO_JSID(cx->runtime->atomState.toStringAtom), ATOM_TO_JSID(cx->runtime->atomState.toStringAtom),
js_str_toString)) js_str_toString))
{ {
@ -3191,12 +3191,12 @@ js_InitStringClass(JSContext *cx, JSObject *obj)
GlobalObject *global = obj->asGlobal(); GlobalObject *global = obj->asGlobal();
JSObject *proto = global->createBlankPrototype(cx, &StringClass); JSObject *proto = global->createBlankPrototype(cx, &js_StringClass);
if (!proto || !proto->asString()->init(cx, cx->runtime->emptyString)) if (!proto || !proto->asString()->init(cx, cx->runtime->emptyString))
return NULL; return NULL;
/* Now create the String function. */ /* Now create the String function. */
JSFunction *ctor = global->createConstructor(cx, js_String, &StringClass, JSFunction *ctor = global->createConstructor(cx, js_String, &js_StringClass,
CLASS_ATOM(cx, String), 1); CLASS_ATOM(cx, String), 1);
if (!ctor) if (!ctor)
return NULL; return NULL;

Просмотреть файл

@ -101,6 +101,14 @@ extern JSSubString js_EmptySubString;
#define JS7_ISLET(c) ((c) < 128 && isalpha(c)) #define JS7_ISLET(c) ((c) < 128 && isalpha(c))
/* Initialize the String class, returning its prototype object. */ /* Initialize the String class, returning its prototype object. */
extern js::Class js_StringClass;
inline bool
JSObject::isString() const
{
return getClass() == &js_StringClass;
}
extern JSObject * extern JSObject *
js_InitStringClass(JSContext *cx, JSObject *obj); js_InitStringClass(JSContext *cx, JSObject *obj);

Просмотреть файл

@ -9832,9 +9832,9 @@ TraceRecorder::unbox_object(Address addr, LIns* tag_ins, JSValueType type, VMSid
guard(true, w.name(w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_OBJECT)), "isObj"), exit); guard(true, w.name(w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_OBJECT)), "isObj"), exit);
LIns *payload_ins = w.ldiValuePayload(addr); LIns *payload_ins = w.ldiValuePayload(addr);
if (type == JSVAL_TYPE_FUNOBJ) if (type == JSVAL_TYPE_FUNOBJ)
guardClass(payload_ins, &FunctionClass, exit, LOAD_NORMAL); guardClass(payload_ins, &js_FunctionClass, exit, LOAD_NORMAL);
else else
guardNotClass(payload_ins, &FunctionClass, exit, LOAD_NORMAL); guardNotClass(payload_ins, &js_FunctionClass, exit, LOAD_NORMAL);
return payload_ins; return payload_ins;
} }
@ -9985,9 +9985,9 @@ TraceRecorder::unbox_object(LIns* v_ins, JSValueType type, VMSideExit* exit)
exit); exit);
v_ins = unpack_ptr(v_ins); v_ins = unpack_ptr(v_ins);
if (type == JSVAL_TYPE_FUNOBJ) if (type == JSVAL_TYPE_FUNOBJ)
guardClass(v_ins, &FunctionClass, exit, LOAD_NORMAL); guardClass(v_ins, &js_FunctionClass, exit, LOAD_NORMAL);
else else
guardNotClass(v_ins, &FunctionClass, exit, LOAD_NORMAL); guardNotClass(v_ins, &js_FunctionClass, exit, LOAD_NORMAL);
return v_ins; return v_ins;
} }
@ -10194,13 +10194,13 @@ TraceRecorder::guardNotClass(LIns* obj_ins, Class* clasp, VMSideExit* exit, Load
JS_REQUIRES_STACK void JS_REQUIRES_STACK void
TraceRecorder::guardDenseArray(LIns* obj_ins, ExitType exitType) TraceRecorder::guardDenseArray(LIns* obj_ins, ExitType exitType)
{ {
guardClass(obj_ins, &ArrayClass, snapshot(exitType), LOAD_NORMAL); guardClass(obj_ins, &js_ArrayClass, snapshot(exitType), LOAD_NORMAL);
} }
JS_REQUIRES_STACK void JS_REQUIRES_STACK void
TraceRecorder::guardDenseArray(LIns* obj_ins, VMSideExit* exit) TraceRecorder::guardDenseArray(LIns* obj_ins, VMSideExit* exit)
{ {
guardClass(obj_ins, &ArrayClass, exit, LOAD_NORMAL); guardClass(obj_ins, &js_ArrayClass, exit, LOAD_NORMAL);
} }
JS_REQUIRES_STACK bool JS_REQUIRES_STACK bool
@ -11065,7 +11065,7 @@ TraceRecorder::getClassPrototype(JSObject* ctor, LIns*& proto_ins)
JS_ASSERT(!pval.isPrimitive()); JS_ASSERT(!pval.isPrimitive());
JSObject *proto = &pval.toObject(); JSObject *proto = &pval.toObject();
JS_ASSERT(!proto->isDenseArray()); JS_ASSERT(!proto->isDenseArray());
JS_ASSERT_IF(clasp != &ArrayClass, proto->getNewType(cx)->emptyShapes[0]->getClass() == clasp); JS_ASSERT_IF(clasp != &js_ArrayClass, proto->getNewType(cx)->emptyShapes[0]->getClass() == clasp);
proto_ins = w.immpObjGC(proto); proto_ins = w.immpObjGC(proto);
return RECORD_CONTINUE; return RECORD_CONTINUE;
@ -11608,15 +11608,15 @@ TraceRecorder::callNative(uintN argc, JSOp mode)
LIns* this_ins; LIns* this_ins;
if (mode == JSOP_NEW) { if (mode == JSOP_NEW) {
Class* clasp = fun->u.n.clasp; Class* clasp = fun->u.n.clasp;
JS_ASSERT(clasp != &SlowArrayClass); JS_ASSERT(clasp != &js_SlowArrayClass);
if (!clasp) if (!clasp)
clasp = &ObjectClass; clasp = &js_ObjectClass;
JS_ASSERT(((jsuword) clasp & 3) == 0); JS_ASSERT(((jsuword) clasp & 3) == 0);
// Abort on |new Function|. (FIXME: This restriction might not // Abort on |new Function|. (FIXME: This restriction might not
// unnecessary now that the constructor creates the new function object // unnecessary now that the constructor creates the new function object
// itself.) // itself.)
if (clasp == &FunctionClass) if (clasp == &js_FunctionClass)
RETURN_STOP("new Function"); RETURN_STOP("new Function");
if (!IsFastTypedArrayClass(clasp) && !clasp->isNative()) if (!IsFastTypedArrayClass(clasp) && !clasp->isNative())
@ -12494,7 +12494,7 @@ TraceRecorder::recordInitPropertyOp(jsbytecode op)
Value& l = stackval(-2); Value& l = stackval(-2);
JSObject* obj = &l.toObject(); JSObject* obj = &l.toObject();
LIns* obj_ins = get(&l); LIns* obj_ins = get(&l);
JS_ASSERT(obj->getClass() == &ObjectClass); JS_ASSERT(obj->getClass() == &js_ObjectClass);
Value& v = stackval(-1); Value& v = stackval(-1);
LIns* v_ins = get(&v); LIns* v_ins = get(&v);
@ -12769,7 +12769,7 @@ GetPropertyWithNativeGetter(JSContext* cx, JSObject* obj, Shape* shape, Value* v
// Shape::get contains a special case for With objects. We can elide it // Shape::get contains a special case for With objects. We can elide it
// here because With objects are, we claim, never on the operand stack // here because With objects are, we claim, never on the operand stack
// while recording. // while recording.
JS_ASSERT(obj->getClass() != &WithClass); JS_ASSERT(obj->getClass() != &js_WithClass);
vp->setUndefined(); vp->setUndefined();
if (!shape->getterOp()(cx, obj, SHAPE_USERID(shape), vp)) { if (!shape->getterOp()(cx, obj, SHAPE_USERID(shape), vp)) {
@ -14823,8 +14823,8 @@ TraceRecorder::record_JSOP_MOREITER()
* ni->flags (nor do we in unboxNextValue), because the different iteration * ni->flags (nor do we in unboxNextValue), because the different iteration
* type will guarantee a different entry typemap. * type will guarantee a different entry typemap.
*/ */
if (iterobj->hasClass(&IteratorClass)) { if (iterobj->hasClass(&js_IteratorClass)) {
guardClass(iterobj_ins, &IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); guardClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL);
NativeIterator *ni = (NativeIterator *) iterobj->getPrivate(); NativeIterator *ni = (NativeIterator *) iterobj->getPrivate();
if (ni->isKeyIter()) { if (ni->isKeyIter()) {
@ -14837,7 +14837,7 @@ TraceRecorder::record_JSOP_MOREITER()
return ARECORD_CONTINUE; return ARECORD_CONTINUE;
} }
} else { } else {
guardNotClass(iterobj_ins, &IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); guardNotClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL);
} }
enterDeepBailCall(); enterDeepBailCall();
@ -14922,8 +14922,8 @@ TraceRecorder::unboxNextValue(Value &iterobj_val, LIns* &v_ins)
JSObject *iterobj = &iterobj_val.toObject(); JSObject *iterobj = &iterobj_val.toObject();
LIns* iterobj_ins = get(&iterobj_val); LIns* iterobj_ins = get(&iterobj_val);
if (iterobj->hasClass(&IteratorClass)) { if (iterobj->hasClass(&js_IteratorClass)) {
guardClass(iterobj_ins, &IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); guardClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL);
NativeIterator *ni = (NativeIterator *) iterobj->getPrivate(); NativeIterator *ni = (NativeIterator *) iterobj->getPrivate();
LIns *ni_ins = w.ldpObjPrivate(iterobj_ins); LIns *ni_ins = w.ldpObjPrivate(iterobj_ins);
@ -14966,7 +14966,7 @@ TraceRecorder::unboxNextValue(Value &iterobj_val, LIns* &v_ins)
return ARECORD_CONTINUE; return ARECORD_CONTINUE;
} }
} else { } else {
guardNotClass(iterobj_ins, &IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); guardNotClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL);
} }
@ -16340,7 +16340,7 @@ TraceRecorder::record_JSOP_LENGTH()
guardDenseArray(obj_ins, BRANCH_EXIT); guardDenseArray(obj_ins, BRANCH_EXIT);
} else { } else {
JS_ASSERT(obj->isSlowArray()); JS_ASSERT(obj->isSlowArray());
guardClass(obj_ins, &SlowArrayClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); guardClass(obj_ins, &js_SlowArrayClass, snapshot(BRANCH_EXIT), LOAD_NORMAL);
} }
v_ins = w.lduiObjPrivate(obj_ins); v_ins = w.lduiObjPrivate(obj_ins);
if (obj->getArrayLength() <= JSVAL_INT_MAX) { if (obj->getArrayLength() <= JSVAL_INT_MAX) {

Просмотреть файл

@ -186,7 +186,7 @@ static JSObject *
DelegateObject(JSContext *cx, JSObject *obj) DelegateObject(JSContext *cx, JSObject *obj)
{ {
if (!obj->getPrivate()) { if (!obj->getPrivate()) {
JSObject *delegate = NewNonFunction<WithProto::Given>(cx, &ObjectClass, obj->getProto(), NULL); JSObject *delegate = NewNonFunction<WithProto::Given>(cx, &js_ObjectClass, obj->getProto(), NULL);
obj->setPrivate(delegate); obj->setPrivate(delegate);
return delegate; return delegate;
} }
@ -212,7 +212,7 @@ ArrayBuffer::create(JSContext *cx, int32 nbytes)
JS_ASSERT(obj->getClass() == &ArrayBuffer::slowClass); JS_ASSERT(obj->getClass() == &ArrayBuffer::slowClass);
obj->setSharedNonNativeMap(); obj->setSharedNonNativeMap();
obj->setClass(&ArrayBufferClass); obj->clasp = &js_ArrayBufferClass;
/* /*
* The first 8 bytes hold the length. * The first 8 bytes hold the length.
@ -980,7 +980,7 @@ class TypedArrayTemplate
JS_ASSERT(obj->getClass() == slowClass()); JS_ASSERT(obj->getClass() == slowClass());
obj->setSharedNonNativeMap(); obj->setSharedNonNativeMap();
obj->setClass(fastClass()); obj->clasp = fastClass();
// FIXME Bug 599008: make it ok to call preventExtensions here. // FIXME Bug 599008: make it ok to call preventExtensions here.
obj->flags |= JSObject::NOT_EXTENSIBLE; obj->flags |= JSObject::NOT_EXTENSIBLE;
@ -1694,7 +1694,7 @@ Class ArrayBuffer::slowClass = {
FinalizeStub FinalizeStub
}; };
Class js::ArrayBufferClass = { Class js_ArrayBufferClass = {
"ArrayBuffer", "ArrayBuffer",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_PRIVATE |
Class::NON_NATIVE | Class::NON_NATIVE |
@ -1902,7 +1902,7 @@ InitArrayBufferClass(JSContext *cx, GlobalObject *global)
return NULL; return NULL;
JSFunction *ctor = JSFunction *ctor =
global->createConstructor(cx, ArrayBuffer::class_constructor, &ArrayBufferClass, global->createConstructor(cx, ArrayBuffer::class_constructor, &js_ArrayBufferClass,
CLASS_ATOM(cx, ArrayBuffer), 1); CLASS_ATOM(cx, ArrayBuffer), 1);
if (!ctor) if (!ctor)
return NULL; return NULL;
@ -1953,7 +1953,7 @@ JS_FRIEND_API(JSBool)
js_IsArrayBuffer(JSObject *obj) js_IsArrayBuffer(JSObject *obj)
{ {
JS_ASSERT(obj); JS_ASSERT(obj);
return obj->isArrayBuffer(); return obj->getClass() == &js_ArrayBufferClass;
} }
namespace js { namespace js {

Просмотреть файл

@ -78,6 +78,12 @@ WeakMapBase::sweepAll(JSTracer *tracer)
} /* namespace js */ } /* namespace js */
bool
JSObject::isWeakMap() const
{
return getClass() == &WeakMapClass;
}
typedef WeakMap<JSObject *, Value> ObjectValueMap; typedef WeakMap<JSObject *, Value> ObjectValueMap;
static ObjectValueMap * static ObjectValueMap *
@ -258,7 +264,9 @@ WeakMap_construct(JSContext *cx, uintN argc, Value *vp)
return true; return true;
} }
Class js::WeakMapClass = { namespace js {
Class WeakMapClass = {
"WeakMap", "WeakMap",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_CACHED_PROTO(JSProto_WeakMap), JSCLASS_HAS_CACHED_PROTO(JSProto_WeakMap),
@ -279,6 +287,8 @@ Class js::WeakMapClass = {
WeakMap_mark WeakMap_mark
}; };
}
static JSFunctionSpec weak_map_methods[] = { static JSFunctionSpec weak_map_methods[] = {
JS_FN("has", WeakMap_has, 1, 0), JS_FN("has", WeakMap_has, 1, 0),
JS_FN("get", WeakMap_get, 2, 0), JS_FN("get", WeakMap_get, 2, 0),

Просмотреть файл

@ -317,6 +317,9 @@ class DefaultMarkPolicy<JSObject *, JSObject *> {
// //
typedef DefaultMarkPolicy<JSObject *, JSObject *> CrossCompartmentMarkPolicy; typedef DefaultMarkPolicy<JSObject *, JSObject *> CrossCompartmentMarkPolicy;
// The class of JavaScript WeakMap objects.
extern Class WeakMapClass;
} }
extern JSObject * extern JSObject *

Просмотреть файл

@ -632,7 +632,7 @@ CanReify(Value *vp)
{ {
JSObject *obj; JSObject *obj;
return vp->isObject() && return vp->isObject() &&
(obj = &vp->toObject())->getClass() == &IteratorClass && (obj = &vp->toObject())->getClass() == &js_IteratorClass &&
(obj->getNativeIterator()->flags & JSITER_ENUMERATE); (obj->getNativeIterator()->flags & JSITER_ENUMERATE);
} }

Просмотреть файл

@ -153,7 +153,7 @@ IsDeclared(const JSObject *obj)
{ {
jsval v; jsval v;
JS_ASSERT(obj->getClass() == &NamespaceClass); JS_ASSERT(obj->getClass() == &js_NamespaceClass);
v = obj->getNamespaceDeclared(); v = obj->getNamespaceDeclared();
JS_ASSERT(JSVAL_IS_VOID(v) || v == JSVAL_TRUE); JS_ASSERT(JSVAL_IS_VOID(v) || v == JSVAL_TRUE);
return v == JSVAL_TRUE; return v == JSVAL_TRUE;
@ -197,9 +197,9 @@ NewBuiltinClassInstanceXML(JSContext *cx, Class *clasp)
* Namespace class and library functions. * Namespace class and library functions.
*/ */
DEFINE_GETTER(NamePrefix_getter, DEFINE_GETTER(NamePrefix_getter,
if (obj->getClass() == &NamespaceClass) *vp = obj->getNamePrefixVal()) if (obj->getClass() == &js_NamespaceClass) *vp = obj->getNamePrefixVal())
DEFINE_GETTER(NameURI_getter, DEFINE_GETTER(NameURI_getter,
if (obj->getClass() == &NamespaceClass) *vp = obj->getNameURIVal()) if (obj->getClass() == &js_NamespaceClass) *vp = obj->getNameURIVal())
static JSBool static JSBool
namespace_equality(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp) namespace_equality(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
@ -208,13 +208,13 @@ namespace_equality(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
JS_ASSERT(v->isObjectOrNull()); JS_ASSERT(v->isObjectOrNull());
obj2 = v->toObjectOrNull(); obj2 = v->toObjectOrNull();
*bp = (!obj2 || obj2->getClass() != &NamespaceClass) *bp = (!obj2 || obj2->getClass() != &js_NamespaceClass)
? JS_FALSE ? JS_FALSE
: EqualStrings(obj->getNameURI(), obj2->getNameURI()); : EqualStrings(obj->getNameURI(), obj2->getNameURI());
return JS_TRUE; return JS_TRUE;
} }
JS_FRIEND_DATA(Class) js::NamespaceClass = { JS_FRIEND_DATA(Class) js_NamespaceClass = {
"Namespace", "Namespace",
JSCLASS_HAS_RESERVED_SLOTS(JSObject::NAMESPACE_CLASS_RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(JSObject::NAMESPACE_CLASS_RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace), JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace),
@ -258,7 +258,7 @@ namespace_toString(JSContext *cx, uintN argc, Value *vp)
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
if (!obj->isNamespace()) { if (!obj->isNamespace()) {
ReportIncompatibleMethod(cx, vp, &NamespaceClass); ReportIncompatibleMethod(cx, vp, &js_NamespaceClass);
return JS_FALSE; return JS_FALSE;
} }
*vp = Valueify(obj->getNameURIVal()); *vp = Valueify(obj->getNameURIVal());
@ -275,7 +275,7 @@ NewXMLNamespace(JSContext *cx, JSLinearString *prefix, JSLinearString *uri, JSBo
{ {
JSObject *obj; JSObject *obj;
obj = NewBuiltinClassInstanceXML(cx, &NamespaceClass); obj = NewBuiltinClassInstanceXML(cx, &js_NamespaceClass);
if (!obj) if (!obj)
return NULL; return NULL;
JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefixVal())); JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefixVal()));
@ -299,10 +299,10 @@ NewXMLNamespace(JSContext *cx, JSLinearString *prefix, JSLinearString *uri, JSBo
* QName class and library functions. * QName class and library functions.
*/ */
DEFINE_GETTER(QNameNameURI_getter, DEFINE_GETTER(QNameNameURI_getter,
if (obj->getClass() == &QNameClass) if (obj->getClass() == &js_QNameClass)
*vp = JSVAL_IS_VOID(obj->getNameURIVal()) ? JSVAL_NULL : obj->getNameURIVal()) *vp = JSVAL_IS_VOID(obj->getNameURIVal()) ? JSVAL_NULL : obj->getNameURIVal())
DEFINE_GETTER(QNameLocalName_getter, DEFINE_GETTER(QNameLocalName_getter,
if (obj->getClass() == &QNameClass) if (obj->getClass() == &js_QNameClass)
*vp = obj->getQNameLocalNameVal()) *vp = obj->getQNameLocalNameVal())
static JSBool static JSBool
@ -324,13 +324,13 @@ qname_equality(JSContext *cx, JSObject *qn, const Value *v, JSBool *bp)
JSObject *obj2; JSObject *obj2;
obj2 = v->toObjectOrNull(); obj2 = v->toObjectOrNull();
*bp = (!obj2 || obj2->getClass() != &QNameClass) *bp = (!obj2 || obj2->getClass() != &js_QNameClass)
? JS_FALSE ? JS_FALSE
: qname_identity(qn, obj2); : qname_identity(qn, obj2);
return JS_TRUE; return JS_TRUE;
} }
JS_FRIEND_DATA(Class) js::QNameClass = { JS_FRIEND_DATA(Class) js_QNameClass = {
"QName", "QName",
JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_QName), JSCLASS_HAS_CACHED_PROTO(JSProto_QName),
@ -364,7 +364,7 @@ JS_FRIEND_DATA(Class) js::QNameClass = {
* qname_toString method, and therefore are exposed as constructable objects * qname_toString method, and therefore are exposed as constructable objects
* in this implementation. * in this implementation.
*/ */
JS_FRIEND_DATA(Class) js::AttributeNameClass = { JS_FRIEND_DATA(Class) js_AttributeNameClass = {
js_AttributeName_str, js_AttributeName_str,
JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS, JSCLASS_IS_ANONYMOUS,
@ -378,7 +378,7 @@ JS_FRIEND_DATA(Class) js::AttributeNameClass = {
FinalizeStub FinalizeStub
}; };
JS_FRIEND_DATA(Class) js::AnyNameClass = { JS_FRIEND_DATA(Class) js_AnyNameClass = {
js_AnyName_str, js_AnyName_str,
JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS, JSCLASS_IS_ANONYMOUS,
@ -422,7 +422,7 @@ ConvertQNameToString(JSContext *cx, JSObject *obj)
if (!str) if (!str)
return NULL; return NULL;
if (obj->getClass() == &AttributeNameClass) { if (obj->getClass() == &js_AttributeNameClass) {
JS::Anchor<JSString *> anchor(str); JS::Anchor<JSString *> anchor(str);
size_t length = str->length(); size_t length = str->length();
jschar *chars = (jschar *) cx->malloc_((length + 2) * sizeof(jschar)); jschar *chars = (jschar *) cx->malloc_((length + 2) * sizeof(jschar));
@ -453,7 +453,7 @@ qname_toString(JSContext *cx, uintN argc, Value *vp)
return false; return false;
if (!obj->isQName()) { if (!obj->isQName()) {
ReportIncompatibleMethod(cx, vp, &QNameClass); ReportIncompatibleMethod(cx, vp, &js_QNameClass);
return false; return false;
} }
@ -497,7 +497,7 @@ static JSObject *
NewXMLQName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix, NewXMLQName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix,
JSAtom *localName) JSAtom *localName)
{ {
JSObject *obj = NewBuiltinClassInstanceXML(cx, &QNameClass); JSObject *obj = NewBuiltinClassInstanceXML(cx, &js_QNameClass);
if (!obj) if (!obj)
return NULL; return NULL;
if (!InitXMLQName(cx, obj, uri, prefix, localName)) if (!InitXMLQName(cx, obj, uri, prefix, localName))
@ -514,7 +514,7 @@ NewXMLAttributeName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix,
* exposed to scripts. * exposed to scripts.
*/ */
JSObject *parent = GetGlobalForScopeChain(cx); JSObject *parent = GetGlobalForScopeChain(cx);
JSObject *obj = NewNonFunction<WithProto::Given>(cx, &AttributeNameClass, NULL, parent); JSObject *obj = NewNonFunction<WithProto::Given>(cx, &js_AttributeNameClass, NULL, parent);
if (!obj) if (!obj)
return NULL; return NULL;
JS_ASSERT(obj->isQName()); JS_ASSERT(obj->isQName());
@ -534,13 +534,13 @@ js_ConstructXMLQNameObject(JSContext *cx, const Value &nsval, const Value &lnval
* production, step 2. * production, step 2.
*/ */
if (nsval.isObject() && if (nsval.isObject() &&
nsval.toObject().getClass() == &AnyNameClass) { nsval.toObject().getClass() == &js_AnyNameClass) {
argv[0].setNull(); argv[0].setNull();
} else { } else {
argv[0] = nsval; argv[0] = nsval;
} }
argv[1] = lnval; argv[1] = lnval;
return js_ConstructObject(cx, &QNameClass, NULL, NULL, 2, argv); return js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 2, argv);
} }
static JSBool static JSBool
@ -616,8 +616,8 @@ NamespaceHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv,
if (!JSVAL_IS_PRIMITIVE(urival)) { if (!JSVAL_IS_PRIMITIVE(urival)) {
uriobj = JSVAL_TO_OBJECT(urival); uriobj = JSVAL_TO_OBJECT(urival);
clasp = uriobj->getClass(); clasp = uriobj->getClass();
isNamespace = (clasp == &NamespaceClass); isNamespace = (clasp == &js_NamespaceClass);
isQName = (clasp == &QNameClass); isQName = (clasp == &js_QNameClass);
} }
} }
@ -629,7 +629,7 @@ NamespaceHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv,
return JS_TRUE; return JS_TRUE;
} }
obj = NewBuiltinClassInstanceXML(cx, &NamespaceClass); obj = NewBuiltinClassInstanceXML(cx, &js_NamespaceClass);
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
} }
@ -732,7 +732,7 @@ QNameHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv, jsval *rval)
nameval = argv[argc > 1]; nameval = argv[argc > 1];
isQName = isQName =
!JSVAL_IS_PRIMITIVE(nameval) && !JSVAL_IS_PRIMITIVE(nameval) &&
JSVAL_TO_OBJECT(nameval)->getClass() == &QNameClass; JSVAL_TO_OBJECT(nameval)->getClass() == &js_QNameClass;
} }
if (!obj) { if (!obj) {
@ -744,7 +744,7 @@ QNameHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv, jsval *rval)
} }
/* Create and return a new QName object exactly as if constructed. */ /* Create and return a new QName object exactly as if constructed. */
obj = NewBuiltinClassInstanceXML(cx, &QNameClass); obj = NewBuiltinClassInstanceXML(cx, &js_QNameClass);
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
} }
@ -782,7 +782,7 @@ QNameHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv, jsval *rval)
return JS_FALSE; return JS_FALSE;
JS_ASSERT(!JSVAL_IS_PRIMITIVE(nsval)); JS_ASSERT(!JSVAL_IS_PRIMITIVE(nsval));
JS_ASSERT(JSVAL_TO_OBJECT(nsval)->getClass() == JS_ASSERT(JSVAL_TO_OBJECT(nsval)->getClass() ==
&NamespaceClass); &js_NamespaceClass);
} }
if (JSVAL_IS_NULL(nsval)) { if (JSVAL_IS_NULL(nsval)) {
@ -799,8 +799,8 @@ QNameHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv, jsval *rval)
isNamespace = isQName = JS_FALSE; isNamespace = isQName = JS_FALSE;
if (!JSVAL_IS_PRIMITIVE(nsval)) { if (!JSVAL_IS_PRIMITIVE(nsval)) {
obj2 = JSVAL_TO_OBJECT(nsval); obj2 = JSVAL_TO_OBJECT(nsval);
isNamespace = (obj2->getClass() == &NamespaceClass); isNamespace = (obj2->getClass() == &js_NamespaceClass);
isQName = (obj2->getClass() == &QNameClass); isQName = (obj2->getClass() == &js_QNameClass);
} }
#ifdef __GNUC__ /* suppress bogus gcc warnings */ #ifdef __GNUC__ /* suppress bogus gcc warnings */
else obj2 = NULL; else obj2 = NULL;
@ -1852,9 +1852,9 @@ ToXML(JSContext *cx, jsval v)
JS_ASSERT(0); JS_ASSERT(0);
} }
if (clasp != &StringClass && if (clasp != &js_StringClass &&
clasp != &NumberClass && clasp != &js_NumberClass &&
clasp != &BooleanClass) { clasp != &js_BooleanClass) {
goto bad; goto bad;
} }
} }
@ -1933,9 +1933,9 @@ ToXMLList(JSContext *cx, jsval v)
JS_ASSERT(0); JS_ASSERT(0);
} }
if (clasp != &StringClass && if (clasp != &js_StringClass &&
clasp != &NumberClass && clasp != &js_NumberClass &&
clasp != &BooleanClass) { clasp != &js_BooleanClass) {
goto bad; goto bad;
} }
} }
@ -2230,7 +2230,7 @@ GetNamespace(JSContext *cx, JSObject *qn, const JSXMLArray *inScopeNSes)
if (!match) { if (!match) {
argv[0] = prefix ? STRING_TO_JSVAL(prefix) : JSVAL_VOID; argv[0] = prefix ? STRING_TO_JSVAL(prefix) : JSVAL_VOID;
argv[1] = STRING_TO_JSVAL(uri); argv[1] = STRING_TO_JSVAL(uri);
ns = js_ConstructObject(cx, &NamespaceClass, NULL, NULL, ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, NULL,
2, Valueify(argv)); 2, Valueify(argv));
if (!ns) if (!ns)
return NULL; return NULL;
@ -2783,16 +2783,16 @@ ToAttributeName(JSContext *cx, jsval v)
obj = JSVAL_TO_OBJECT(v); obj = JSVAL_TO_OBJECT(v);
clasp = obj->getClass(); clasp = obj->getClass();
if (clasp == &AttributeNameClass) if (clasp == &js_AttributeNameClass)
return obj; return obj;
if (clasp == &QNameClass) { if (clasp == &js_QNameClass) {
qn = obj; qn = obj;
uri = qn->getNameURI(); uri = qn->getNameURI();
prefix = qn->getNamePrefix(); prefix = qn->getNamePrefix();
name = qn->getQNameLocalName(); name = qn->getQNameLocalName();
} else { } else {
if (clasp == &AnyNameClass) { if (clasp == &js_AnyNameClass) {
name = cx->runtime->atomState.starAtom; name = cx->runtime->atomState.starAtom;
} else { } else {
if (!js_ValueToAtom(cx, Valueify(v), &name)) if (!js_ValueToAtom(cx, Valueify(v), &name))
@ -2853,9 +2853,9 @@ ToXMLName(JSContext *cx, jsval v, jsid *funidp)
obj = JSVAL_TO_OBJECT(v); obj = JSVAL_TO_OBJECT(v);
clasp = obj->getClass(); clasp = obj->getClass();
if (clasp == &AttributeNameClass || clasp == &QNameClass) if (clasp == &js_AttributeNameClass || clasp == &js_QNameClass)
goto out; goto out;
if (clasp == &AnyNameClass) { if (clasp == &js_AnyNameClass) {
name = cx->runtime->atomState.starAtom; name = cx->runtime->atomState.starAtom;
goto construct; goto construct;
} }
@ -2894,7 +2894,7 @@ ToXMLName(JSContext *cx, jsval v, jsid *funidp)
construct: construct:
v = STRING_TO_JSVAL(name); v = STRING_TO_JSVAL(name);
obj = js_ConstructObject(cx, &QNameClass, NULL, NULL, 1, Valueify(&v)); obj = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 1, Valueify(&v));
if (!obj) if (!obj)
return NULL; return NULL;
@ -3207,7 +3207,7 @@ DescendantsHelper(JSContext *cx, JSXML *xml, JSObject *nameqn, JSXML *list)
JS_CHECK_RECURSION(cx, return JS_FALSE); JS_CHECK_RECURSION(cx, return JS_FALSE);
if (xml->xml_class == JSXML_CLASS_ELEMENT && if (xml->xml_class == JSXML_CLASS_ELEMENT &&
nameqn->getClass() == &AttributeNameClass) { nameqn->getClass() == &js_AttributeNameClass) {
for (i = 0, n = xml->xml_attrs.length; i < n; i++) { for (i = 0, n = xml->xml_attrs.length; i < n; i++) {
attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML); attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML);
if (attr && MatchAttrName(nameqn, attr)) { if (attr && MatchAttrName(nameqn, attr)) {
@ -3221,7 +3221,7 @@ DescendantsHelper(JSContext *cx, JSXML *xml, JSObject *nameqn, JSXML *list)
kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
if (!kid) if (!kid)
continue; continue;
if (nameqn->getClass() != &AttributeNameClass && if (nameqn->getClass() != &js_AttributeNameClass &&
MatchElemName(nameqn, kid)) { MatchElemName(nameqn, kid)) {
if (!Append(cx, list, kid)) if (!Append(cx, list, kid))
return JS_FALSE; return JS_FALSE;
@ -3670,7 +3670,7 @@ GetNamedProperty(JSContext *cx, JSXML *xml, JSObject* nameqn, JSXML *list)
} }
} }
} else if (xml->xml_class == JSXML_CLASS_ELEMENT) { } else if (xml->xml_class == JSXML_CLASS_ELEMENT) {
attrs = (nameqn->getClass() == &AttributeNameClass); attrs = (nameqn->getClass() == &js_AttributeNameClass);
if (attrs) { if (attrs) {
array = &xml->xml_attrs; array = &xml->xml_attrs;
matcher = MatchAttrName; matcher = MatchAttrName;
@ -3921,7 +3921,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
goto bad; goto bad;
} else { } else {
nameobj = targetprop; nameobj = targetprop;
if (nameobj->getClass() == &AttributeNameClass) { if (nameobj->getClass() == &js_AttributeNameClass) {
/* /*
* 2(c)(iii)(1-3). * 2(c)(iii)(1-3).
* Note that rxml can't be null here, because target * Note that rxml can't be null here, because target
@ -4017,7 +4017,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
parent = kid->parent; parent = kid->parent;
if (kid->xml_class == JSXML_CLASS_ATTRIBUTE) { if (kid->xml_class == JSXML_CLASS_ATTRIBUTE) {
nameobj = kid->name; nameobj = kid->name;
if (nameobj->getClass() != &AttributeNameClass) { if (nameobj->getClass() != &js_AttributeNameClass) {
nameobj = NewXMLAttributeName(cx, nameobj->getNameURI(), nameobj->getNamePrefix(), nameobj = NewXMLAttributeName(cx, nameobj->getNameURI(), nameobj->getNamePrefix(),
nameobj->getQNameLocalName()); nameobj->getQNameLocalName());
if (!nameobj) if (!nameobj)
@ -4224,7 +4224,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
if (!ok) if (!ok)
goto out; goto out;
if (nameobj->getClass() == &AttributeNameClass) { if (nameobj->getClass() == &js_AttributeNameClass) {
/* 7(a). */ /* 7(a). */
if (!js_IsXMLName(cx, OBJECT_TO_JSVAL(nameobj))) if (!js_IsXMLName(cx, OBJECT_TO_JSVAL(nameobj)))
goto out; goto out;
@ -4477,7 +4477,7 @@ ResolveValue(JSContext *cx, JSXML *list, JSXML **result)
return JS_TRUE; return JS_TRUE;
} }
if (targetprop->getClass() == &AttributeNameClass) { if (targetprop->getClass() == &js_AttributeNameClass) {
*result = NULL; *result = NULL;
return JS_TRUE; return JS_TRUE;
} }
@ -4533,7 +4533,7 @@ HasNamedProperty(JSXML *xml, JSObject *nameqn)
} }
if (xml->xml_class == JSXML_CLASS_ELEMENT) { if (xml->xml_class == JSXML_CLASS_ELEMENT) {
if (nameqn->getClass() == &AttributeNameClass) { if (nameqn->getClass() == &js_AttributeNameClass) {
array = &xml->xml_attrs; array = &xml->xml_attrs;
matcher = MatchAttrName; matcher = MatchAttrName;
} else { } else {
@ -4572,7 +4572,7 @@ HasFunctionProperty(JSContext *cx, JSObject *obj, jsid funid, JSBool *found)
JSProperty *prop; JSProperty *prop;
JSXML *xml; JSXML *xml;
JS_ASSERT(obj->getClass() == &XMLClass); JS_ASSERT(obj->getClass() == &js_XMLClass);
if (!js_LookupProperty(cx, obj, funid, &pobj, &prop)) if (!js_LookupProperty(cx, obj, funid, &pobj, &prop))
return false; return false;
@ -4818,7 +4818,7 @@ xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool st
return js_DeleteProperty(cx, obj, funid, rval, false); return js_DeleteProperty(cx, obj, funid, rval, false);
DeleteNamedProperty(cx, xml, nameqn, DeleteNamedProperty(cx, xml, nameqn,
nameqn->getClass() == &AttributeNameClass); nameqn->getClass() == &js_AttributeNameClass);
} }
/* /*
@ -5112,7 +5112,7 @@ out:
return ok; return ok;
} }
JS_FRIEND_DATA(Class) js::XMLClass = { JS_FRIEND_DATA(Class) js_XMLClass = {
js_XML_str, js_XML_str,
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_CACHED_PROTO(JSProto_XML), JSCLASS_HAS_CACHED_PROTO(JSProto_XML),
@ -5162,7 +5162,7 @@ StartNonListXMLMethod(JSContext *cx, jsval *vp, JSObject **objp)
if (!*objp) if (!*objp)
return NULL; return NULL;
if (!(*objp)->isXML()) { if (!(*objp)->isXML()) {
ReportIncompatibleMethod(cx, Valueify(vp), &XMLClass); ReportIncompatibleMethod(cx, Valueify(vp), &js_XMLClass);
return NULL; return NULL;
} }
xml = (JSXML *) (*objp)->getPrivate(); xml = (JSXML *) (*objp)->getPrivate();
@ -5196,7 +5196,7 @@ StartNonListXMLMethod(JSContext *cx, jsval *vp, JSObject **objp)
if (!obj) \ if (!obj) \
return JS_FALSE; \ return JS_FALSE; \
if (!obj->isXML()) { \ if (!obj->isXML()) { \
ReportIncompatibleMethod(cx, Valueify(vp), &XMLClass); \ ReportIncompatibleMethod(cx, Valueify(vp), &js_XMLClass); \
return JS_FALSE; \ return JS_FALSE; \
} \ } \
JSXML *xml = (JSXML *)obj->getPrivate(); \ JSXML *xml = (JSXML *)obj->getPrivate(); \
@ -5683,7 +5683,7 @@ xml_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp)
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
if (!obj->isXML()) { if (!obj->isXML()) {
ReportIncompatibleMethod(cx, Valueify(vp), &XMLClass); ReportIncompatibleMethod(cx, Valueify(vp), &js_XMLClass);
return JS_FALSE; return JS_FALSE;
} }
@ -6480,13 +6480,13 @@ xml_setName(JSContext *cx, uintN argc, jsval *vp)
} else { } else {
name = vp[2]; name = vp[2];
if (!JSVAL_IS_PRIMITIVE(name) && if (!JSVAL_IS_PRIMITIVE(name) &&
JSVAL_TO_OBJECT(name)->getClass() == &QNameClass && JSVAL_TO_OBJECT(name)->getClass() == &js_QNameClass &&
!(nameqn = JSVAL_TO_OBJECT(name))->getNameURI()) { !(nameqn = JSVAL_TO_OBJECT(name))->getNameURI()) {
name = vp[2] = nameqn->getQNameLocalNameVal(); name = vp[2] = nameqn->getQNameLocalNameVal();
} }
} }
nameqn = js_ConstructObject(cx, &QNameClass, NULL, NULL, 1, Valueify(&name)); nameqn = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 1, Valueify(&name));
if (!nameqn) if (!nameqn)
return JS_FALSE; return JS_FALSE;
@ -6588,7 +6588,7 @@ xml_setNamespace(JSContext *cx, uintN argc, jsval *vp)
if (!xml) if (!xml)
return JS_FALSE; return JS_FALSE;
ns = js_ConstructObject(cx, &NamespaceClass, NULL, obj, ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, obj,
argc == 0 ? 0 : 1, Valueify(vp + 2)); argc == 0 ? 0 : 1, Valueify(vp + 2));
if (!ns) if (!ns)
return JS_FALSE; return JS_FALSE;
@ -6597,7 +6597,7 @@ xml_setNamespace(JSContext *cx, uintN argc, jsval *vp)
qnargv[0] = OBJECT_TO_JSVAL(ns); qnargv[0] = OBJECT_TO_JSVAL(ns);
qnargv[1] = OBJECT_TO_JSVAL(xml->name); qnargv[1] = OBJECT_TO_JSVAL(xml->name);
qn = js_ConstructObject(cx, &QNameClass, NULL, NULL, 2, Valueify(qnargv)); qn = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 2, Valueify(qnargv));
if (!qn) if (!qn)
return JS_FALSE; return JS_FALSE;
@ -6925,7 +6925,7 @@ XML(JSContext *cx, uintN argc, Value *vp)
if (IsConstructing(vp) && !JSVAL_IS_PRIMITIVE(v)) { if (IsConstructing(vp) && !JSVAL_IS_PRIMITIVE(v)) {
vobj = JSVAL_TO_OBJECT(v); vobj = JSVAL_TO_OBJECT(v);
clasp = vobj->getClass(); clasp = vobj->getClass();
if (clasp == &XMLClass || if (clasp == &js_XMLClass ||
(clasp->flags & JSCLASS_DOCUMENT_OBSERVER)) { (clasp->flags & JSCLASS_DOCUMENT_OBSERVER)) {
copy = DeepCopy(cx, xml, NULL, 0); copy = DeepCopy(cx, xml, NULL, 0);
if (!copy) if (!copy)
@ -7071,7 +7071,7 @@ NewXMLObject(JSContext *cx, JSXML *xml)
JSObject *obj; JSObject *obj;
JSObject *parent = GetGlobalForScopeChain(cx); JSObject *parent = GetGlobalForScopeChain(cx);
obj = NewNonFunction<WithProto::Class>(cx, &XMLClass, NULL, parent); obj = NewNonFunction<WithProto::Class>(cx, &js_XMLClass, NULL, parent);
if (!obj) if (!obj)
return NULL; return NULL;
obj->setPrivate(xml); obj->setPrivate(xml);
@ -7103,7 +7103,7 @@ js_InitNamespaceClass(JSContext *cx, JSObject *obj)
GlobalObject *global = obj->asGlobal(); GlobalObject *global = obj->asGlobal();
JSObject *namespaceProto = global->createBlankPrototype(cx, &NamespaceClass); JSObject *namespaceProto = global->createBlankPrototype(cx, &js_NamespaceClass);
if (!namespaceProto) if (!namespaceProto)
return NULL; return NULL;
JSFlatString *empty = cx->runtime->emptyString; JSFlatString *empty = cx->runtime->emptyString;
@ -7112,7 +7112,7 @@ js_InitNamespaceClass(JSContext *cx, JSObject *obj)
namespaceProto->syncSpecialEquality(); namespaceProto->syncSpecialEquality();
const uintN NAMESPACE_CTOR_LENGTH = 2; const uintN NAMESPACE_CTOR_LENGTH = 2;
JSFunction *ctor = global->createConstructor(cx, Namespace, &NamespaceClass, JSFunction *ctor = global->createConstructor(cx, Namespace, &js_NamespaceClass,
CLASS_ATOM(cx, Namespace), CLASS_ATOM(cx, Namespace),
NAMESPACE_CTOR_LENGTH); NAMESPACE_CTOR_LENGTH);
if (!ctor) if (!ctor)
@ -7137,7 +7137,7 @@ js_InitQNameClass(JSContext *cx, JSObject *obj)
GlobalObject *global = obj->asGlobal(); GlobalObject *global = obj->asGlobal();
JSObject *qnameProto = global->createBlankPrototype(cx, &QNameClass); JSObject *qnameProto = global->createBlankPrototype(cx, &js_QNameClass);
if (!qnameProto) if (!qnameProto)
return NULL; return NULL;
JSAtom *empty = cx->runtime->emptyString; JSAtom *empty = cx->runtime->emptyString;
@ -7146,7 +7146,7 @@ js_InitQNameClass(JSContext *cx, JSObject *obj)
qnameProto->syncSpecialEquality(); qnameProto->syncSpecialEquality();
const uintN QNAME_CTOR_LENGTH = 2; const uintN QNAME_CTOR_LENGTH = 2;
JSFunction *ctor = global->createConstructor(cx, QName, &QNameClass, JSFunction *ctor = global->createConstructor(cx, QName, &js_QNameClass,
CLASS_ATOM(cx, QName), QNAME_CTOR_LENGTH); CLASS_ATOM(cx, QName), QNAME_CTOR_LENGTH);
if (!ctor) if (!ctor)
return NULL; return NULL;
@ -7170,7 +7170,7 @@ js_InitXMLClass(JSContext *cx, JSObject *obj)
GlobalObject *global = obj->asGlobal(); GlobalObject *global = obj->asGlobal();
JSObject *xmlProto = global->createBlankPrototype(cx, &XMLClass); JSObject *xmlProto = global->createBlankPrototype(cx, &js_XMLClass);
if (!xmlProto) if (!xmlProto)
return NULL; return NULL;
JSXML *xml = js_NewXML(cx, JSXML_CLASS_TEXT); JSXML *xml = js_NewXML(cx, JSXML_CLASS_TEXT);
@ -7186,7 +7186,7 @@ js_InitXMLClass(JSContext *cx, JSObject *obj)
} }
const uintN XML_CTOR_LENGTH = 1; const uintN XML_CTOR_LENGTH = 1;
JSFunction *ctor = global->createConstructor(cx, XML, &XMLClass, CLASS_ATOM(cx, XML), JSFunction *ctor = global->createConstructor(cx, XML, &js_XMLClass, CLASS_ATOM(cx, XML),
XML_CTOR_LENGTH); XML_CTOR_LENGTH);
if (!ctor) if (!ctor)
return NULL; return NULL;
@ -7293,7 +7293,7 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
obj = NULL; obj = NULL;
for (tmp = scopeChain; tmp; tmp = tmp->getParent()) { for (tmp = scopeChain; tmp; tmp = tmp->getParent()) {
Class *clasp = tmp->getClass(); Class *clasp = tmp->getClass();
if (clasp == &BlockClass || clasp == &WithClass) if (clasp == &js_BlockClass || clasp == &js_WithClass)
continue; continue;
if (!tmp->getProperty(cx, JS_DEFAULT_XML_NAMESPACE_ID, Valueify(&v))) if (!tmp->getProperty(cx, JS_DEFAULT_XML_NAMESPACE_ID, Valueify(&v)))
return JS_FALSE; return JS_FALSE;
@ -7304,7 +7304,7 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
obj = tmp; obj = tmp;
} }
ns = js_ConstructObject(cx, &NamespaceClass, NULL, obj, 0, NULL); ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, obj, 0, NULL);
if (!ns) if (!ns)
return JS_FALSE; return JS_FALSE;
v = OBJECT_TO_JSVAL(ns); v = OBJECT_TO_JSVAL(ns);
@ -7322,7 +7322,7 @@ js_SetDefaultXMLNamespace(JSContext *cx, const Value &v)
Value argv[2]; Value argv[2];
argv[0].setString(cx->runtime->emptyString); argv[0].setString(cx->runtime->emptyString);
argv[1] = v; argv[1] = v;
JSObject *ns = js_ConstructObject(cx, &NamespaceClass, NULL, NULL, 2, argv); JSObject *ns = js_ConstructObject(cx, &js_NamespaceClass, NULL, NULL, 2, argv);
if (!ns) if (!ns)
return JS_FALSE; return JS_FALSE;
@ -7407,7 +7407,7 @@ js_GetAnyName(JSContext *cx, jsid *idp)
JSObject *global = cx->hasfp() ? cx->fp()->scopeChain().getGlobal() : cx->globalObject; JSObject *global = cx->hasfp() ? cx->fp()->scopeChain().getGlobal() : cx->globalObject;
Value v = global->getReservedSlot(JSProto_AnyName); Value v = global->getReservedSlot(JSProto_AnyName);
if (v.isUndefined()) { if (v.isUndefined()) {
JSObject *obj = NewNonFunction<WithProto::Given>(cx, &AnyNameClass, NULL, global); JSObject *obj = NewNonFunction<WithProto::Given>(cx, &js_AnyNameClass, NULL, global);
if (!obj) if (!obj)
return false; return false;
@ -7439,15 +7439,15 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *i
JS_ASSERT(nameval.isObject()); JS_ASSERT(nameval.isObject());
nameobj = &nameval.toObject(); nameobj = &nameval.toObject();
if (nameobj->getClass() == &AnyNameClass) { if (nameobj->getClass() == &js_AnyNameClass) {
v = STRING_TO_JSVAL(cx->runtime->atomState.starAtom); v = STRING_TO_JSVAL(cx->runtime->atomState.starAtom);
nameobj = js_ConstructObject(cx, &QNameClass, NULL, NULL, 1, nameobj = js_ConstructObject(cx, &js_QNameClass, NULL, NULL, 1,
Valueify(&v)); Valueify(&v));
if (!nameobj) if (!nameobj)
return JS_FALSE; return JS_FALSE;
} else { } else {
JS_ASSERT(nameobj->getClass() == &AttributeNameClass || JS_ASSERT(nameobj->getClass() == &js_AttributeNameClass ||
nameobj->getClass() == &QNameClass); nameobj->getClass() == &js_QNameClass);
} }
qn = nameobj; qn = nameobj;
@ -7458,7 +7458,7 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *i
do { do {
/* Skip any With object that can wrap XML. */ /* Skip any With object that can wrap XML. */
target = obj; target = obj;
while (target->getClass() == &WithClass) { while (target->getClass() == &js_WithClass) {
proto = target->getProto(); proto = target->getProto();
if (!proto) if (!proto)
break; break;

Просмотреть файл

@ -219,12 +219,48 @@ js_NewXMLObject(JSContext *cx, JSXMLClass xml_class);
extern JSObject * extern JSObject *
js_GetXMLObject(JSContext *cx, JSXML *xml); js_GetXMLObject(JSContext *cx, JSXML *xml);
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). * Methods to test whether an object or a value is of type "xml" (per typeof).
*/ */
inline bool
JSObject::isXML() const
{
return getClass() == &js_XMLClass;
}
inline bool
JSObject::isXMLId() const
{
js::Class *clasp = getClass();
return clasp == &js_QNameClass ||
clasp == &js_AttributeNameClass ||
clasp == &js_AnyNameClass;
}
#define VALUE_IS_XML(v) (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isXML()) #define VALUE_IS_XML(v) (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isXML())
inline bool
JSObject::isNamespace() const
{
return getClass() == &js_NamespaceClass;
}
inline bool
JSObject::isQName() const
{
js::Class* clasp = getClass();
return clasp == &js_QNameClass ||
clasp == &js_AttributeNameClass ||
clasp == &js_AnyNameClass;
}
static inline bool static inline bool
IsXML(const js::Value &v) IsXML(const js::Value &v)
{ {

Просмотреть файл

@ -204,8 +204,8 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
} }
Jump testFunction(Condition cond, RegisterID fun) { Jump testFunction(Condition cond, RegisterID fun) {
return branchPtr(cond, Address(fun, JSObject::offsetOfClassPointer()), return branchPtr(cond, Address(fun, offsetof(JSObject, clasp)),
ImmPtr(&FunctionClass)); ImmPtr(&js_FunctionClass));
} }
/* /*
@ -811,7 +811,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
} }
void loadObjClass(RegisterID objReg, RegisterID destReg) { void loadObjClass(RegisterID objReg, RegisterID destReg) {
loadPtr(Address(objReg, JSObject::offsetOfClassPointer()), destReg); loadPtr(Address(objReg, offsetof(JSObject, clasp)), destReg);
} }
Jump testClass(Condition cond, RegisterID claspReg, js::Class *clasp) { Jump testClass(Condition cond, RegisterID claspReg, js::Class *clasp) {
@ -819,7 +819,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
} }
Jump testObjClass(Condition cond, RegisterID objReg, js::Class *clasp) { Jump testObjClass(Condition cond, RegisterID objReg, js::Class *clasp) {
return branchPtr(cond, Address(objReg, JSObject::offsetOfClassPointer()), ImmPtr(clasp)); return branchPtr(cond, Address(objReg, offsetof(JSObject, clasp)), ImmPtr(clasp));
} }
void branchValue(Condition cond, RegisterID reg, int32 value, RegisterID result) void branchValue(Condition cond, RegisterID reg, int32 value, RegisterID result)
@ -1289,7 +1289,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
} }
storePtr(ImmPtr(templateObject->lastProp), Address(result, offsetof(JSObject, lastProp))); storePtr(ImmPtr(templateObject->lastProp), Address(result, offsetof(JSObject, lastProp)));
storePtr(ImmPtr(templateObject->getClass()), Address(result, JSObject::offsetOfClassPointer())); storePtr(ImmPtr(templateObject->clasp), Address(result, offsetof(JSObject, clasp)));
store32(Imm32(templateObject->flags), Address(result, offsetof(JSObject, flags))); store32(Imm32(templateObject->flags), Address(result, offsetof(JSObject, flags)));
store32(Imm32(templateObject->objShape), Address(result, offsetof(JSObject, objShape))); store32(Imm32(templateObject->objShape), Address(result, offsetof(JSObject, objShape)));
storePtr(ImmPtr(templateObject->newType), Address(result, offsetof(JSObject, newType))); storePtr(ImmPtr(templateObject->newType), Address(result, offsetof(JSObject, newType)));

Просмотреть файл

@ -5594,7 +5594,7 @@ mjit::Compiler::iterNext()
frame.unpinReg(reg); frame.unpinReg(reg);
/* Test clasp */ /* Test clasp */
Jump notFast = masm.testObjClass(Assembler::NotEqual, reg, &IteratorClass); Jump notFast = masm.testObjClass(Assembler::NotEqual, reg, &js_IteratorClass);
stubcc.linkExit(notFast, Uses(1)); stubcc.linkExit(notFast, Uses(1));
/* Get private from iter obj. */ /* Get private from iter obj. */
@ -5648,7 +5648,7 @@ mjit::Compiler::iterMore(jsbytecode *target)
RegisterID tempreg = frame.allocReg(); RegisterID tempreg = frame.allocReg();
/* Test clasp */ /* Test clasp */
Jump notFast = masm.testObjClass(Assembler::NotEqual, reg, &IteratorClass); Jump notFast = masm.testObjClass(Assembler::NotEqual, reg, &js_IteratorClass);
stubcc.linkExitForBranch(notFast); stubcc.linkExitForBranch(notFast);
/* Get private from iter obj. */ /* Get private from iter obj. */
@ -5687,7 +5687,7 @@ mjit::Compiler::iterEnd()
frame.unpinReg(reg); frame.unpinReg(reg);
/* Test clasp */ /* Test clasp */
Jump notIterator = masm.testObjClass(Assembler::NotEqual, reg, &IteratorClass); Jump notIterator = masm.testObjClass(Assembler::NotEqual, reg, &js_IteratorClass);
stubcc.linkExit(notIterator, Uses(1)); stubcc.linkExit(notIterator, Uses(1));
/* Get private from iter obj. */ /* Get private from iter obj. */

Просмотреть файл

@ -1570,7 +1570,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
ic.slowPathStart = stubcc.syncExit(Uses(3)); ic.slowPathStart = stubcc.syncExit(Uses(3));
// Guard obj is a dense array. // Guard obj is a dense array.
ic.claspGuard = masm.testObjClass(Assembler::NotEqual, ic.objReg, &ArrayClass); ic.claspGuard = masm.testObjClass(Assembler::NotEqual, ic.objReg, &js_ArrayClass);
stubcc.linkExitDirect(ic.claspGuard, ic.slowPathStart); stubcc.linkExitDirect(ic.claspGuard, ic.slowPathStart);
// Guard in range of initialized length. // Guard in range of initialized length.
@ -2120,7 +2120,7 @@ mjit::Compiler::jsop_getelem(bool isCall)
} }
// Guard on the clasp. // Guard on the clasp.
ic.claspGuard = masm.testObjClass(Assembler::NotEqual, ic.objReg, &ArrayClass); ic.claspGuard = masm.testObjClass(Assembler::NotEqual, ic.objReg, &js_ArrayClass);
stubcc.linkExitDirect(ic.claspGuard, ic.slowPathStart); stubcc.linkExitDirect(ic.claspGuard, ic.slowPathStart);
Int32Key key = id->isConstant() Int32Key key = id->isConstant()

Просмотреть файл

@ -115,7 +115,7 @@ top:
jsbytecode *pc = script->main() + tn->start + tn->length; jsbytecode *pc = script->main() + tn->start + tn->length;
cx->regs().pc = pc; cx->regs().pc = pc;
JSBool ok = UnwindScope(cx, tn->stackDepth, JS_TRUE); JSBool ok = js_UnwindScope(cx, tn->stackDepth, JS_TRUE);
JS_ASSERT(cx->regs().sp == fp->base() + tn->stackDepth); JS_ASSERT(cx->regs().sp == fp->base() + tn->stackDepth);
switch (tn->kind) { switch (tn->kind) {
@ -178,7 +178,7 @@ static void
InlineReturn(VMFrame &f) InlineReturn(VMFrame &f)
{ {
JS_ASSERT(f.fp() != f.entryfp); JS_ASSERT(f.fp() != f.entryfp);
JS_ASSERT(!IsActiveWithOrBlock(f.cx, f.fp()->scopeChain(), 0)); JS_ASSERT(!js_IsActiveWithOrBlock(f.cx, &f.fp()->scopeChain(), 0));
f.cx->stack.popInlineFrame(f.regs); f.cx->stack.popInlineFrame(f.regs);
DebugOnly<JSOp> op = js_GetOpcode(f.cx, f.fp()->script(), f.regs.pc); DebugOnly<JSOp> op = js_GetOpcode(f.cx, f.fp()->script(), f.regs.pc);
@ -603,7 +603,7 @@ js_InternalThrow(VMFrame &f)
// and epilogues. RunTracer(), Interpret(), and Invoke() all // and epilogues. RunTracer(), Interpret(), and Invoke() all
// rely on this property. // rely on this property.
JS_ASSERT(!f.fp()->finishedInInterpreter()); JS_ASSERT(!f.fp()->finishedInInterpreter());
UnwindScope(cx, 0, cx->isExceptionPending()); js_UnwindScope(cx, 0, cx->isExceptionPending());
ScriptEpilogue(f.cx, f.fp(), false); ScriptEpilogue(f.cx, f.fp(), false);
// Don't remove the last frame, this is the responsibility of // Don't remove the last frame, this is the responsibility of
@ -782,7 +782,7 @@ HandleErrorInExcessFrame(VMFrame &f, StackFrame *stopFp, bool searchedTopmostFra
break; break;
/* Unwind and return. */ /* Unwind and return. */
returnOK &= UnwindScope(cx, 0, returnOK || cx->isExceptionPending()); returnOK &= bool(js_UnwindScope(cx, 0, returnOK || cx->isExceptionPending()));
returnOK = ScriptEpilogue(cx, fp, returnOK); returnOK = ScriptEpilogue(cx, fp, returnOK);
InlineReturn(f); InlineReturn(f);
} }

Просмотреть файл

@ -775,7 +775,7 @@ class CallCompiler : public BaseCompiler
RegisterID t0 = tempRegs.takeAnyReg().reg(); RegisterID t0 = tempRegs.takeAnyReg().reg();
/* Guard that it's actually a function object. */ /* Guard that it's actually a function object. */
Jump claspGuard = masm.testObjClass(Assembler::NotEqual, ic.funObjReg, &FunctionClass); Jump claspGuard = masm.testObjClass(Assembler::NotEqual, ic.funObjReg, &js_FunctionClass);
/* Guard that it's the same function. */ /* Guard that it's the same function. */
JSFunction *fun = obj->getFunctionPrivate(); JSFunction *fun = obj->getFunctionPrivate();

Просмотреть файл

@ -323,7 +323,7 @@ class SetPropCompiler : public PICStubCompiler
return error(); return error();
} }
JS_ASSERT_IF(!shape->hasDefaultSetter(), obj->isCall()); JS_ASSERT_IF(!shape->hasDefaultSetter(), obj->getClass() == &js_CallClass);
MaybeJump skipOver; MaybeJump skipOver;
@ -914,8 +914,8 @@ class GetPropCompiler : public PICStubCompiler
Assembler masm; Assembler masm;
masm.loadObjClass(pic.objReg, pic.shapeReg); masm.loadObjClass(pic.objReg, pic.shapeReg);
Jump isDense = masm.testClass(Assembler::Equal, pic.shapeReg, &ArrayClass); Jump isDense = masm.testClass(Assembler::Equal, pic.shapeReg, &js_ArrayClass);
Jump notArray = masm.testClass(Assembler::NotEqual, pic.shapeReg, &SlowArrayClass); Jump notArray = masm.testClass(Assembler::NotEqual, pic.shapeReg, &js_SlowArrayClass);
isDense.linkTo(masm.label(), &masm); isDense.linkTo(masm.label(), &masm);
masm.load32(Address(pic.objReg, offsetof(JSObject, privateData)), pic.objReg); masm.load32(Address(pic.objReg, offsetof(JSObject, privateData)), pic.objReg);
@ -1494,7 +1494,7 @@ class ScopeNameCompiler : public PICStubCompiler
* tree in ComputeImplicitThis. * tree in ComputeImplicitThis.
*/ */
if (pic.kind == ic::PICInfo::CALLNAME) { if (pic.kind == ic::PICInfo::CALLNAME) {
JS_ASSERT(obj->isCall()); JS_ASSERT(obj->getClass() == &js_CallClass);
Value *thisVp = &cx->regs().sp[1]; Value *thisVp = &cx->regs().sp[1];
Address thisSlot(JSFrameReg, StackFrame::offsetOfFixed(thisVp - cx->fp()->slots())); Address thisSlot(JSFrameReg, StackFrame::offsetOfFixed(thisVp - cx->fp()->slots()));
masm.storeValue(UndefinedValue(), thisSlot); masm.storeValue(UndefinedValue(), thisSlot);
@ -1597,7 +1597,7 @@ class ScopeNameCompiler : public PICStubCompiler
if (obj != getprop.holder) if (obj != getprop.holder)
return disable("property is on proto of a scope object"); return disable("property is on proto of a scope object");
if (obj->isCall()) if (obj->getClass() == &js_CallClass)
return generateCallStub(obj); return generateCallStub(obj);
LookupStatus status = getprop.testForGet(); LookupStatus status = getprop.testForGet();
@ -1641,7 +1641,7 @@ class ScopeNameCompiler : public PICStubCompiler
const Shape *shape = getprop.shape; const Shape *shape = getprop.shape;
JSObject *normalized = obj; JSObject *normalized = obj;
if (obj->isWith() && !shape->hasDefaultGetter()) if (obj->getClass() == &js_WithClass && !shape->hasDefaultGetter())
normalized = js_UnwrapWithObject(cx, obj); normalized = js_UnwrapWithObject(cx, obj);
NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, return false); NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, return false);
if (thisvp) if (thisvp)
@ -2049,7 +2049,7 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic)
#if JS_HAS_NO_SUCH_METHOD #if JS_HAS_NO_SUCH_METHOD
if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) { if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) {
regs.sp[-2].setString(JSID_TO_STRING(id)); regs.sp[-2].setString(JSID_TO_STRING(id));
if (!OnUnknownMethod(cx, regs.sp - 2)) if (!js_OnUnknownMethod(cx, regs.sp - 2))
THROW(); THROW();
} }
#endif #endif
@ -2805,7 +2805,7 @@ ic::CallElement(VMFrame &f, ic::GetElementIC *ic)
if (JS_UNLIKELY(f.regs.sp[-2].isPrimitive()) && thisv.isObject()) { if (JS_UNLIKELY(f.regs.sp[-2].isPrimitive()) && thisv.isObject()) {
f.regs.sp[-2] = f.regs.sp[-1]; f.regs.sp[-2] = f.regs.sp[-1];
f.regs.sp[-1].setObject(*thisObj); f.regs.sp[-1].setObject(*thisObj);
if (!OnUnknownMethod(cx, f.regs.sp - 2)) if (!js_OnUnknownMethod(cx, f.regs.sp - 2))
THROW(); THROW();
} else } else
#endif #endif

Просмотреть файл

@ -389,7 +389,7 @@ NameOp(VMFrame &f, JSObject *obj, bool callname)
} else { } else {
shape = (Shape *)prop; shape = (Shape *)prop;
JSObject *normalized = obj; JSObject *normalized = obj;
if (normalized->isWith() && !shape->hasDefaultGetter()) if (normalized->getClass() == &js_WithClass && !shape->hasDefaultGetter())
normalized = js_UnwrapWithObject(cx, normalized); normalized = js_UnwrapWithObject(cx, normalized);
NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL); NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL);
} }
@ -552,7 +552,7 @@ stubs::CallElem(VMFrame &f)
if (JS_UNLIKELY(regs.sp[-2].isPrimitive()) && thisv.isObject()) { if (JS_UNLIKELY(regs.sp[-2].isPrimitive()) && thisv.isObject()) {
regs.sp[-2] = regs.sp[-1]; regs.sp[-2] = regs.sp[-1];
regs.sp[-1].setObject(*thisObj); regs.sp[-1].setObject(*thisObj);
if (!OnUnknownMethod(cx, regs.sp - 2)) if (!js_OnUnknownMethod(cx, regs.sp - 2))
THROW(); THROW();
} else } else
#endif #endif
@ -1351,7 +1351,7 @@ stubs::NewInitObject(VMFrame &f, JSObject *baseobj)
if (!baseobj) { if (!baseobj) {
gc::AllocKind kind = GuessObjectGCKind(0, false); gc::AllocKind kind = GuessObjectGCKind(0, false);
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, kind); JSObject *obj = NewBuiltinClassInstance(cx, &js_ObjectClass, kind);
if (!obj) if (!obj)
THROW(); THROW();
if (type) if (type)
@ -1740,7 +1740,7 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom)
#if JS_HAS_NO_SUCH_METHOD #if JS_HAS_NO_SUCH_METHOD
if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) { if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) {
regs.sp[-2].setString(origAtom); regs.sp[-2].setString(origAtom);
if (!OnUnknownMethod(cx, regs.sp - 2)) if (!js_OnUnknownMethod(cx, regs.sp - 2))
THROW(); THROW();
} }
#endif #endif
@ -2016,9 +2016,10 @@ stubs::EnterBlock(VMFrame &f, JSObject *obj)
* static scope. * static scope.
*/ */
JSObject *obj2 = &fp->scopeChain(); JSObject *obj2 = &fp->scopeChain();
while (obj2->isWith()) Class *clasp;
while ((clasp = obj2->getClass()) == &js_WithClass)
obj2 = obj2->getParent(); obj2 = obj2->getParent();
if (obj2->isBlock() && if (clasp == &js_BlockClass &&
obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, fp)) { obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, fp)) {
JSObject *youngestProto = obj2->getProto(); JSObject *youngestProto = obj2->getProto();
JS_ASSERT(youngestProto->isStaticBlock()); JS_ASSERT(youngestProto->isStaticBlock());
@ -2048,7 +2049,7 @@ stubs::LeaveBlock(VMFrame &f, JSObject *blockChain)
*/ */
JSObject *obj = &fp->scopeChain(); JSObject *obj = &fp->scopeChain();
if (obj->getProto() == blockChain) { if (obj->getProto() == blockChain) {
JS_ASSERT(obj->isBlock()); JS_ASSERT(obj->getClass() == &js_BlockClass);
if (!js_PutBlockObject(cx, JS_TRUE)) if (!js_PutBlockObject(cx, JS_TRUE))
THROW(); THROW();
} }

Просмотреть файл

@ -1560,9 +1560,9 @@ ValueToScript(JSContext *cx, jsval v)
JSObject *obj = JSVAL_TO_OBJECT(v); JSObject *obj = JSVAL_TO_OBJECT(v);
JSClass *clasp = JS_GET_CLASS(cx, obj); JSClass *clasp = JS_GET_CLASS(cx, obj);
if (clasp == Jsvalify(&ScriptClass)) { if (clasp == Jsvalify(&js_ScriptClass)) {
script = (JSScript *) JS_GetPrivate(cx, obj); script = (JSScript *) JS_GetPrivate(cx, obj);
} else if (clasp == Jsvalify(&GeneratorClass)) { } else if (clasp == Jsvalify(&js_GeneratorClass)) {
JSGenerator *gen = (JSGenerator *) JS_GetPrivate(cx, obj); JSGenerator *gen = (JSGenerator *) JS_GetPrivate(cx, obj);
fun = gen->floatingFrame()->fun(); fun = gen->floatingFrame()->fun();
script = fun->script(); script = fun->script();
@ -1620,8 +1620,8 @@ GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp,
v = argv[0]; v = argv[0];
intarg = 0; intarg = 0;
if (!JSVAL_IS_PRIMITIVE(v) && if (!JSVAL_IS_PRIMITIVE(v) &&
(JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&FunctionClass) || (JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&js_FunctionClass) ||
JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&ScriptClass))) { JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&js_ScriptClass))) {
script = ValueToScript(cx, v); script = ValueToScript(cx, v);
if (!script) if (!script)
return JS_FALSE; return JS_FALSE;

Просмотреть файл

@ -368,12 +368,12 @@ class ReferenceFinder {
JSObject *object = static_cast<JSObject *>(cell); JSObject *object = static_cast<JSObject *>(cell);
/* Certain classes of object are for internal use only. */ /* Certain classes of object are for internal use only. */
if (object->isBlock() || JSClass *clasp = JS_GET_CLASS(context, object);
object->isCall() || if (clasp == Jsvalify(&js_BlockClass) ||
object->isWith() || clasp == Jsvalify(&js_CallClass) ||
object->isDeclEnv()) { clasp == Jsvalify(&js_WithClass) ||
clasp == Jsvalify(&js_DeclEnvClass))
return JSVAL_VOID; return JSVAL_VOID;
}
/* Internal function objects should also not be revealed. */ /* Internal function objects should also not be revealed. */
if (JS_ObjectIsFunction(context, object) && IsInternalFunctionObject(object)) if (JS_ObjectIsFunction(context, object) && IsInternalFunctionObject(object))

Просмотреть файл

@ -479,7 +479,7 @@ class Writer
} }
nj::LIns *ldpObjClasp(nj::LIns *obj, nj::LoadQual loadQual) const { nj::LIns *ldpObjClasp(nj::LIns *obj, nj::LoadQual loadQual) const {
return name(lir->insLoad(nj::LIR_ldp, obj, JSObject::offsetOfClassPointer(), ACCSET_OBJ_CLASP, return name(lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, clasp), ACCSET_OBJ_CLASP,
loadQual), loadQual),
"clasp"); "clasp");
} }

Просмотреть файл

@ -151,7 +151,7 @@ class ArgumentsObject : public ::JSObject
static const uint32 INITIAL_LENGTH_SLOT = 0; static const uint32 INITIAL_LENGTH_SLOT = 0;
static const uint32 DATA_SLOT = 1; static const uint32 DATA_SLOT = 1;
public: protected:
static const uint32 RESERVED_SLOTS = 2; static const uint32 RESERVED_SLOTS = 2;
private: private:
@ -240,6 +240,8 @@ class ArgumentsObject : public ::JSObject
*/ */
class NormalArgumentsObject : public ArgumentsObject class NormalArgumentsObject : public ArgumentsObject
{ {
static js::Class jsClass;
friend bool JSObject::isNormalArguments() const; friend bool JSObject::isNormalArguments() const;
friend struct EmptyShape; // for EmptyShape::getEmptyArgumentsShape friend struct EmptyShape; // for EmptyShape::getEmptyArgumentsShape
friend ArgumentsObject * friend ArgumentsObject *
@ -264,6 +266,8 @@ class NormalArgumentsObject : public ArgumentsObject
*/ */
class StrictArgumentsObject : public ArgumentsObject class StrictArgumentsObject : public ArgumentsObject
{ {
static js::Class jsClass;
friend bool JSObject::isStrictArguments() const; friend bool JSObject::isStrictArguments() const;
friend ArgumentsObject * friend ArgumentsObject *
ArgumentsObject::create(JSContext *cx, uint32 argc, JSObject &callee); ArgumentsObject::create(JSContext *cx, uint32 argc, JSObject &callee);
@ -271,6 +275,12 @@ class StrictArgumentsObject : public ArgumentsObject
} // namespace js } // namespace js
inline bool
JSObject::isNormalArguments() const
{
return getClass() == &js::NormalArgumentsObject::jsClass;
}
js::NormalArgumentsObject * js::NormalArgumentsObject *
JSObject::asNormalArguments() JSObject::asNormalArguments()
{ {
@ -278,6 +288,12 @@ JSObject::asNormalArguments()
return reinterpret_cast<js::NormalArgumentsObject *>(this); return reinterpret_cast<js::NormalArgumentsObject *>(this);
} }
inline bool
JSObject::isStrictArguments() const
{
return getClass() == &js::StrictArgumentsObject::jsClass;
}
js::StrictArgumentsObject * js::StrictArgumentsObject *
JSObject::asStrictArguments() JSObject::asStrictArguments()
{ {
@ -285,6 +301,12 @@ JSObject::asStrictArguments()
return reinterpret_cast<js::StrictArgumentsObject *>(this); return reinterpret_cast<js::StrictArgumentsObject *>(this);
} }
inline bool
JSObject::isArguments() const
{
return isNormalArguments() || isStrictArguments();
}
js::ArgumentsObject * js::ArgumentsObject *
JSObject::asArguments() JSObject::asArguments()
{ {

Просмотреть файл

@ -347,9 +347,9 @@ JS_STATIC_ASSERT(uintN(JSSLOT_DEBUGFRAME_OWNER) == uintN(JSSLOT_DEBUGSCRIPT_OWNE
Debugger * Debugger *
Debugger::fromChildJSObject(JSObject *obj) Debugger::fromChildJSObject(JSObject *obj)
{ {
JS_ASSERT(obj->getClass() == &DebuggerFrame_class || JS_ASSERT(obj->clasp == &DebuggerFrame_class ||
obj->getClass() == &DebuggerObject_class || obj->clasp == &DebuggerObject_class ||
obj->getClass() == &DebuggerScript_class); obj->clasp == &DebuggerScript_class);
JSObject *dbgobj = &obj->getReservedSlot(JSSLOT_DEBUGOBJECT_OWNER).toObject(); JSObject *dbgobj = &obj->getReservedSlot(JSSLOT_DEBUGOBJECT_OWNER).toObject();
return fromJSObject(dbgobj); return fromJSObject(dbgobj);
} }
@ -523,9 +523,9 @@ Debugger::unwrapDebuggeeValue(JSContext *cx, Value *vp)
assertSameCompartment(cx, object, *vp); assertSameCompartment(cx, object, *vp);
if (vp->isObject()) { if (vp->isObject()) {
JSObject *dobj = &vp->toObject(); JSObject *dobj = &vp->toObject();
if (dobj->getClass() != &DebuggerObject_class) { if (dobj->clasp != &DebuggerObject_class) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_EXPECTED_TYPE, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_EXPECTED_TYPE,
"Debugger", "Debugger.Object", dobj->getClass()->name); "Debugger", "Debugger.Object", dobj->clasp->name);
return false; return false;
} }
@ -587,7 +587,7 @@ Debugger::newCompletionValue(AutoCompartment &ac, bool ok, Value val, Value *vp)
return true; return true;
} }
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_ObjectClass);
if (!obj || if (!obj ||
!wrapDebuggeeValue(cx, &val) || !wrapDebuggeeValue(cx, &val) ||
!DefineNativeProperty(cx, obj, key, val, PropertyStub, StrictPropertyStub, !DefineNativeProperty(cx, obj, key, val, PropertyStub, StrictPropertyStub,
@ -1479,7 +1479,7 @@ Debugger::unwrapDebuggeeArgument(JSContext *cx, const Value &v)
*/ */
JSObject *obj = NonNullObject(cx, v); JSObject *obj = NonNullObject(cx, v);
if (obj) { if (obj) {
if (obj->getClass() == &DebuggerObject_class) { if (obj->clasp == &DebuggerObject_class) {
Value rv = v; Value rv = v;
if (!unwrapDebuggeeValue(cx, &rv)) if (!unwrapDebuggeeValue(cx, &rv))
return NULL; return NULL;
@ -1977,7 +1977,7 @@ DebuggerScript_check(JSContext *cx, const Value &v, const char *clsname, const c
return NULL; return NULL;
} }
JSObject *thisobj = &v.toObject(); JSObject *thisobj = &v.toObject();
if (thisobj->getClass() != &DebuggerScript_class) { if (thisobj->clasp != &DebuggerScript_class) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
clsname, fnname, thisobj->getClass()->name); clsname, fnname, thisobj->getClass()->name);
return NULL; return NULL;
@ -2947,7 +2947,7 @@ DebuggerFrameEval(JSContext *cx, uintN argc, Value *vp, EvalBindingsMode mode)
/* If evalWithBindings, create the inner scope object. */ /* If evalWithBindings, create the inner scope object. */
if (mode == WithBindings) { if (mode == WithBindings) {
/* TODO - Should probably create a With object here. */ /* TODO - Should probably create a With object here. */
scobj = NewNonFunction<WithProto::Given>(cx, &ObjectClass, NULL, scobj); scobj = NewNonFunction<WithProto::Given>(cx, &js_ObjectClass, NULL, scobj);
if (!scobj) if (!scobj)
return false; return false;
for (size_t i = 0; i < keys.length(); i++) { for (size_t i = 0; i < keys.length(); i++) {
@ -3040,7 +3040,7 @@ DebuggerObject_checkThis(JSContext *cx, const CallArgs &args, const char *fnname
return NULL; return NULL;
} }
JSObject *thisobj = &args.thisv().toObject(); JSObject *thisobj = &args.thisv().toObject();
if (thisobj->getClass() != &DebuggerObject_class) { if (thisobj->clasp != &DebuggerObject_class) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
"Debugger.Object", fnname, thisobj->getClass()->name); "Debugger.Object", fnname, thisobj->getClass()->name);
return NULL; return NULL;
@ -3098,7 +3098,7 @@ static JSBool
DebuggerObject_getClass(JSContext *cx, uintN argc, Value *vp) DebuggerObject_getClass(JSContext *cx, uintN argc, Value *vp)
{ {
THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "get class", args, refobj); THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "get class", args, refobj);
const char *s = refobj->getClass()->name; const char *s = refobj->clasp->name;
JSAtom *str = js_Atomize(cx, s, strlen(s)); JSAtom *str = js_Atomize(cx, s, strlen(s));
if (!str) if (!str)
return false; return false;

Просмотреть файл

@ -227,8 +227,8 @@ GlobalObject::createConstructor(JSContext *cx, Native ctor, Class *clasp, JSAtom
static JSObject * static JSObject *
CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &global) CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &global)
{ {
JS_ASSERT(clasp != &ObjectClass); JS_ASSERT(clasp != &js_ObjectClass);
JS_ASSERT(clasp != &FunctionClass); JS_ASSERT(clasp != &js_FunctionClass);
JSObject *blankProto = NewNonFunction<WithProto::Given>(cx, clasp, &proto, &global); JSObject *blankProto = NewNonFunction<WithProto::Given>(cx, clasp, &proto, &global);
if (!blankProto || !blankProto->setSingletonType(cx)) if (!blankProto || !blankProto->setSingletonType(cx))
@ -300,7 +300,7 @@ GlobalObject::getDebuggers()
Value debuggers = getReservedSlot(DEBUGGERS); Value debuggers = getReservedSlot(DEBUGGERS);
if (debuggers.isUndefined()) if (debuggers.isUndefined())
return NULL; return NULL;
JS_ASSERT(debuggers.toObject().getClass() == &GlobalDebuggees_class); JS_ASSERT(debuggers.toObject().clasp == &GlobalDebuggees_class);
return (DebuggerVector *) debuggers.toObject().getPrivate(); return (DebuggerVector *) debuggers.toObject().getPrivate();
} }

Просмотреть файл

@ -358,7 +358,7 @@ StackFrame::callObj() const
JS_ASSERT_IF(isNonEvalFunctionFrame() || isStrictEvalFrame(), hasCallObj()); JS_ASSERT_IF(isNonEvalFunctionFrame() || isStrictEvalFrame(), hasCallObj());
JSObject *pobj = &scopeChain(); JSObject *pobj = &scopeChain();
while (JS_UNLIKELY(!pobj->isCall())) { while (JS_UNLIKELY(pobj->getClass() != &js_CallClass)) {
JS_ASSERT(IsCacheableNonGlobalScope(pobj) || pobj->isWith()); JS_ASSERT(IsCacheableNonGlobalScope(pobj) || pobj->isWith());
pobj = pobj->getParent(); pobj = pobj->getParent();
} }

Просмотреть файл

@ -152,7 +152,7 @@ StackFrame::stealFrameAndSlots(Value *vp, StackFrame *otherfp,
otherfp->flags_ &= ~HAS_CALL_OBJ; otherfp->flags_ &= ~HAS_CALL_OBJ;
if (js_IsNamedLambda(fun())) { if (js_IsNamedLambda(fun())) {
JSObject *env = obj.getParent(); JSObject *env = obj.getParent();
JS_ASSERT(env->isDeclEnv()); JS_ASSERT(env->getClass() == &js_DeclEnvClass);
env->setPrivate(this); env->setPrivate(this);
} }
} }

Просмотреть файл

@ -55,7 +55,7 @@ namespace js {
inline StringObject * inline StringObject *
StringObject::create(JSContext *cx, JSString *str) StringObject::create(JSContext *cx, JSString *str)
{ {
JSObject *obj = NewBuiltinClassInstance(cx, &StringClass); JSObject *obj = NewBuiltinClassInstance(cx, &js_StringClass);
if (!obj) if (!obj)
return NULL; return NULL;
StringObject *strobj = obj->asString(); StringObject *strobj = obj->asString();
@ -67,8 +67,8 @@ StringObject::create(JSContext *cx, JSString *str)
inline StringObject * inline StringObject *
StringObject::createWithProto(JSContext *cx, JSString *str, JSObject &proto) StringObject::createWithProto(JSContext *cx, JSString *str, JSObject &proto)
{ {
JS_ASSERT(gc::FINALIZE_OBJECT2 == gc::GetGCObjectKind(JSCLASS_RESERVED_SLOTS(&StringClass))); JS_ASSERT(gc::FINALIZE_OBJECT2 == gc::GetGCObjectKind(JSCLASS_RESERVED_SLOTS(&js_StringClass)));
JSObject *obj = NewObjectWithClassProto(cx, &StringClass, &proto, gc::FINALIZE_OBJECT2); JSObject *obj = NewObjectWithClassProto(cx, &js_StringClass, &proto, gc::FINALIZE_OBJECT2);
if (!obj) if (!obj)
return NULL; return NULL;
StringObject *strobj = obj->asString(); StringObject *strobj = obj->asString();

Просмотреть файл

@ -808,7 +808,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
JS_snprintf(name, sizeof(name), "JS Object (%s - %s)", JS_snprintf(name, sizeof(name), "JS Object (%s - %s)",
clazz->name, si->GetJSClass()->name); clazz->name, si->GetJSClass()->name);
} }
else if(clazz == &js::ScriptClass) else if(clazz == &js_ScriptClass)
{ {
JSScript* script = (JSScript*) xpc_GetJSPrivate(obj); JSScript* script = (JSScript*) xpc_GetJSPrivate(obj);
if(script->filename) if(script->filename)
@ -822,7 +822,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
JS_snprintf(name, sizeof(name), "JS Object (Script)"); JS_snprintf(name, sizeof(name), "JS Object (Script)");
} }
} }
else if(clazz == &js::FunctionClass) else if(clazz == &js_FunctionClass)
{ {
JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj); JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj);
JSString* str = JS_GetFunctionId(fun); JSString* str = JS_GetFunctionId(fun);