[JAEGER] Merge from fatval.

This commit is contained in:
David Anderson 2010-05-30 20:07:48 -07:00
commit dff194f865
21 changed files with 884 additions and 538 deletions

View File

@ -89,17 +89,17 @@ namespace CType {
static void Finalize(JSContext* cx, JSObject* obj); static void Finalize(JSContext* cx, JSObject* obj);
static void FinalizeProtoClass(JSContext* cx, JSObject* obj); static void FinalizeProtoClass(JSContext* cx, JSObject* obj);
static JSBool PrototypeGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool PrototypeGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool NameGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool NameGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool SizeGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool SizeGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool PtrGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp); static JSBool PtrGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
static JSBool CreateArray(JSContext* cx, uintN argc, jsval* vp); static JSBool CreateArray(JSContext* cx, uintN argc, jsval* vp);
static JSBool ToString(JSContext* cx, uintN argc, jsval* vp); static JSBool ToString(JSContext* cx, uintN argc, jsval* vp);
static JSBool ToSource(JSContext* cx, uintN argc, jsval* vp); static JSBool ToSource(JSContext* cx, uintN argc, jsval* vp);
static JSBool HasInstance(JSContext* cx, JSObject* obj, jsval v, JSBool* bp); static JSBool HasInstance(JSContext* cx, JSObject* obj, const jsval* vp, JSBool* bp);
} }
namespace PointerType { namespace PointerType {
@ -107,11 +107,11 @@ namespace PointerType {
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc,
jsval* argv, jsval* rval); jsval* argv, jsval* rval);
static JSBool TargetTypeGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool TargetTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool ContentsGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool ContentsGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool ContentsSetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool ContentsSetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool IsNull(JSContext* cx, uintN argc, jsval* vp); static JSBool IsNull(JSContext* cx, uintN argc, jsval* vp);
} }
@ -121,12 +121,12 @@ namespace ArrayType {
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc,
jsval* argv, jsval* rval); jsval* argv, jsval* rval);
static JSBool ElementTypeGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool ElementTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool LengthGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool LengthGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool Getter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp); static JSBool Getter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
static JSBool Setter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp); static JSBool Setter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
static JSBool AddressOfElement(JSContext* cx, uintN argc, jsval* vp); static JSBool AddressOfElement(JSContext* cx, uintN argc, jsval* vp);
} }
@ -135,11 +135,11 @@ namespace StructType {
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc,
jsval* argv, jsval* rval); jsval* argv, jsval* rval);
static JSBool FieldsArrayGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool FieldsArrayGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool FieldGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool FieldGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool FieldSetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool FieldSetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool AddressOfField(JSContext* cx, uintN argc, jsval* vp); static JSBool AddressOfField(JSContext* cx, uintN argc, jsval* vp);
static JSBool Define(JSContext* cx, uintN argc, jsval* vp); static JSBool Define(JSContext* cx, uintN argc, jsval* vp);
@ -153,12 +153,12 @@ namespace FunctionType {
static JSBool Call(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, static JSBool Call(JSContext* cx, JSObject* obj, uintN argc, jsval* argv,
jsval* rval); jsval* rval);
static JSBool ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool ArgTypesGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool ReturnTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool ABIGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp); static JSBool ABIGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
static JSBool IsVariadicGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool IsVariadicGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
} }
@ -174,9 +174,9 @@ namespace CClosure {
namespace CData { namespace CData {
static void Finalize(JSContext* cx, JSObject* obj); static void Finalize(JSContext* cx, JSObject* obj);
static JSBool ValueGetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool ValueGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool ValueSetter(JSContext* cx, JSObject* obj, jsval idval, static JSBool ValueSetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp); jsval* vp);
static JSBool Address(JSContext* cx, uintN argc, jsval* vp); static JSBool Address(JSContext* cx, uintN argc, jsval* vp);
static JSBool ReadString(JSContext* cx, uintN argc, jsval* vp); static JSBool ReadString(JSContext* cx, uintN argc, jsval* vp);
@ -514,7 +514,7 @@ JSBool
TypeError(JSContext* cx, const char* expected, jsval actual) TypeError(JSContext* cx, const char* expected, jsval actual)
{ {
JSString* str = JS_ValueToSource(cx, actual); JSString* str = JS_ValueToSource(cx, actual);
js::AutoValueRooter root(cx, str); js::AutoStringRooter root(cx, str);
const char* src; const char* src;
if (str) { if (str) {
@ -682,7 +682,7 @@ InitTypeConstructor(JSContext* cx,
dataProto = JS_NewObject(cx, &sCDataProtoClass, CDataProto, parent); dataProto = JS_NewObject(cx, &sCDataProtoClass, CDataProto, parent);
if (!dataProto) if (!dataProto)
return false; return false;
js::AutoValueRooter protoroot(cx, dataProto); js::AutoObjectRooter protoroot(cx, dataProto);
// Define functions and properties on the 'dataProto' object that are common // Define functions and properties on the 'dataProto' object that are common
// to all CData objects created from this type constructor. (These will // to all CData objects created from this type constructor. (These will
@ -816,27 +816,27 @@ InitTypeClasses(JSContext* cx, JSObject* parent)
sPointerInstanceFunctions, sPointerInstanceProps, sPointerInstanceFunctions, sPointerInstanceProps,
protos[SLOT_POINTERPROTO], protos[SLOT_POINTERDATAPROTO])) protos[SLOT_POINTERPROTO], protos[SLOT_POINTERDATAPROTO]))
return false; return false;
js::AutoValueRooter proot(cx, protos[SLOT_POINTERDATAPROTO]); js::AutoObjectRooter proot(cx, protos[SLOT_POINTERDATAPROTO]);
if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto, if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
sArrayFunction, NULL, sArrayProps, sArrayFunction, NULL, sArrayProps,
sArrayInstanceFunctions, sArrayInstanceProps, sArrayInstanceFunctions, sArrayInstanceProps,
protos[SLOT_ARRAYPROTO], protos[SLOT_ARRAYDATAPROTO])) protos[SLOT_ARRAYPROTO], protos[SLOT_ARRAYDATAPROTO]))
return false; return false;
js::AutoValueRooter aroot(cx, protos[SLOT_ARRAYDATAPROTO]); js::AutoObjectRooter aroot(cx, protos[SLOT_ARRAYDATAPROTO]);
if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto, if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
sStructFunction, sStructFunctions, sStructProps, sStructFunction, sStructFunctions, sStructProps,
sStructInstanceFunctions, NULL, sStructInstanceFunctions, NULL,
protos[SLOT_STRUCTPROTO], protos[SLOT_STRUCTDATAPROTO])) protos[SLOT_STRUCTPROTO], protos[SLOT_STRUCTDATAPROTO]))
return false; return false;
js::AutoValueRooter sroot(cx, protos[SLOT_STRUCTDATAPROTO]); js::AutoObjectRooter sroot(cx, protos[SLOT_STRUCTDATAPROTO]);
if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto, if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
sFunctionFunction, NULL, sFunctionProps, NULL, NULL, sFunctionFunction, NULL, sFunctionProps, NULL, NULL,
protos[SLOT_FUNCTIONPROTO], protos[SLOT_FUNCTIONDATAPROTO])) protos[SLOT_FUNCTIONPROTO], protos[SLOT_FUNCTIONDATAPROTO]))
return false; return false;
js::AutoValueRooter froot(cx, protos[SLOT_FUNCTIONDATAPROTO]); js::AutoObjectRooter froot(cx, protos[SLOT_FUNCTIONDATAPROTO]);
protos[SLOT_CDATAPROTO] = CDataProto; protos[SLOT_CDATAPROTO] = CDataProto;
@ -1105,7 +1105,7 @@ jsvalToBool(JSContext* cx, jsval val, bool* result)
return i == 0 || i == 1; return i == 0 || i == 1;
} }
if (JSVAL_IS_DOUBLE(val)) { if (JSVAL_IS_DOUBLE(val)) {
jsdouble d = *JSVAL_TO_DOUBLE(val); jsdouble d = JSVAL_TO_DOUBLE(val);
*result = d != 0; *result = d != 0;
// Allow -0. // Allow -0.
return d == 1 || d == 0; return d == 1 || d == 0;
@ -1132,7 +1132,7 @@ jsvalToInteger(JSContext* cx, jsval val, IntegerType* result)
if (JSVAL_IS_DOUBLE(val)) { if (JSVAL_IS_DOUBLE(val)) {
// Don't silently lose bits here -- check that val really is an // Don't silently lose bits here -- check that val really is an
// integer value, and has the right sign. // integer value, and has the right sign.
jsdouble d = *JSVAL_TO_DOUBLE(val); jsdouble d = JSVAL_TO_DOUBLE(val);
return ConvertExact(d, result); return ConvertExact(d, result);
} }
if (!JSVAL_IS_PRIMITIVE(val)) { if (!JSVAL_IS_PRIMITIVE(val)) {
@ -1213,7 +1213,7 @@ jsvalToFloat(JSContext *cx, jsval val, FloatType* result)
return true; return true;
} }
if (JSVAL_IS_DOUBLE(val)) { if (JSVAL_IS_DOUBLE(val)) {
*result = FloatType(*JSVAL_TO_DOUBLE(val)); *result = FloatType(JSVAL_TO_DOUBLE(val));
return true; return true;
} }
if (!JSVAL_IS_PRIMITIVE(val)) { if (!JSVAL_IS_PRIMITIVE(val)) {
@ -1275,7 +1275,7 @@ jsvalToBigInteger(JSContext* cx,
if (JSVAL_IS_DOUBLE(val)) { if (JSVAL_IS_DOUBLE(val)) {
// Don't silently lose bits here -- check that val really is an // Don't silently lose bits here -- check that val really is an
// integer value, and has the right sign. // integer value, and has the right sign.
jsdouble d = *JSVAL_TO_DOUBLE(val); jsdouble d = JSVAL_TO_DOUBLE(val);
return ConvertExact(d, result); return ConvertExact(d, result);
} }
if (allowString && JSVAL_IS_STRING(val)) { if (allowString && JSVAL_IS_STRING(val)) {
@ -1338,7 +1338,7 @@ jsvalToIntegerExplicit(JSContext* cx, jsval val, IntegerType* result)
if (JSVAL_IS_DOUBLE(val)) { if (JSVAL_IS_DOUBLE(val)) {
// Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast. // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
jsdouble d = *JSVAL_TO_DOUBLE(val); jsdouble d = JSVAL_TO_DOUBLE(val);
*result = FloatIsFinite(d) ? IntegerType(d) : 0; *result = FloatIsFinite(d) ? IntegerType(d) : 0;
return true; return true;
} }
@ -1371,7 +1371,7 @@ jsvalToPtrExplicit(JSContext* cx, jsval val, uintptr_t* result)
return true; return true;
} }
if (JSVAL_IS_DOUBLE(val)) { if (JSVAL_IS_DOUBLE(val)) {
jsdouble d = *JSVAL_TO_DOUBLE(val); jsdouble d = JSVAL_TO_DOUBLE(val);
if (d < 0) { if (d < 0) {
// Cast through an intptr_t intermediate to sign-extend. // Cast through an intptr_t intermediate to sign-extend.
intptr_t i = Convert<intptr_t>(d); intptr_t i = Convert<intptr_t>(d);
@ -1858,11 +1858,11 @@ ImplicitConvert(JSContext* cx,
for (jsuint i = 0; i < sourceLength; ++i) { for (jsuint i = 0; i < sourceLength; ++i) {
js::AutoValueRooter item(cx); js::AutoValueRooter item(cx);
if (!JS_GetElement(cx, sourceArray, i, item.addr())) if (!JS_GetElement(cx, sourceArray, i, Jsvalify(item.addr())))
return false; return false;
char* data = intermediate.get() + elementSize * i; char* data = intermediate.get() + elementSize * i;
if (!ImplicitConvert(cx, item.value(), baseType, data, false, NULL)) if (!ImplicitConvert(cx, Jsvalify(item.value()), baseType, data, false, NULL))
return false; return false;
} }
@ -1883,7 +1883,7 @@ ImplicitConvert(JSContext* cx,
JSObject* iter = JS_NewPropertyIterator(cx, obj); JSObject* iter = JS_NewPropertyIterator(cx, obj);
if (!iter) if (!iter)
return false; return false;
js::AutoValueRooter iterroot(cx, iter); js::AutoObjectRooter iterroot(cx, iter);
// Convert into an intermediate, in case of failure. // Convert into an intermediate, in case of failure.
size_t structSize = CType::GetSize(cx, targetType); size_t structSize = CType::GetSize(cx, targetType);
@ -1902,26 +1902,25 @@ ImplicitConvert(JSContext* cx,
break; break;
js::AutoValueRooter fieldVal(cx); js::AutoValueRooter fieldVal(cx);
if (!JS_IdToValue(cx, id, fieldVal.addr())) JS_IdToValue(cx, id, Jsvalify(fieldVal.addr()));
return false; if (!fieldVal.value().isString()) {
if (!JSVAL_IS_STRING(fieldVal.value())) {
JS_ReportError(cx, "property name is not a string"); JS_ReportError(cx, "property name is not a string");
return false; return false;
} }
const FieldInfo* field = StructType::LookupField(cx, targetType, const FieldInfo* field = StructType::LookupField(cx, targetType,
fieldVal.value()); Jsvalify(fieldVal.value()));
if (!field) if (!field)
return false; return false;
JSString* name = JSVAL_TO_STRING(fieldVal.value()); JSString* name = fieldVal.value().asString();
js::AutoValueRooter prop(cx); js::AutoValueRooter prop(cx);
if (!JS_GetUCProperty(cx, obj, name->chars(), name->length(), prop.addr())) if (!JS_GetUCProperty(cx, obj, name->chars(), name->length(), Jsvalify(prop.addr())))
return false; return false;
// Convert the field via ImplicitConvert(). // Convert the field via ImplicitConvert().
char* fieldData = intermediate.get() + field->mOffset; char* fieldData = intermediate.get() + field->mOffset;
if (!ImplicitConvert(cx, prop.value(), field->mType, fieldData, false, NULL)) if (!ImplicitConvert(cx, Jsvalify(prop.value()), field->mType, fieldData, false, NULL))
return false; return false;
++i; ++i;
@ -1962,7 +1961,7 @@ ExplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer)
// hard failure (out of memory, or some other similarly serious condition). // hard failure (out of memory, or some other similarly serious condition).
// We store any pending exception in case we need to re-throw it. // We store any pending exception in case we need to re-throw it.
js::AutoValueRooter ex(cx); js::AutoValueRooter ex(cx);
if (!JS_GetPendingException(cx, ex.addr())) if (!JS_GetPendingException(cx, Jsvalify(ex.addr())))
return false; return false;
// Otherwise, assume soft failure. Clear the pending exception so that we // Otherwise, assume soft failure. Clear the pending exception so that we
@ -2010,7 +2009,7 @@ ExplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer)
case TYPE_array: case TYPE_array:
case TYPE_struct: case TYPE_struct:
// ImplicitConvert is sufficient. Re-throw the exception it generated. // ImplicitConvert is sufficient. Re-throw the exception it generated.
JS_SetPendingException(cx, ex.value()); JS_SetPendingException(cx, Jsvalify(ex.value()));
return false; return false;
case TYPE_void_t: case TYPE_void_t:
case TYPE_function: case TYPE_function:
@ -2528,7 +2527,7 @@ CType::Create(JSContext* cx,
JSObject* typeObj = JS_NewObject(cx, &sCTypeClass, typeProto, parent); JSObject* typeObj = JS_NewObject(cx, &sCTypeClass, typeProto, parent);
if (!typeObj) if (!typeObj)
return NULL; return NULL;
js::AutoValueRooter root(cx, typeObj); js::AutoObjectRooter root(cx, typeObj);
// Set up the reserved slots. // Set up the reserved slots.
if (!JS_SetReservedSlot(cx, typeObj, SLOT_TYPECODE, INT_TO_JSVAL(type)) || if (!JS_SetReservedSlot(cx, typeObj, SLOT_TYPECODE, INT_TO_JSVAL(type)) ||
@ -2543,7 +2542,7 @@ CType::Create(JSContext* cx,
JSObject* prototype = JS_NewObject(cx, &sCDataProtoClass, dataProto, parent); JSObject* prototype = JS_NewObject(cx, &sCDataProtoClass, dataProto, parent);
if (!prototype) if (!prototype)
return NULL; return NULL;
js::AutoValueRooter protoroot(cx, prototype); js::AutoObjectRooter protoroot(cx, prototype);
if (!JS_DefineProperty(cx, prototype, "constructor", OBJECT_TO_JSVAL(typeObj), if (!JS_DefineProperty(cx, prototype, "constructor", OBJECT_TO_JSVAL(typeObj),
NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT)) NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT))
@ -2581,7 +2580,7 @@ CType::DefineBuiltin(JSContext* cx,
JSString* nameStr = JS_NewStringCopyZ(cx, name); JSString* nameStr = JS_NewStringCopyZ(cx, name);
if (!nameStr) if (!nameStr)
return NULL; return NULL;
js::AutoValueRooter nameRoot(cx, nameStr); js::AutoStringRooter nameRoot(cx, nameStr);
// Create a new CType object with the common properties and slots. // Create a new CType object with the common properties and slots.
JSObject* typeObj = Create(cx, typeProto, dataProto, type, nameStr, size, JSObject* typeObj = Create(cx, typeProto, dataProto, type, nameStr, size,
@ -2807,7 +2806,7 @@ CType::GetSafeSize(JSContext* cx, JSObject* obj, size_t* result)
return true; return true;
} }
if (JSVAL_IS_DOUBLE(size)) { if (JSVAL_IS_DOUBLE(size)) {
*result = Convert<size_t>(*JSVAL_TO_DOUBLE(size)); *result = Convert<size_t>(JSVAL_TO_DOUBLE(size));
return true; return true;
} }
@ -2830,7 +2829,7 @@ CType::GetSize(JSContext* cx, JSObject* obj)
// For callers who know it can never be JSVAL_VOID, return a size_t directly. // For callers who know it can never be JSVAL_VOID, return a size_t directly.
if (JSVAL_IS_INT(size)) if (JSVAL_IS_INT(size))
return JSVAL_TO_INT(size); return JSVAL_TO_INT(size);
return Convert<size_t>(*JSVAL_TO_DOUBLE(size)); return Convert<size_t>(JSVAL_TO_DOUBLE(size));
} }
bool bool
@ -2943,7 +2942,7 @@ CType::GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
} }
JSBool JSBool
CType::PrototypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) CType::PrototypeGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CType::IsCType(cx, obj)) { if (!CType::IsCType(cx, obj)) {
JS_ReportError(cx, "not a CType"); JS_ReportError(cx, "not a CType");
@ -2956,7 +2955,7 @@ CType::PrototypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
} }
JSBool JSBool
CType::NameGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) CType::NameGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CType::IsCType(cx, obj)) { if (!CType::IsCType(cx, obj)) {
JS_ReportError(cx, "not a CType"); JS_ReportError(cx, "not a CType");
@ -2972,7 +2971,7 @@ CType::NameGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
} }
JSBool JSBool
CType::SizeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) CType::SizeGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CType::IsCType(cx, obj)) { if (!CType::IsCType(cx, obj)) {
JS_ReportError(cx, "not a CType"); JS_ReportError(cx, "not a CType");
@ -2985,7 +2984,7 @@ CType::SizeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
} }
JSBool JSBool
CType::PtrGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) CType::PtrGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CType::IsCType(cx, obj)) { if (!CType::IsCType(cx, obj)) {
JS_ReportError(cx, "not a CType"); JS_ReportError(cx, "not a CType");
@ -3078,7 +3077,7 @@ CType::ToSource(JSContext* cx, uintN argc, jsval *vp)
} }
JSBool JSBool
CType::HasInstance(JSContext* cx, JSObject* obj, jsval v, JSBool* bp) CType::HasInstance(JSContext* cx, JSObject* obj, const jsval* vp, JSBool* bp)
{ {
JS_ASSERT(CType::IsCType(cx, obj)); JS_ASSERT(CType::IsCType(cx, obj));
@ -3089,10 +3088,10 @@ CType::HasInstance(JSContext* cx, JSObject* obj, jsval v, JSBool* bp)
JS_ASSERT(JS_GET_CLASS(cx, prototype) == &sCDataProtoClass); JS_ASSERT(JS_GET_CLASS(cx, prototype) == &sCDataProtoClass);
*bp = JS_FALSE; *bp = JS_FALSE;
if (JSVAL_IS_PRIMITIVE(v)) if (JSVAL_IS_PRIMITIVE(*vp))
return JS_TRUE; return JS_TRUE;
JSObject* proto = JSVAL_TO_OBJECT(v); JSObject* proto = JSVAL_TO_OBJECT(*vp);
while ((proto = JS_GetPrototype(cx, proto))) { while ((proto = JS_GetPrototype(cx, proto))) {
if (proto == prototype) { if (proto == prototype) {
*bp = JS_TRUE; *bp = JS_TRUE;
@ -3152,7 +3151,7 @@ PointerType::CreateInternal(JSContext* cx, JSObject* baseType)
&ffi_type_pointer); &ffi_type_pointer);
if (!typeObj) if (!typeObj)
return NULL; return NULL;
js::AutoValueRooter root(cx, typeObj); js::AutoObjectRooter root(cx, typeObj);
// Set the target type. (This will be 'null' for an opaque pointer type.) // Set the target type. (This will be 'null' for an opaque pointer type.)
if (!JS_SetReservedSlot(cx, typeObj, SLOT_TARGET_T, OBJECT_TO_JSVAL(baseType))) if (!JS_SetReservedSlot(cx, typeObj, SLOT_TARGET_T, OBJECT_TO_JSVAL(baseType)))
@ -3237,7 +3236,7 @@ PointerType::GetBaseType(JSContext* cx, JSObject* obj)
JSBool JSBool
PointerType::TargetTypeGetter(JSContext* cx, PointerType::TargetTypeGetter(JSContext* cx,
JSObject* obj, JSObject* obj,
jsval idval, jsid idval,
jsval* vp) jsval* vp)
{ {
if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_pointer) { if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_pointer) {
@ -3277,7 +3276,7 @@ PointerType::IsNull(JSContext* cx, uintN argc, jsval* vp)
JSBool JSBool
PointerType::ContentsGetter(JSContext* cx, PointerType::ContentsGetter(JSContext* cx,
JSObject* obj, JSObject* obj,
jsval idval, jsid idval,
jsval* vp) jsval* vp)
{ {
if (!CData::IsCData(cx, obj)) { if (!CData::IsCData(cx, obj)) {
@ -3315,7 +3314,7 @@ PointerType::ContentsGetter(JSContext* cx,
JSBool JSBool
PointerType::ContentsSetter(JSContext* cx, PointerType::ContentsSetter(JSContext* cx,
JSObject* obj, JSObject* obj,
jsval idval, jsid idval,
jsval* vp) jsval* vp)
{ {
if (!CData::IsCData(cx, obj)) { if (!CData::IsCData(cx, obj)) {
@ -3422,7 +3421,7 @@ ArrayType::CreateInternal(JSContext* cx,
sizeVal, INT_TO_JSVAL(align), NULL); sizeVal, INT_TO_JSVAL(align), NULL);
if (!typeObj) if (!typeObj)
return NULL; return NULL;
js::AutoValueRooter root(cx, typeObj); js::AutoObjectRooter root(cx, typeObj);
// Set the element type. // Set the element type.
if (!JS_SetReservedSlot(cx, typeObj, SLOT_ELEMENT_T, OBJECT_TO_JSVAL(baseType))) if (!JS_SetReservedSlot(cx, typeObj, SLOT_ELEMENT_T, OBJECT_TO_JSVAL(baseType)))
@ -3477,8 +3476,8 @@ ArrayType::ConstructData(JSContext* cx,
// This could be a JS array, or a CData array. // This could be a JS array, or a CData array.
JSObject* arg = JSVAL_TO_OBJECT(argv[0]); JSObject* arg = JSVAL_TO_OBJECT(argv[0]);
js::AutoValueRooter lengthVal(cx); js::AutoValueRooter lengthVal(cx);
if (!JS_GetProperty(cx, arg, "length", lengthVal.addr()) || if (!JS_GetProperty(cx, arg, "length", Jsvalify(lengthVal.addr())) ||
!jsvalToSize(cx, lengthVal.value(), false, &length)) { !jsvalToSize(cx, Jsvalify(lengthVal.value()), false, &length)) {
JS_ReportError(cx, "argument must be an array object or length"); JS_ReportError(cx, "argument must be an array object or length");
return JS_FALSE; return JS_FALSE;
} }
@ -3521,7 +3520,7 @@ ArrayType::ConstructData(JSContext* cx,
} }
// Root the CType object, in case we created one above. // Root the CType object, in case we created one above.
js::AutoValueRooter root(cx, obj); js::AutoObjectRooter root(cx, obj);
JSObject* result = CData::Create(cx, obj, NULL, NULL, true); JSObject* result = CData::Create(cx, obj, NULL, NULL, true);
if (!result) if (!result)
@ -3565,7 +3564,7 @@ ArrayType::GetSafeLength(JSContext* cx, JSObject* obj, size_t* result)
return true; return true;
} }
if (JSVAL_IS_DOUBLE(length)) { if (JSVAL_IS_DOUBLE(length)) {
*result = Convert<size_t>(*JSVAL_TO_DOUBLE(length)); *result = Convert<size_t>(JSVAL_TO_DOUBLE(length));
return true; return true;
} }
@ -3589,7 +3588,7 @@ ArrayType::GetLength(JSContext* cx, JSObject* obj)
// For callers who know it can never be JSVAL_VOID, return a size_t directly. // For callers who know it can never be JSVAL_VOID, return a size_t directly.
if (JSVAL_IS_INT(length)) if (JSVAL_IS_INT(length))
return JSVAL_TO_INT(length); return JSVAL_TO_INT(length);
return Convert<size_t>(*JSVAL_TO_DOUBLE(length)); return Convert<size_t>(JSVAL_TO_DOUBLE(length));
} }
ffi_type* ffi_type*
@ -3636,7 +3635,7 @@ ArrayType::BuildFFIType(JSContext* cx, JSObject* obj)
} }
JSBool JSBool
ArrayType::ElementTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) ArrayType::ElementTypeGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_array) { if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_array) {
JS_ReportError(cx, "not an ArrayType"); JS_ReportError(cx, "not an ArrayType");
@ -3649,7 +3648,7 @@ ArrayType::ElementTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* v
} }
JSBool JSBool
ArrayType::LengthGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) ArrayType::LengthGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
// This getter exists for both CTypes and CDatas of the ArrayType persuasion. // This getter exists for both CTypes and CDatas of the ArrayType persuasion.
// If we're dealing with a CData, get the CType from it. // If we're dealing with a CData, get the CType from it.
@ -3667,7 +3666,7 @@ ArrayType::LengthGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
} }
JSBool JSBool
ArrayType::Getter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) ArrayType::Getter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
// This should never happen, but we'll check to be safe. // This should never happen, but we'll check to be safe.
if (!CData::IsCData(cx, obj)) { if (!CData::IsCData(cx, obj)) {
@ -3702,7 +3701,7 @@ ArrayType::Getter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
} }
JSBool JSBool
ArrayType::Setter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) ArrayType::Setter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
// This should never happen, but we'll check to be safe. // This should never happen, but we'll check to be safe.
if (!CData::IsCData(cx, obj)) { if (!CData::IsCData(cx, obj)) {
@ -3762,7 +3761,7 @@ ArrayType::AddressOfElement(JSContext* cx, uintN argc, jsval *vp)
JSObject* pointerType = PointerType::CreateInternal(cx, baseType); JSObject* pointerType = PointerType::CreateInternal(cx, baseType);
if (!pointerType) if (!pointerType)
return JS_FALSE; return JS_FALSE;
js::AutoValueRooter root(cx, pointerType); js::AutoObjectRooter root(cx, pointerType);
// Create a PointerType CData object containing null. // Create a PointerType CData object containing null.
JSObject* result = CData::Create(cx, pointerType, NULL, NULL, true); JSObject* result = CData::Create(cx, pointerType, NULL, NULL, true);
@ -3805,20 +3804,19 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
JSObject* iter = JS_NewPropertyIterator(cx, obj); JSObject* iter = JS_NewPropertyIterator(cx, obj);
if (!iter) if (!iter)
return NULL; return NULL;
js::AutoValueRooter iterroot(cx, iter); js::AutoObjectRooter iterroot(cx, iter);
jsid id; jsid id;
if (!JS_NextProperty(cx, iter, &id)) if (!JS_NextProperty(cx, iter, &id))
return NULL; return NULL;
js::AutoValueRooter nameVal(cx); js::AutoValueRooter nameVal(cx);
if (!JS_IdToValue(cx, id, nameVal.addr())) JS_IdToValue(cx, id, Jsvalify(nameVal.addr()));
return NULL; if (!nameVal.value().isString()) {
if (!JSVAL_IS_STRING(nameVal.value())) {
JS_ReportError(cx, "struct field descriptors require a valid name and type"); JS_ReportError(cx, "struct field descriptors require a valid name and type");
return NULL; return NULL;
} }
JSString* name = JSVAL_TO_STRING(nameVal.value()); JSString* name = nameVal.value().asString();
// make sure we have one, and only one, property // make sure we have one, and only one, property
if (!JS_NextProperty(cx, iter, &id)) if (!JS_NextProperty(cx, iter, &id))
@ -3829,11 +3827,11 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
} }
js::AutoValueRooter propVal(cx); js::AutoValueRooter propVal(cx);
if (!JS_GetUCProperty(cx, obj, name->chars(), name->length(), propVal.addr())) if (!JS_GetUCProperty(cx, obj, name->chars(), name->length(), Jsvalify(propVal.addr())))
return NULL; return NULL;
if (JSVAL_IS_PRIMITIVE(propVal.value()) || if (propVal.value().isPrimitive() ||
!CType::IsCType(cx, JSVAL_TO_OBJECT(propVal.value()))) { !CType::IsCType(cx, &propVal.value().asObject())) {
JS_ReportError(cx, "struct field descriptors require a valid name and type"); JS_ReportError(cx, "struct field descriptors require a valid name and type");
return NULL; return NULL;
} }
@ -3841,7 +3839,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
// Undefined size or zero size struct members are illegal. // Undefined size or zero size struct members are illegal.
// (Zero-size arrays are legal as struct members in C++, but libffi will // (Zero-size arrays are legal as struct members in C++, but libffi will
// choke on a zero-size struct, so we disallow them.) // choke on a zero-size struct, so we disallow them.)
*typeObj = JSVAL_TO_OBJECT(propVal.value()); *typeObj = &propVal.value().asObject();
size_t size; size_t size;
if (!CType::GetSafeSize(cx, *typeObj, &size) || size == 0) { if (!CType::GetSafeSize(cx, *typeObj, &size) || size == 0) {
JS_ReportError(cx, "struct field types must have defined and nonzero size"); JS_ReportError(cx, "struct field types must have defined and nonzero size");
@ -3902,7 +3900,7 @@ StructType::Create(JSContext* cx, uintN argc, jsval* vp)
JSVAL_TO_STRING(name), JSVAL_VOID, JSVAL_VOID, NULL); JSVAL_TO_STRING(name), JSVAL_VOID, JSVAL_VOID, NULL);
if (!result) if (!result)
return JS_FALSE; return JS_FALSE;
js::AutoValueRooter root(cx, result); js::AutoObjectRooter root(cx, result);
if (argc == 2) { if (argc == 2) {
if (JSVAL_IS_PRIMITIVE(argv[1]) || if (JSVAL_IS_PRIMITIVE(argv[1]) ||
@ -3937,7 +3935,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj
JSObject* prototype = JS_NewObject(cx, &sCDataProtoClass, dataProto, NULL); JSObject* prototype = JS_NewObject(cx, &sCDataProtoClass, dataProto, NULL);
if (!prototype) if (!prototype)
return JS_FALSE; return JS_FALSE;
js::AutoValueRooter protoroot(cx, prototype); js::AutoObjectRooter protoroot(cx, prototype);
if (!JS_DefineProperty(cx, prototype, "constructor", OBJECT_TO_JSVAL(typeObj), if (!JS_DefineProperty(cx, prototype, "constructor", OBJECT_TO_JSVAL(typeObj),
NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT)) NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT))
@ -3967,11 +3965,11 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj
for (jsuint i = 0; i < len; ++i) { for (jsuint i = 0; i < len; ++i) {
js::AutoValueRooter item(cx); js::AutoValueRooter item(cx);
if (!JS_GetElement(cx, fieldsObj, i, item.addr())) if (!JS_GetElement(cx, fieldsObj, i, Jsvalify(item.addr())))
return JS_FALSE; return JS_FALSE;
JSObject* fieldType; JSObject* fieldType;
JSString* name = ExtractStructField(cx, item.value(), &fieldType); JSString* name = ExtractStructField(cx, Jsvalify(item.value()), &fieldType);
if (!name) if (!name)
return JS_FALSE; return JS_FALSE;
@ -4268,10 +4266,10 @@ StructType::BuildFieldsArray(JSContext* cx, JSObject* obj)
// Prepare a new array for the 'fields' property of the StructType. // Prepare a new array for the 'fields' property of the StructType.
jsval* fieldsVec; jsval* fieldsVec;
JSObject* fieldsProp = JSObject* fieldsProp =
js_NewArrayObjectWithCapacity(cx, len, &fieldsVec); js_NewArrayObjectWithCapacity(cx, len, Valueify(&fieldsVec));
if (!fieldsProp) if (!fieldsProp)
return NULL; return NULL;
js::AutoValueRooter root(cx, fieldsProp); js::AutoObjectRooter root(cx, fieldsProp);
JS_ASSERT(len == 0 || fieldsVec); JS_ASSERT(len == 0 || fieldsVec);
for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) { for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
@ -4290,7 +4288,7 @@ StructType::BuildFieldsArray(JSContext* cx, JSObject* obj)
} }
JSBool JSBool
StructType::FieldsArrayGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) StructType::FieldsArrayGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_struct) { if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_struct) {
JS_ReportError(cx, "not a StructType"); JS_ReportError(cx, "not a StructType");
@ -4320,7 +4318,7 @@ StructType::FieldsArrayGetter(JSContext* cx, JSObject* obj, jsval idval, jsval*
} }
JSBool JSBool
StructType::FieldGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) StructType::FieldGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CData::IsCData(cx, obj)) { if (!CData::IsCData(cx, obj)) {
JS_ReportError(cx, "not a CData"); JS_ReportError(cx, "not a CData");
@ -4342,7 +4340,7 @@ StructType::FieldGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
} }
JSBool JSBool
StructType::FieldSetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) StructType::FieldSetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CData::IsCData(cx, obj)) { if (!CData::IsCData(cx, obj)) {
JS_ReportError(cx, "not a CData"); JS_ReportError(cx, "not a CData");
@ -4393,7 +4391,7 @@ StructType::AddressOfField(JSContext* cx, uintN argc, jsval *vp)
JSObject* pointerType = PointerType::CreateInternal(cx, baseType); JSObject* pointerType = PointerType::CreateInternal(cx, baseType);
if (!pointerType) if (!pointerType)
return JS_FALSE; return JS_FALSE;
js::AutoValueRooter root(cx, pointerType); js::AutoObjectRooter root(cx, pointerType);
// Create a PointerType CData object containing null. // Create a PointerType CData object containing null.
JSObject* result = CData::Create(cx, pointerType, NULL, NULL, true); JSObject* result = CData::Create(cx, pointerType, NULL, NULL, true);
@ -4689,7 +4687,7 @@ FunctionType::Create(JSContext* cx, uintN argc, jsval* vp)
// Pull out the argument types from the array, if any. // Pull out the argument types from the array, if any.
JS_ASSERT(!argTypes.length() || arrayObj); JS_ASSERT(!argTypes.length() || arrayObj);
js::AutoArrayRooter items(cx, argTypes.length(), argTypes.begin()); js::AutoArrayRooter items(cx, argTypes.length(), Valueify(argTypes.begin()));
for (jsuint i = 0; i < argTypes.length(); ++i) { for (jsuint i = 0; i < argTypes.length(); ++i) {
if (!JS_GetElement(cx, arrayObj, i, &argTypes[i])) if (!JS_GetElement(cx, arrayObj, i, &argTypes[i]))
return JS_FALSE; return JS_FALSE;
@ -4728,7 +4726,7 @@ FunctionType::CreateInternal(JSContext* cx,
NULL, JSVAL_VOID, JSVAL_VOID, NULL); NULL, JSVAL_VOID, JSVAL_VOID, NULL);
if (!typeObj) if (!typeObj)
return NULL; return NULL;
js::AutoValueRooter root(cx, typeObj); js::AutoObjectRooter root(cx, typeObj);
// Stash the FunctionInfo in a reserved slot. // Stash the FunctionInfo in a reserved slot.
if (!JS_SetReservedSlot(cx, typeObj, SLOT_FNINFO, if (!JS_SetReservedSlot(cx, typeObj, SLOT_FNINFO,
@ -4759,7 +4757,7 @@ FunctionType::ConstructData(JSContext* cx,
JSObject* closureObj = CClosure::Create(cx, typeObj, fnObj, thisObj, data); JSObject* closureObj = CClosure::Create(cx, typeObj, fnObj, thisObj, data);
if (!closureObj) if (!closureObj)
return JS_FALSE; return JS_FALSE;
js::AutoValueRooter root(cx, closureObj); js::AutoObjectRooter root(cx, closureObj);
// Set the closure object as the referent of the new CData object. // Set the closure object as the referent of the new CData object.
if (!JS_SetReservedSlot(cx, dataObj, SLOT_REFERENT, if (!JS_SetReservedSlot(cx, dataObj, SLOT_REFERENT,
@ -4944,7 +4942,7 @@ CheckFunctionType(JSContext* cx, JSObject* obj)
} }
JSBool JSBool
FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CheckFunctionType(cx, obj)) if (!CheckFunctionType(cx, obj))
return JS_FALSE; return JS_FALSE;
@ -4960,10 +4958,10 @@ FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* v
// Prepare a new array. // Prepare a new array.
jsval* vec; jsval* vec;
JSObject* argTypes = JSObject* argTypes =
js_NewArrayObjectWithCapacity(cx, len, &vec); js_NewArrayObjectWithCapacity(cx, len, Valueify(&vec));
if (!argTypes) if (!argTypes)
return JS_FALSE; return JS_FALSE;
js::AutoValueRooter argsroot(cx, argTypes); js::AutoObjectRooter argsroot(cx, argTypes);
JS_ASSERT(len == 0 || vec); JS_ASSERT(len == 0 || vec);
for (size_t i = 0; i < len; ++i) for (size_t i = 0; i < len; ++i)
@ -4979,7 +4977,7 @@ FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* v
} }
JSBool JSBool
FunctionType::ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) FunctionType::ReturnTypeGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CheckFunctionType(cx, obj)) if (!CheckFunctionType(cx, obj))
return JS_FALSE; return JS_FALSE;
@ -4990,7 +4988,7 @@ FunctionType::ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval*
} }
JSBool JSBool
FunctionType::ABIGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) FunctionType::ABIGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CheckFunctionType(cx, obj)) if (!CheckFunctionType(cx, obj))
return JS_FALSE; return JS_FALSE;
@ -5001,7 +4999,7 @@ FunctionType::ABIGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
} }
JSBool JSBool
FunctionType::IsVariadicGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) FunctionType::IsVariadicGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!CheckFunctionType(cx, obj)) if (!CheckFunctionType(cx, obj))
return JS_FALSE; return JS_FALSE;
@ -5024,7 +5022,7 @@ CClosure::Create(JSContext* cx,
JSObject* result = JS_NewObject(cx, &sCClosureClass, NULL, NULL); JSObject* result = JS_NewObject(cx, &sCClosureClass, NULL, NULL);
if (!result) if (!result)
return NULL; return NULL;
js::AutoValueRooter root(cx, result); js::AutoObjectRooter root(cx, result);
// Get the FunctionInfo from the FunctionType. // Get the FunctionInfo from the FunctionType.
FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, typeObj); FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, typeObj);
@ -5176,7 +5174,7 @@ CClosure::ClosureStub(ffi_cif* cif, void* result, void** args, void* userData)
JS_ASSERT(cif == &fninfo->mCIF); JS_ASSERT(cif == &fninfo->mCIF);
// Get a death grip on 'closureObj'. // Get a death grip on 'closureObj'.
js::AutoValueRooter root(cx, cinfo->closureObj); js::AutoObjectRooter root(cx, cinfo->closureObj);
// Set up an array for converted arguments. // Set up an array for converted arguments.
Array<jsval, 16> argv; Array<jsval, 16> argv;
@ -5188,7 +5186,7 @@ CClosure::ClosureStub(ffi_cif* cif, void* result, void** args, void* userData)
for (JSUint32 i = 0; i < cif->nargs; ++i) for (JSUint32 i = 0; i < cif->nargs; ++i)
argv[i] = JSVAL_VOID; argv[i] = JSVAL_VOID;
js::AutoArrayRooter roots(cx, argv.length(), argv.begin()); js::AutoArrayRooter roots(cx, argv.length(), Valueify(argv.begin()));
for (JSUint32 i = 0; i < cif->nargs; ++i) { for (JSUint32 i = 0; i < cif->nargs; ++i) {
// Convert each argument, and have any CData objects created depend on // Convert each argument, and have any CData objects created depend on
// the existing buffers. // the existing buffers.
@ -5262,7 +5260,7 @@ CData::Create(JSContext* cx,
JSObject* dataObj = JS_NewObject(cx, &sCDataClass, proto, parent); JSObject* dataObj = JS_NewObject(cx, &sCDataClass, proto, parent);
if (!dataObj) if (!dataObj)
return NULL; return NULL;
js::AutoValueRooter root(cx, dataObj); js::AutoObjectRooter root(cx, dataObj);
// set the CData's associated type // set the CData's associated type
if (!JS_SetReservedSlot(cx, dataObj, SLOT_CTYPE, OBJECT_TO_JSVAL(typeObj))) if (!JS_SetReservedSlot(cx, dataObj, SLOT_CTYPE, OBJECT_TO_JSVAL(typeObj)))
@ -5368,7 +5366,7 @@ CData::IsCData(JSContext* cx, JSObject* obj)
} }
JSBool JSBool
CData::ValueGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) CData::ValueGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!IsCData(cx, obj)) { if (!IsCData(cx, obj)) {
JS_ReportError(cx, "not a CData"); JS_ReportError(cx, "not a CData");
@ -5383,7 +5381,7 @@ CData::ValueGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
} }
JSBool JSBool
CData::ValueSetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) CData::ValueSetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
{ {
if (!IsCData(cx, obj)) { if (!IsCData(cx, obj)) {
JS_ReportError(cx, "not a CData"); JS_ReportError(cx, "not a CData");
@ -5413,7 +5411,7 @@ CData::Address(JSContext* cx, uintN argc, jsval *vp)
JSObject* pointerType = PointerType::CreateInternal(cx, typeObj); JSObject* pointerType = PointerType::CreateInternal(cx, typeObj);
if (!pointerType) if (!pointerType)
return JS_FALSE; return JS_FALSE;
js::AutoValueRooter root(cx, pointerType); js::AutoObjectRooter root(cx, pointerType);
// Create a PointerType CData object containing null. // Create a PointerType CData object containing null.
JSObject* result = CData::Create(cx, pointerType, NULL, NULL, true); JSObject* result = CData::Create(cx, pointerType, NULL, NULL, true);
@ -5616,7 +5614,7 @@ Int64Base::Construct(JSContext* cx,
JSObject* result = JS_NewObject(cx, clasp, proto, JS_GetParent(cx, proto)); JSObject* result = JS_NewObject(cx, clasp, proto, JS_GetParent(cx, proto));
if (!result) if (!result)
return NULL; return NULL;
js::AutoValueRooter root(cx, result); js::AutoObjectRooter root(cx, result);
// attach the Int64's data // attach the Int64's data
JSUint64* buffer = new JSUint64(data); JSUint64* buffer = new JSUint64(data);

View File

@ -85,7 +85,7 @@ Library::Create(JSContext* cx, jsval aPath)
JSObject* libraryObj = JS_NewObject(cx, &sLibraryClass, NULL, NULL); JSObject* libraryObj = JS_NewObject(cx, &sLibraryClass, NULL, NULL);
if (!libraryObj) if (!libraryObj)
return NULL; return NULL;
js::AutoValueRooter root(cx, libraryObj); js::AutoObjectRooter root(cx, libraryObj);
// initialize the library // initialize the library
if (!JS_SetReservedSlot(cx, libraryObj, SLOT_LIBRARY, PRIVATE_TO_JSVAL(NULL))) if (!JS_SetReservedSlot(cx, libraryObj, SLOT_LIBRARY, PRIVATE_TO_JSVAL(NULL)))
@ -241,7 +241,7 @@ Library::Declare(JSContext* cx, uintN argc, jsval* vp)
return JS_FALSE; return JS_FALSE;
JSObject* typeObj; JSObject* typeObj;
js::AutoValueRooter root(cx); js::AutoObjectRooter root(cx);
bool isFunction = argc > 2; bool isFunction = argc > 2;
if (isFunction) { if (isFunction) {
// Case 1). // Case 1).

View File

@ -539,6 +539,11 @@ JSRuntime::init(uint32 maxbytes)
if (!js_InitGC(this, maxbytes) || !js_InitAtomState(this)) if (!js_InitGC(this, maxbytes) || !js_InitAtomState(this))
return false; return false;
#ifdef _M_X64
if (!JSString::initStringTables())
return false;
#endif
deflatedStringCache = new js::DeflatedStringCache(); deflatedStringCache = new js::DeflatedStringCache();
if (!deflatedStringCache || !deflatedStringCache->init()) if (!deflatedStringCache || !deflatedStringCache->init())
return false; return false;
@ -2531,7 +2536,6 @@ JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
JS_PUBLIC_API(jsval) JS_PUBLIC_API(jsval)
JSID_TO_JSVAL(jsid id) JSID_TO_JSVAL(jsid id)
{ {
CHECK_REQUEST(cx);
return Jsvalify(IdToValue(id)); return Jsvalify(IdToValue(id));
} }
@ -2594,7 +2598,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
JS_PUBLIC_API(JSClass *) JS_PUBLIC_API(JSClass *)
JS_GetClass(JSContext *cx, JSObject *obj) JS_GetClass(JSContext *cx, JSObject *obj)
{ {
return obj->getClass(); return Jsvalify(obj->getClass());
} }
#else #else
JS_PUBLIC_API(JSClass *) JS_PUBLIC_API(JSClass *)

View File

@ -52,12 +52,12 @@
JS_BEGIN_EXTERN_C JS_BEGIN_EXTERN_C
/* Well-known JS values, initialized on startup. */ /* Well-known JS values, initialized on startup. */
#define JSVAL_NULL JSVAL_CONSTANT(JSVAL_MASK32_NULL, 0) #define JSVAL_NULL BUILD_JSVAL(JSVAL_MASK32_NULL, 0)
#define JSVAL_ZERO JSVAL_CONSTANT(JSVAL_MASK32_INT32, 0) #define JSVAL_ZERO BUILD_JSVAL(JSVAL_MASK32_INT32, 0)
#define JSVAL_ONE JSVAL_CONSTANT(JSVAL_MASK32_INT32, 1) #define JSVAL_ONE BUILD_JSVAL(JSVAL_MASK32_INT32, 1)
#define JSVAL_FALSE JSVAL_CONSTANT(JSVAL_MASK32_BOOLEAN, JS_FALSE) #define JSVAL_FALSE BUILD_JSVAL(JSVAL_MASK32_BOOLEAN, JS_FALSE)
#define JSVAL_TRUE JSVAL_CONSTANT(JSVAL_MASK32_BOOLEAN, JS_TRUE) #define JSVAL_TRUE BUILD_JSVAL(JSVAL_MASK32_BOOLEAN, JS_TRUE)
#define JSVAL_VOID JSVAL_CONSTANT(JSVAL_MASK32_UNDEFINED, 0) #define JSVAL_VOID BUILD_JSVAL(JSVAL_MASK32_UNDEFINED, 0)
/* Predicates for type testing. */ /* Predicates for type testing. */
@ -65,14 +65,14 @@ static JS_ALWAYS_INLINE JSBool
JSVAL_IS_NULL(jsval v) JSVAL_IS_NULL(jsval v)
{ {
jsval_layout l = { v }; jsval_layout l = { v };
return l.s.mask32 == JSVAL_MASK32_NULL; return JSVAL_IS_NULL_IMPL(l);
} }
static JS_ALWAYS_INLINE JSBool static JS_ALWAYS_INLINE JSBool
JSVAL_IS_VOID(jsval v) JSVAL_IS_VOID(jsval v)
{ {
jsval_layout l = { v }; jsval_layout l = { v };
return l.s.mask32 == JSVAL_MASK32_UNDEFINED; return JSVAL_IS_UNDEFINED_IMPL(l);
} }
static JS_ALWAYS_INLINE JSBool static JS_ALWAYS_INLINE JSBool
@ -103,17 +103,14 @@ INT_FITS_IN_JSVAL(jsint i)
static JS_ALWAYS_INLINE jsval static JS_ALWAYS_INLINE jsval
INT_TO_JSVAL(int32 i) INT_TO_JSVAL(int32 i)
{ {
jsval_layout l; return INT32_TO_JSVAL_IMPL(i).asBits;
l.s.mask32 = JSVAL_MASK32_INT32;
l.s.payload.i32 = i;
return l.asBits;
} }
static JS_ALWAYS_INLINE JSBool static JS_ALWAYS_INLINE JSBool
JSVAL_IS_DOUBLE(jsval v) JSVAL_IS_DOUBLE(jsval v)
{ {
jsval_layout l = { v }; jsval_layout l = { v };
return l.s.mask32 < JSVAL_MASK32_CLEAR; return JSVAL_IS_DOUBLE_IMPL(l);
} }
static JS_ALWAYS_INLINE jsdouble static JS_ALWAYS_INLINE jsdouble
@ -127,16 +124,14 @@ JSVAL_TO_DOUBLE(jsval v)
static JS_ALWAYS_INLINE jsval static JS_ALWAYS_INLINE jsval
DOUBLE_TO_JSVAL(jsdouble d) DOUBLE_TO_JSVAL(jsdouble d)
{ {
jsval_layout l; return DOUBLE_TO_JSVAL_IMPL(d).asBits;
l.asDouble = d;
JS_ASSERT(l.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
return l.asBits;
} }
static JS_ALWAYS_INLINE JSBool static JS_ALWAYS_INLINE JSBool
JSVAL_IS_NUMBER(jsval v) JSVAL_IS_NUMBER(jsval v)
{ {
return JSVAL_IS_INT(v) | JSVAL_IS_DOUBLE(v); jsval_layout l = { v };
return JSVAL_IS_NUMBER_IMPL(l);
} }
static JS_ALWAYS_INLINE JSBool static JS_ALWAYS_INLINE JSBool
@ -151,30 +146,20 @@ JSVAL_TO_STRING(jsval v)
{ {
JS_ASSERT(JSVAL_IS_STRING(v)); JS_ASSERT(JSVAL_IS_STRING(v));
jsval_layout l = { v }; jsval_layout l = { v };
return l.s.payload.str; return JSVAL_TO_STRING_IMPL(l);
} }
static JS_ALWAYS_INLINE jsval static JS_ALWAYS_INLINE jsval
STRING_TO_JSVAL(JSString *str) STRING_TO_JSVAL(JSString *str)
{ {
jsval_layout l; return STRING_TO_JSVAL_IMPL(str).asBits;
l.s.mask32 = JSVAL_MASK32_STRING;
l.s.payload.str = str;
return l.asBits;
} }
/*
* N.B. These functions use the older meaning of "object" as "object or null".
* This is not a problem if code only works with jsvals or only works with
* js::Value, but if both uses are mixed, it is important not to get confused
* by the two meanings. For example, JSVAL_IS_OBJECT(v) does not imply
* v.isObject().
*/
static JS_ALWAYS_INLINE JSBool static JS_ALWAYS_INLINE JSBool
JSVAL_IS_OBJECT(jsval v) JSVAL_IS_OBJECT(jsval v)
{ {
jsval_layout l = { v }; jsval_layout l = { v };
return (l.s.mask32 & JSVAL_MASK32_OBJORNULL) > JSVAL_MASK32_CLEAR; return JSVAL_IS_OBJECT_OR_NULL_IMPL(l);
} }
static JS_ALWAYS_INLINE JSObject * static JS_ALWAYS_INLINE JSObject *
@ -182,9 +167,10 @@ JSVAL_TO_OBJECT(jsval v)
{ {
JS_ASSERT(JSVAL_IS_OBJECT(v)); JS_ASSERT(JSVAL_IS_OBJECT(v));
jsval_layout l = { v }; jsval_layout l = { v };
return l.s.payload.obj; return JSVAL_TO_OBJECT_IMPL(l);
} }
/* N.B. Not cheap; uses public API instead of obj->isFunction()! */
static JS_ALWAYS_INLINE jsval static JS_ALWAYS_INLINE jsval
OBJECT_TO_JSVAL(JSObject *obj) OBJECT_TO_JSVAL(JSObject *obj)
{ {
@ -193,12 +179,10 @@ OBJECT_TO_JSVAL(JSObject *obj)
if (!obj) if (!obj)
return JSVAL_NULL; return JSVAL_NULL;
uint32 mask = JS_ObjectIsFunction(NULL, obj) ? JSVAL_MASK32_FUNOBJ
JSValueMask32 mask = JS_ObjectIsFunction(NULL, obj) ? JSVAL_MASK32_FUNOBJ
: JSVAL_MASK32_NONFUNOBJ; : JSVAL_MASK32_NONFUNOBJ;
jsval_layout l; return OBJECT_TO_JSVAL_IMPL(mask, obj).asBits;
l.s.mask32 = mask;
l.s.payload.obj = obj;
return l.asBits;
} }
static JS_ALWAYS_INLINE JSBool static JS_ALWAYS_INLINE JSBool
@ -219,24 +203,21 @@ JSVAL_TO_BOOLEAN(jsval v)
static JS_ALWAYS_INLINE jsval static JS_ALWAYS_INLINE jsval
BOOLEAN_TO_JSVAL(JSBool b) BOOLEAN_TO_JSVAL(JSBool b)
{ {
jsval_layout l; return BOOLEAN_TO_JSVAL_IMPL(b).asBits;
l.s.mask32 = JSVAL_MASK32_BOOLEAN;
l.s.payload.boo = b;
return l.asBits;
} }
static JS_ALWAYS_INLINE JSBool static JS_ALWAYS_INLINE JSBool
JSVAL_IS_PRIMITIVE(jsval v) JSVAL_IS_PRIMITIVE(jsval v)
{ {
jsval_layout l = { v }; jsval_layout l = { v };
return (l.s.mask32 & JSVAL_MASK32_OBJECT) <= JSVAL_MASK32_CLEAR; return JSVAL_IS_PRIMITIVE_IMPL(l);
} }
static JS_ALWAYS_INLINE JSBool static JS_ALWAYS_INLINE JSBool
JSVAL_IS_GCTHING(jsval v) JSVAL_IS_GCTHING(jsval v)
{ {
jsval_layout l = { v }; jsval_layout l = { v };
return (l.s.mask32 & JSVAL_MASK32_GCTHING) > JSVAL_MASK32_CLEAR; return JSVAL_IS_GCTHING_IMPL(l);
} }
static JS_ALWAYS_INLINE void * static JS_ALWAYS_INLINE void *
@ -244,24 +225,23 @@ JSVAL_TO_GCTHING(jsval v)
{ {
JS_ASSERT(JSVAL_IS_GCTHING(v)); JS_ASSERT(JSVAL_IS_GCTHING(v));
jsval_layout l = { v }; jsval_layout l = { v };
return l.s.payload.ptr; return JSVAL_TO_GCTHING_IMPL(l);
} }
/* To be GC-safe, privates are tagged as doubles. */
static JS_ALWAYS_INLINE jsval static JS_ALWAYS_INLINE jsval
PRIVATE_TO_JSVAL(void *ptr) PRIVATE_TO_JSVAL(void *ptr)
{ {
jsval_layout l; return PRIVATE_TO_JSVAL_IMPL(ptr).asBits;
l.s.mask32 = JSVAL_MASK32_INT32;
l.s.payload.ptr = ptr;
return l.asBits;
} }
static JS_ALWAYS_INLINE void * static JS_ALWAYS_INLINE void *
JSVAL_TO_PRIVATE(jsval v) JSVAL_TO_PRIVATE(jsval v)
{ {
JS_ASSERT(JSVAL_IS_INT(v)); JS_ASSERT(JSVAL_IS_DOUBLE(v));
jsval_layout l = { v }; jsval_layout l = { v };
return l.s.payload.ptr; return JSVAL_TO_PRIVATE_IMPL(l);
} }
/* Lock and unlock the GC thing held by a jsval. */ /* Lock and unlock the GC thing held by a jsval. */
@ -1189,7 +1169,7 @@ JSVAL_TRACE_KIND(jsval v)
{ {
JS_ASSERT(JSVAL_IS_GCTHING(v)); JS_ASSERT(JSVAL_IS_GCTHING(v));
jsval_layout l = { v }; jsval_layout l = { v };
return (uint32)(l.s.mask32 == JSVAL_MASK32_STRING); return JSVAL_TRACE_KIND_IMPL(l);
} }
struct JSTracer { struct JSTracer {
@ -3007,44 +2987,26 @@ class Value
* break this encapsulation should be listed as friends below. Also see * break this encapsulation should be listed as friends below. Also see
* uses of public jsval members in jsapi.h/jspubtd.h. * uses of public jsval members in jsapi.h/jspubtd.h.
*/ */
friend bool StrictlyEqual(JSContext *, const Value &, const Value &);
friend bool Interpret(JSContext *); /* grep "value representation" */
friend class PrimitiveValue; friend class PrimitiveValue;
protected: protected:
/* Type masks */ /* Type masks */
template <int I> class T {};
void staticAssertions() { void staticAssertions() {
JS_STATIC_ASSERT(sizeof(void *) == 4);
JS_STATIC_ASSERT(sizeof(jsval) == 8);
JS_STATIC_ASSERT(sizeof(JSBool) == 4);
JS_STATIC_ASSERT(sizeof(JSValueMask16) == 2); JS_STATIC_ASSERT(sizeof(JSValueMask16) == 2);
JS_STATIC_ASSERT(sizeof(jsval_payload) == 4); JS_STATIC_ASSERT(JSVAL_NANBOX_PATTERN == 0xFFFF);
JS_STATIC_ASSERT(sizeof(JSValueMask32) == 4);
JS_STATIC_ASSERT(JSVAL_MASK32_CLEAR == 0xFFFF0000);
JS_STATIC_ASSERT(sizeof(JSBool) == 4);
JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4); JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4);
JS_STATIC_ASSERT(sizeof(((jsval_layout *)0)->s.payload) == 4);
JS_STATIC_ASSERT(sizeof(jsval) == 8);
} }
jsval_layout data; jsval_layout data;
static bool isNullOrUndefinedMask(uint32 mask) {
return (mask & JSVAL_MASK32_SINGLETON) > JSVAL_MASK32_CLEAR;
}
static bool isDoubleMask(uint32 mask) {
return mask < JSVAL_MASK32_CLEAR;
}
static bool isNumberMask(uint32 mask) {
return (mask < JSVAL_MASK32_CLEAR) | (mask == JSVAL_MASK32_INT32);
}
static bool isObjectMask(uint32 mask) {
return (mask & JSVAL_MASK32_OBJECT) > JSVAL_MASK32_CLEAR;
}
static bool isObjectOrNullMask(uint32 mask) {
return (mask & JSVAL_MASK32_OBJORNULL) > JSVAL_MASK32_CLEAR;
}
public: public:
/* Constructors */ /* Constructors */
@ -3075,18 +3037,15 @@ class Value
/* Change to a Value of a single type */ /* Change to a Value of a single type */
void setNull() { void setNull() {
data.s.mask32 = JSVAL_MASK32_NULL; data.asBits = JSVAL_NULL;
data.s.payload.obj = NULL;
} }
void setUndefined() { void setUndefined() {
data.s.mask32 = JSVAL_MASK32_UNDEFINED; data.asBits = JSVAL_VOID;
data.s.payload.obj = NULL;
} }
void setInt32(int32 i) { void setInt32(int32 i) {
data.s.mask32 = JSVAL_MASK32_INT32; data = INT32_TO_JSVAL_IMPL(i);
data.s.payload.i32 = i;
} }
int32 &asInt32Ref() { int32 &asInt32Ref() {
@ -3096,8 +3055,7 @@ class Value
void setDouble(double d) { void setDouble(double d) {
ASSERT_DOUBLE_ALIGN(); ASSERT_DOUBLE_ALIGN();
data.asDouble = d; data = DOUBLE_TO_JSVAL_IMPL(d);
JS_ASSERT(data.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
} }
double &asDoubleRef() { double &asDoubleRef() {
@ -3107,62 +3065,54 @@ class Value
} }
void setString(JSString *str) { void setString(JSString *str) {
data.s.mask32 = JSVAL_MASK32_STRING; data = STRING_TO_JSVAL_IMPL(str);
data.s.payload.str = str;
} }
void setFunObj(JSObject &arg) { void setFunObj(JSObject &arg) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &arg)); JS_ASSERT(JS_ObjectIsFunction(NULL, &arg));
data.s.mask32 = JSVAL_MASK32_FUNOBJ; data = OBJECT_TO_JSVAL_IMPL(JSVAL_MASK32_FUNOBJ, &arg);
data.s.payload.obj = &arg;
} }
void setNonFunObj(JSObject &arg) { void setNonFunObj(JSObject &arg) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, &arg)); JS_ASSERT(!JS_ObjectIsFunction(NULL, &arg));
data.s.mask32 = JSVAL_MASK32_NONFUNOBJ; data = OBJECT_TO_JSVAL_IMPL(JSVAL_MASK32_NONFUNOBJ, &arg);
data.s.payload.obj = &arg;
} }
void setBoolean(bool b) { void setBoolean(bool b) {
data.s.mask32 = JSVAL_MASK32_BOOLEAN; data = BOOLEAN_TO_JSVAL_IMPL(b);
data.s.payload.boo = b;
} }
void setMagic(JSWhyMagic why) { void setMagic(JSWhyMagic why) {
data.s.mask32 = JSVAL_MASK32_MAGIC; data = MAGIC_TO_JSVAL_IMPL(why);
data.s.payload.why = why;
} }
/* Change to a Value of a type dynamically chosen from a set of types */ /* Change to a Value of a type dynamically chosen from a set of types */
void setNumber(uint32 ui) { void setNumber(uint32 ui) {
if (ui > JSVAL_INT_MAX) { if (ui > JSVAL_INT_MAX)
data.asDouble = ui; data = DOUBLE_TO_JSVAL_IMPL(ui);
JS_ASSERT(data.s.tag.nanBits != JSVAL_NANBOX_PATTERN); else
} else { data = INT32_TO_JSVAL_IMPL((int32)ui);
data.s.mask32 = JSVAL_MASK32_INT32;
data.s.payload.i32 = (int32)ui;
}
} }
inline void setNumber(double d); inline void setNumber(double d);
void setFunObjOrNull(JSObject *arg) { void setFunObjOrNull(JSObject *arg) {
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg)); JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
data.s.mask32 = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_NULL; JSValueMask32 mask = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_NULL;
data.s.payload.obj = arg; data = OBJECT_TO_JSVAL_IMPL(mask, arg);
} }
void setFunObjOrUndefined(JSObject *arg) { void setFunObjOrUndefined(JSObject *arg) {
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg)); JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
data.s.mask32 = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_UNDEFINED; JSValueMask32 mask = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_UNDEFINED;
data.s.payload.obj = arg; data = OBJECT_TO_JSVAL_IMPL(mask, arg);
} }
void setNonFunObjOrNull(JSObject *arg) { void setNonFunObjOrNull(JSObject *arg) {
JS_ASSERT_IF(arg, !JS_ObjectIsFunction(NULL, arg)); JS_ASSERT_IF(arg, !JS_ObjectIsFunction(NULL, arg));
data.s.mask32 = arg ? JSVAL_MASK32_NONFUNOBJ : JSVAL_MASK32_NULL; JSValueMask32 mask = arg ? JSVAL_MASK32_NONFUNOBJ : JSVAL_MASK32_NULL;
data.s.payload.obj = arg; data = OBJECT_TO_JSVAL_IMPL(mask, arg);
} }
inline void setObject(JSObject &arg); inline void setObject(JSObject &arg);
@ -3171,15 +3121,15 @@ class Value
/* Query a Value's type */ /* Query a Value's type */
bool isUndefined() const { bool isUndefined() const {
return data.s.mask32 == JSVAL_MASK32_UNDEFINED; return JSVAL_IS_UNDEFINED_IMPL(data);
} }
bool isNull() const { bool isNull() const {
return data.s.mask32 == JSVAL_MASK32_NULL; return JSVAL_IS_NULL_IMPL(data);
} }
bool isNullOrUndefined() const { bool isNullOrUndefined() const {
return isNullOrUndefinedMask(data.s.mask32); return JSVAL_IS_SINGLETON_IMPL(data);
} }
bool isInt32() const { bool isInt32() const {
@ -3187,16 +3137,15 @@ class Value
} }
bool isInt32(int32 i32) const { bool isInt32(int32 i32) const {
return (data.s.mask32 == JSVAL_MASK32_INT32) & return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
(data.s.payload.i32 == i32);
} }
bool isDouble() const { bool isDouble() const {
return isDoubleMask(data.s.mask32); return JSVAL_IS_DOUBLE_IMPL(data);
} }
bool isNumber() const { bool isNumber() const {
return isNumberMask(data.s.mask32); return JSVAL_IS_NUMBER_IMPL(data);
} }
bool isString() const { bool isString() const {
@ -3212,19 +3161,19 @@ class Value
} }
bool isObject() const { bool isObject() const {
return isObjectMask(data.s.mask32); return JSVAL_IS_OBJECT_IMPL(data);
} }
bool isPrimitive() const { bool isPrimitive() const {
return !isObject(); return JSVAL_IS_PRIMITIVE_IMPL(data);
} }
bool isObjectOrNull() const { bool isObjectOrNull() const {
return isObjectOrNullMask(data.s.mask32); return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
} }
bool isGCThing() const { bool isGCThing() const {
return (data.s.mask32 & JSVAL_MASK32_GCTHING) > JSVAL_MASK32_CLEAR; return JSVAL_IS_GCTHING_IMPL(data);
} }
bool isBoolean() const { bool isBoolean() const {
@ -3232,13 +3181,11 @@ class Value
} }
bool isTrue() const { bool isTrue() const {
return data.s.mask32 == JSVAL_MASK32_BOOLEAN && return JSVAL_IS_SPECIFIC_BOOLEAN(data, true);
data.s.payload.boo == JS_TRUE;
} }
bool isFalse() const { bool isFalse() const {
return data.s.mask32 == JSVAL_MASK32_BOOLEAN && return JSVAL_IS_SPECIFIC_BOOLEAN(data, false);
data.s.payload.boo == JS_FALSE;
} }
bool isMagic() const { bool isMagic() const {
@ -3252,13 +3199,17 @@ class Value
int32 traceKind() const { int32 traceKind() const {
JS_ASSERT(isGCThing()); JS_ASSERT(isGCThing());
return (int32)(data.s.mask32 == JSVAL_MASK32_STRING); return JSVAL_TRACE_KIND_IMPL(data);
} }
#ifdef DEBUG
JSWhyMagic whyMagic() const { JSWhyMagic whyMagic() const {
JS_ASSERT(isMagic()); JS_ASSERT(isMagic());
return data.s.payload.why; return data.s.payload.why;
} }
#endif
/* Comparison */
bool operator==(const Value &rhs) const { bool operator==(const Value &rhs) const {
return data.asBits == rhs.data.asBits; return data.asBits == rhs.data.asBits;
@ -3268,6 +3219,18 @@ class Value
return data.asBits != rhs.data.asBits; return data.asBits != rhs.data.asBits;
} }
friend bool SamePrimitiveTypeOrBothObjects(const Value &lhs, const Value &rhs) {
return JSVAL_SAME_PRIMITIVE_TYPE_OR_BOTH_OBJECTS_IMPL(lhs.data, rhs.data);
}
friend bool BothInt32(const Value &lhs, const Value &rhs) {
return JSVAL_BOTH_INT32_IMPL(lhs.data, rhs.data);
}
friend bool BothString(const Value &lhs, const Value &rhs) {
return JSVAL_BOTH_STRING_IMPL(lhs.data, rhs.data);
}
/* Extract a Value's payload */ /* Extract a Value's payload */
int32 asInt32() const { int32 asInt32() const {
@ -3288,32 +3251,32 @@ class Value
JSString *asString() const { JSString *asString() const {
JS_ASSERT(isString()); JS_ASSERT(isString());
return data.s.payload.str; return JSVAL_TO_STRING_IMPL(data);
} }
JSObject &asNonFunObj() const { JSObject &asNonFunObj() const {
JS_ASSERT(isNonFunObj()); JS_ASSERT(isNonFunObj());
return *data.s.payload.obj; return *JSVAL_TO_OBJECT_IMPL(data);
} }
JSObject &asFunObj() const { JSObject &asFunObj() const {
JS_ASSERT(isFunObj()); JS_ASSERT(isFunObj());
return *data.s.payload.obj; return *JSVAL_TO_OBJECT_IMPL(data);
} }
JSObject &asObject() const { JSObject &asObject() const {
JS_ASSERT(isObject()); JS_ASSERT(isObject());
return *data.s.payload.obj; return *JSVAL_TO_OBJECT_IMPL(data);
} }
JSObject *asObjectOrNull() const { JSObject *asObjectOrNull() const {
JS_ASSERT(isObjectOrNull()); JS_ASSERT(isObjectOrNull());
return data.s.payload.obj; return JSVAL_TO_OBJECT_IMPL(data);
} }
void *asGCThing() const { void *asGCThing() const {
JS_ASSERT(isGCThing()); JS_ASSERT(isGCThing());
return data.s.payload.ptr; return JSVAL_TO_GCTHING_IMPL(data);
} }
bool asBoolean() const { bool asBoolean() const {
@ -3321,6 +3284,11 @@ class Value
return data.s.payload.boo; return data.s.payload.boo;
} }
uint32 asRawUint32() const {
JS_ASSERT(!isDouble());
return data.s.payload.u32;
}
/* Swap two Values */ /* Swap two Values */
void swap(Value &rhs) { void swap(Value &rhs) {
@ -3343,27 +3311,24 @@ class Value
} }
void setPrivateVoidPtr(void *ptr) { void setPrivateVoidPtr(void *ptr) {
data.s.mask32 = JSVAL_MASK32_INT32; data = PRIVATE_TO_JSVAL_IMPL(ptr);
data.s.payload.ptr = ptr;
} }
void *asPrivateVoidPtr() const { void *asPrivateVoidPtr() const {
JS_ASSERT(data.s.mask32 == JSVAL_MASK32_INT32); JS_ASSERT(isDouble());
return data.s.payload.ptr; return JSVAL_TO_PRIVATE_IMPL(data);
} }
void setPrivateUint32(uint32 u) { void setPrivateUint32(uint32 u) {
data.s.mask32 = JSVAL_MASK32_INT32; setInt32((int32)u);
data.s.payload.u32 = u;
} }
uint32 asPrivateUint32() const { uint32 asPrivateUint32() const {
JS_ASSERT(data.s.mask32 == JSVAL_MASK32_INT32); return (uint32)asInt32();
return data.s.payload.u32;
} }
uint32 &asPrivateUint32Ref() { uint32 &asPrivateUint32Ref() {
JS_ASSERT(data.s.mask32 == JSVAL_MASK32_INT32); JS_ASSERT(isInt32());
return data.s.payload.u32; return data.s.payload.u32;
} }
} VALUE_ALIGNMENT; } VALUE_ALIGNMENT;
@ -3378,6 +3343,7 @@ static inline jsval & Jsvalify(Value &v) { return (jsval &)v; }
static inline const jsval & Jsvalify(const Value &v) { return (const jsval &)v; } static inline const jsval & Jsvalify(const Value &v) { return (const jsval &)v; }
static inline Value * Valueify(jsval *v) { return (Value *)v; } static inline Value * Valueify(jsval *v) { return (Value *)v; }
static inline const Value * Valueify(const jsval *v) { return (const Value *)v; } static inline const Value * Valueify(const jsval *v) { return (const Value *)v; }
static inline Value ** Valueify(jsval **v) { return (Value **)v; }
static inline Value & Valueify(jsval &v) { return (Value &)v; } static inline Value & Valueify(jsval &v) { return (Value &)v; }
static inline const Value & Valueify(const jsval &v) { return (const Value &)v; } static inline const Value & Valueify(const jsval &v) { return (const Value &)v; }

View File

@ -2040,8 +2040,10 @@ array_sort(JSContext *cx, uintN argc, Value *vp)
str = js_ValueToString(cx, v); str = js_ValueToString(cx, v);
if (!str) if (!str)
return false; return false;
vec[2 * i].setString(str); // Copying v must come first, because the following line overwrites v
// when i == 0.
vec[2 * i + 1] = v; vec[2 * i + 1] = v;
vec[2 * i].setString(str);
} while (i != 0); } while (i != 0);
JS_ASSERT(tvr.array == vec); JS_ASSERT(tvr.array == vec);
@ -2730,7 +2732,7 @@ array_indexOfHelper(JSContext *cx, JSBool isLast, uintN argc, Value *vp)
return JS_FALSE; return JS_FALSE;
} }
if (!hole && StrictlyEqual(cx, *vp, tosearch)) { if (!hole && StrictlyEqual(cx, *vp, tosearch)) {
Uint32ToValue(i, vp); vp->setNumber(i);
return JS_TRUE; return JS_TRUE;
} }
if (i == stop) if (i == stop)

View File

@ -911,6 +911,11 @@ struct JSGCLockHashEntry : public JSDHashEntryHdr
JSBool JSBool
js_InitGC(JSRuntime *rt, uint32 maxbytes) js_InitGC(JSRuntime *rt, uint32 maxbytes)
{ {
#if defined(XP_WIN) && defined(_M_X64)
if (!InitNtAllocAPIs())
return JS_FALSE;
#endif
InitGCArenaLists(rt); InitGCArenaLists(rt);
if (!rt->gcRootsHash.init(GC_ROOTS_SIZE)) if (!rt->gcRootsHash.init(GC_ROOTS_SIZE))
return false; return false;

View File

@ -39,6 +39,10 @@
#ifdef XP_WIN #ifdef XP_WIN
# include <windows.h> # include <windows.h>
#ifdef _M_X64
# include "jsstr.h"
#endif
# ifdef _MSC_VER # ifdef _MSC_VER
# pragma warning( disable: 4267 4996 4146 ) # pragma warning( disable: 4267 4996 4146 )
# endif # endif
@ -140,6 +144,68 @@ UnmapPages(void *p, size_t size)
# else /* WINCE */ # else /* WINCE */
# ifdef _M_X64
typedef long (*ntavm_fun)(HANDLE handle, void **addr, ULONG zbits,
size_t *size, ULONG alloctype, ULONG prot);
typedef long (*ntfvm_fun)(HANDLE handle, void **addr, size_t *size,
ULONG freetype);
static ntavm_fun NtAllocateVirtualMemory;
static ntfvm_fun NtFreeVirtualMemory;
bool
js::InitNtAllocAPIs()
{
HMODULE h = GetModuleHandle("ntdll.dll");
if (!h)
return false;
NtAllocateVirtualMemory = ntavm_fun(GetProcAddress(h, "NtAllocateVirtualMemory"));
if (!NtAllocateVirtualMemory)
return false;
NtFreeVirtualMemory = ntfvm_fun(GetProcAddress(h, "NtFreeVirtualMemory"));
if (!NtFreeVirtualMemory)
return false;
}
// Allocate pages with 32-bit addresses (i.e., top 16 bits are all 0).
static void *
MapPages(void *addr, size_t size)
{
long rc = NtAllocateVirtualMemory(INVALID_HANDLE_VALUE, &addr, 1, &size,
MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
return rc ? NULL : addr;
}
static void
UnmapPages(void *addr, size_t size)
{
NtFreeVirtualMemory(INVALID_HANDLE_VALUE, &addr, &size, MEM_RELEASE);
}
bool
JSString::initStringTables()
{
char *p = (char *) MapPages(NULL, unitStringTableSize + intStringTableSize);
if (!p)
return false;
unitStringTable = (JSString*) memcpy(p, staticUnitStringTable, unitStringTableSize);
intStringTable = (JSString*) memcpy(p + unitStringTableSize,
staticIntStringTable, intStringTableSize);
return true;
}
void
JSString::freeStringTables()
{
UnmapPages(unitStringTable, unitStringTableSize + intStringTableSize);
unitStringTable = NULL;
intStringTable = NULL;
}
# else /* _M_X64 */
static void * static void *
MapPages(void *addr, size_t size) MapPages(void *addr, size_t size)
{ {
@ -154,6 +220,8 @@ UnmapPages(void *addr, size_t size)
JS_ALWAYS_TRUE(VirtualFree(addr, 0, MEM_RELEASE)); JS_ALWAYS_TRUE(VirtualFree(addr, 0, MEM_RELEASE));
} }
# endif /* _M_X64 */
# endif /* !WINCE */ # endif /* !WINCE */
#elif defined(XP_MACOSX) || defined(DARWIN) #elif defined(XP_MACOSX) || defined(DARWIN)
@ -203,8 +271,9 @@ MapAlignedPages(size_t size, size_t alignment)
* We don't use MAP_FIXED here, because it can cause the *replacement* * We don't use MAP_FIXED here, because it can cause the *replacement*
* of existing mappings, and we only want to create new mappings. * of existing mappings, and we only want to create new mappings.
*/ */
// TODO: this is totally a hack for now; need to replace
void *p = mmap((caddr_t) alignment, size, PROT_READ | PROT_WRITE, void *p = mmap((caddr_t) alignment, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_NOSYNC | MAP_ALIGN | MAP_ANON, -1, 0); MAP_PRIVATE | MAP_NOSYNC | MAP_ALIGN | MAP_ANON | MAP_32BIT, -1, 0);
if (p == MAP_FAILED) if (p == MAP_FAILED)
return NULL; return NULL;
return p; return p;
@ -219,7 +288,8 @@ MapPages(void *addr, size_t size)
* We don't use MAP_FIXED here, because it can cause the *replacement* * We don't use MAP_FIXED here, because it can cause the *replacement*
* of existing mappings, and we only want to create new mappings. * of existing mappings, and we only want to create new mappings.
*/ */
void *p = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, // TODO: this is totally a hack for now; need to replace
void *p = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_32BIT,
-1, 0); -1, 0);
if (p == MAP_FAILED) if (p == MAP_FAILED)
return NULL; return NULL;

View File

@ -55,6 +55,10 @@ const size_t GC_CHUNK_SHIFT = 20;
const size_t GC_CHUNK_SIZE = size_t(1) << GC_CHUNK_SHIFT; const size_t GC_CHUNK_SIZE = size_t(1) << GC_CHUNK_SHIFT;
const size_t GC_CHUNK_MASK = GC_CHUNK_SIZE - 1; const size_t GC_CHUNK_MASK = GC_CHUNK_SIZE - 1;
#if defined(XP_WIN) && defined(_M_X64)
bool InitNtAllocAPIs();
#endif
void * void *
AllocGCChunk(); AllocGCChunk();

View File

@ -387,8 +387,7 @@ NoSuchMethod(JSContext *cx, uintN argc, Value *vp, uint32 flags)
namespace js { namespace js {
static const uint32 FAKE_NUMBER_MASK = JSVAL_MASK32_INT32 | static const uint32 FAKE_NUMBER_MASK = JSVAL_MASK32_INT32 | PrimitiveValue::DOUBLE_MASK;
PrimitiveValue::DOUBLE_MASK;
const uint32 PrimitiveValue::Masks[PrimitiveValue::THISP_ARRAY_SIZE] = { const uint32 PrimitiveValue::Masks[PrimitiveValue::THISP_ARRAY_SIZE] = {
0, /* 000 */ 0, /* 000 */
@ -1001,36 +1000,29 @@ EqualObjects(JSContext *cx, JSObject *lobj, JSObject *robj)
} }
bool bool
StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval) StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref)
{ {
uint32 lmask = lval.data.s.mask32; Value lval = lref, rval = rref;
uint32 rmask = rval.data.s.mask32; if (SamePrimitiveTypeOrBothObjects(lval, rval)) {
if (lmask == rmask) { if (lval.isString())
if (lmask == JSVAL_MASK32_STRING) return js_EqualStrings(lval.asString(), rval.asString());
return js_EqualStrings(lval.data.s.payload.str, rval.data.s.payload.str); if (lval.isDouble())
if (Value::isObjectMask(lmask)) return JSDOUBLE_COMPARE(lval.asDouble(), ==, rval.asDouble(), JS_FALSE);
return EqualObjects(cx, lval.data.s.payload.obj, rval.data.s.payload.obj); if (lval.isObject())
if (Value::isDoubleMask(lmask)) return EqualObjects(cx, &lval.asObject(), &rval.asObject());
return JSDOUBLE_COMPARE(lval.data.asDouble, ==, rval.data.asDouble, JS_FALSE); return lval.asRawUint32() == rval.asRawUint32();
JS_ASSERT(lmask == JSVAL_MASK32_NULL ||
lmask == JSVAL_MASK32_UNDEFINED ||
lmask == JSVAL_MASK32_INT32 ||
lmask == JSVAL_MASK32_FUNOBJ ||
lmask == JSVAL_MASK32_NONFUNOBJ ||
lmask == JSVAL_MASK32_BOOLEAN);
return lval.data.s.payload.u32 == rval.data.s.payload.u32;
} }
if (Value::isNumberMask(lmask) && Value::isNumberMask(rmask)) { if (lval.isDouble() && rval.isInt32()) {
double ld = lmask == JSVAL_MASK32_INT32 ? lval.data.s.payload.i32 double ld = lval.asDouble();
: lval.data.asDouble; double rd = rval.asInt32();
double rd = rmask == JSVAL_MASK32_INT32 ? rval.data.s.payload.i32 return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
: rval.data.asDouble; }
if (lval.isInt32() && rval.isDouble()) {
double ld = lval.asInt32();
double rd = rval.asDouble();
return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE); return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
} }
if (Value::isObjectMask(lmask) && Value::isObjectMask(rmask))
return EqualObjects(cx, lval.data.s.payload.obj, rval.data.s.payload.obj);
return false; return false;
} }
@ -1824,9 +1816,11 @@ namespace reprmeter {
if ((vp)->isObject()) { \ if ((vp)->isObject()) { \
obj = &(vp)->asObject(); \ obj = &(vp)->asObject(); \
} else { \ } else { \
if (!js_ValueToNonNullObject(cx, *(vp), (vp))) \ Value v; \
if (!js_ValueToNonNullObject(cx, *(vp), &v)) \
goto error; \ goto error; \
obj = &(vp)->asObject(); \ *(vp) = v; \
obj = &v.asObject(); \
} \ } \
JS_END_MACRO JS_END_MACRO
@ -1836,6 +1830,15 @@ namespace reprmeter {
VALUE_TO_OBJECT(cx, vp_, obj); \ VALUE_TO_OBJECT(cx, vp_, obj); \
JS_END_MACRO JS_END_MACRO
#define DEFAULT_VALUE(cx, n, hint, v) \
JS_BEGIN_MACRO \
JS_ASSERT(v.isObject()); \
JS_ASSERT(v == regs.sp[n]); \
if (!v.asObject().defaultValue(cx, hint, &regs.sp[n])) \
goto error; \
v = regs.sp[n]; \
JS_END_MACRO
/* Test whether v is an int in the range [-2^31 + 1, 2^31 - 2] */ /* Test whether v is an int in the range [-2^31 + 1, 2^31 - 2] */
static JS_ALWAYS_INLINE bool static JS_ALWAYS_INLINE bool
CanIncDecWithoutOverflow(int32_t i) CanIncDecWithoutOverflow(int32_t i)

View File

@ -289,7 +289,7 @@ class PrimitiveValue
static const uint32 Masks[THISP_ARRAY_SIZE]; static const uint32 Masks[THISP_ARRAY_SIZE];
public: public:
static const uint32 DOUBLE_MASK = 0x8000; static const uint32 DOUBLE_MASK = 0xFFFF8000;
static bool test(JSFunction *fun, const Value &v) { static bool test(JSFunction *fun, const Value &v) {
uint32 mask = Masks[(fun->flags >> THISP_SHIFT) & THISP_MASK]; uint32 mask = Masks[(fun->flags >> THISP_SHIFT) & THISP_MASK];

View File

@ -493,16 +493,16 @@ FinishSharingTitle(JSContext *cx, JSTitle *title)
uint32 nslots = scope->freeslot; uint32 nslots = scope->freeslot;
JS_ASSERT(nslots >= JSSLOT_START(obj->getClass())); JS_ASSERT(nslots >= JSSLOT_START(obj->getClass()));
for (uint32 i = JSSLOT_START(obj->getClass()); i != nslots; ++i) { for (uint32 i = JSSLOT_START(obj->getClass()); i != nslots; ++i) {
jsval v = obj->getSlot(i); Value v = obj->getSlot(i);
if (JSVAL_IS_STRING(v) && if (v.isString() &&
!js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) { !js_MakeStringImmutable(cx, v.asString())) {
/* /*
* FIXME bug 363059: The following error recovery changes * FIXME bug 363059: The following error recovery changes
* runtime execution semantics, arbitrarily and silently * runtime execution semantics, arbitrarily and silently
* ignoring errors except out-of-memory, which should have been * ignoring errors except out-of-memory, which should have been
* reported through JS_ReportOutOfMemory at this point. * reported through JS_ReportOutOfMemory at this point.
*/ */
obj->setSlot(i, JSVAL_VOID); obj->setSlot(i, undefinedValue());
} }
} }
} }
@ -710,7 +710,7 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
if (CX_THREAD_IS_RUNNING_GC(cx) || if (CX_THREAD_IS_RUNNING_GC(cx) ||
scope->sealed() || scope->sealed() ||
(title->ownercx && ClaimTitle(title, cx))) { (title->ownercx && ClaimTitle(title, cx))) {
return obj->getSlot(slot); return Jsvalify(obj->getSlot(slot));
} }
#ifndef NSPR_LOCK #ifndef NSPR_LOCK
@ -725,7 +725,7 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
* lock release followed by fat lock acquisition. * lock release followed by fat lock acquisition.
*/ */
if (scope == obj->scope()) { if (scope == obj->scope()) {
v = obj->getSlot(slot); v = Jsvalify(obj->getSlot(slot));
if (!NativeCompareAndSwap(&tl->owner, me, 0)) { if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
/* Assert that scope locks never revert to flyweight. */ /* Assert that scope locks never revert to flyweight. */
JS_ASSERT(title->ownercx != cx); JS_ASSERT(title->ownercx != cx);
@ -739,12 +739,12 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
js_Dequeue(tl); js_Dequeue(tl);
} }
else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) { else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
return obj->getSlot(slot); return Jsvalify(obj->getSlot(slot));
} }
#endif #endif
js_LockObj(cx, obj); js_LockObj(cx, obj);
v = obj->getSlot(slot); v = Jsvalify(obj->getSlot(slot));
/* /*
* Test whether cx took ownership of obj's scope during js_LockObj. * Test whether cx took ownership of obj's scope during js_LockObj.
@ -798,7 +798,7 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
if (CX_THREAD_IS_RUNNING_GC(cx) || if (CX_THREAD_IS_RUNNING_GC(cx) ||
scope->sealed() || scope->sealed() ||
(title->ownercx && ClaimTitle(title, cx))) { (title->ownercx && ClaimTitle(title, cx))) {
obj->lockedSetSlot(slot, v); obj->lockedSetSlot(slot, Valueify(v));
return; return;
} }
@ -808,7 +808,7 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
JS_ASSERT(CURRENT_THREAD_IS_ME(me)); JS_ASSERT(CURRENT_THREAD_IS_ME(me));
if (NativeCompareAndSwap(&tl->owner, 0, me)) { if (NativeCompareAndSwap(&tl->owner, 0, me)) {
if (scope == obj->scope()) { if (scope == obj->scope()) {
obj->lockedSetSlot(slot, v); obj->lockedSetSlot(slot, Valueify(v));
if (!NativeCompareAndSwap(&tl->owner, me, 0)) { if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
/* Assert that scope locks never revert to flyweight. */ /* Assert that scope locks never revert to flyweight. */
JS_ASSERT(title->ownercx != cx); JS_ASSERT(title->ownercx != cx);
@ -821,13 +821,13 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
if (!NativeCompareAndSwap(&tl->owner, me, 0)) if (!NativeCompareAndSwap(&tl->owner, me, 0))
js_Dequeue(tl); js_Dequeue(tl);
} else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) { } else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
obj->lockedSetSlot(slot, v); obj->lockedSetSlot(slot, Valueify(v));
return; return;
} }
#endif #endif
js_LockObj(cx, obj); js_LockObj(cx, obj);
obj->lockedSetSlot(slot, v); obj->lockedSetSlot(slot, Valueify(v));
/* /*
* Same drill as above, in js_GetSlotThreadSafe. * Same drill as above, in js_GetSlotThreadSafe.

View File

@ -600,15 +600,6 @@ ValueFitsInInt32(const Value &v, int32_t *pi)
return v.isDouble() && JSDOUBLE_IS_INT32(v.asDouble(), *pi); return v.isDouble() && JSDOUBLE_IS_INT32(v.asDouble(), *pi);
} }
static JS_ALWAYS_INLINE void
Uint32ToValue(uint32_t u, Value *vp)
{
if (JS_UNLIKELY(u > INT32_MAX))
vp->setDouble(u);
else
vp->setInt32((int32_t)u);
}
JS_ALWAYS_INLINE JS_ALWAYS_INLINE
Value::Value(NumberTag arg) Value::Value(NumberTag arg)
{ {

View File

@ -1484,7 +1484,7 @@ obj_unwatch(JSContext *cx, uintN argc, Value *vp)
if (argc == 0) if (argc == 0)
return JS_TRUE; return JS_TRUE;
jsid id; jsid id;
if (ValueToId(cx, vp[2], &id)) if (!ValueToId(cx, vp[2], &id))
return JS_FALSE; return JS_FALSE;
return JS_ClearWatchPoint(cx, obj, id, NULL, NULL); return JS_ClearWatchPoint(cx, obj, id, NULL, NULL);
} }

View File

@ -66,7 +66,7 @@ JSObject::getSlotMT(JSContext *cx, uintN slot)
OBJ_CHECK_SLOT(this, slot); OBJ_CHECK_SLOT(this, slot);
return (scope()->title.ownercx == cx) return (scope()->title.ownercx == cx)
? this->lockedGetSlot(slot) ? this->lockedGetSlot(slot)
: js_GetSlotThreadSafe(cx, this, slot); : js::Valueify(js_GetSlotThreadSafe(cx, this, slot));
#else #else
return this->lockedGetSlot(slot); return this->lockedGetSlot(slot);
#endif #endif
@ -81,7 +81,7 @@ JSObject::setSlotMT(JSContext *cx, uintN slot, const js::Value &value)
if (scope()->title.ownercx == cx) if (scope()->title.ownercx == cx)
this->lockedSetSlot(slot, value); this->lockedSetSlot(slot, value);
else else
js_SetSlotThreadSafe(cx, this, slot, value); js_SetSlotThreadSafe(cx, this, slot, Jsvalify(value));
#else #else
this->lockedSetSlot(slot, value); this->lockedSetSlot(slot, value);
#endif #endif
@ -643,35 +643,35 @@ NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
JS_ALWAYS_INLINE JS_ALWAYS_INLINE
Value::Value(ObjectTag arg) Value::Value(ObjectTag arg)
{ {
data.s.mask32 = arg.obj.isFunction() ? JSVAL_MASK32_FUNOBJ JSValueMask32 mask = arg.obj.isFunction() ? JSVAL_MASK32_FUNOBJ
: JSVAL_MASK32_NONFUNOBJ; : JSVAL_MASK32_NONFUNOBJ;
data.s.payload.obj = &arg.obj; data = OBJECT_TO_JSVAL_IMPL(mask, &arg.obj);
} }
JS_ALWAYS_INLINE JS_ALWAYS_INLINE
Value::Value(ObjectOrNullTag arg) Value::Value(ObjectOrNullTag arg)
{ {
data.s.mask32 = arg.obj ? arg.obj->isFunction() ? JSVAL_MASK32_FUNOBJ JSValueMask32 mask = arg.obj ? arg.obj->isFunction() ? JSVAL_MASK32_FUNOBJ
: JSVAL_MASK32_NONFUNOBJ : JSVAL_MASK32_NONFUNOBJ
: JSVAL_MASK32_NULL; : JSVAL_MASK32_NULL;
data.s.payload.obj = arg.obj; data = OBJECT_TO_JSVAL_IMPL(mask, arg.obj);
} }
JS_ALWAYS_INLINE void JS_ALWAYS_INLINE void
Value::setObject(JSObject &arg) Value::setObject(JSObject &arg)
{ {
data.s.mask32 = arg.isFunction() ? JSVAL_MASK32_FUNOBJ JSValueMask32 mask = arg.isFunction() ? JSVAL_MASK32_FUNOBJ
: JSVAL_MASK32_NONFUNOBJ; : JSVAL_MASK32_NONFUNOBJ;
data.s.payload.obj = &arg; data = OBJECT_TO_JSVAL_IMPL(mask, &arg);
} }
JS_ALWAYS_INLINE void JS_ALWAYS_INLINE void
Value::setObjectOrNull(JSObject *arg) Value::setObjectOrNull(JSObject *arg)
{ {
data.s.mask32 = arg ? arg->isFunction() ? JSVAL_MASK32_FUNOBJ JSValueMask32 mask = arg ? arg->isFunction() ? JSVAL_MASK32_FUNOBJ
: JSVAL_MASK32_NONFUNOBJ : JSVAL_MASK32_NONFUNOBJ
: JSVAL_MASK32_NULL; : JSVAL_MASK32_NULL;
data.s.payload.obj = arg; data = OBJECT_TO_JSVAL_IMPL(mask, arg);
} }
} /* namespace js */ } /* namespace js */

View File

@ -816,9 +816,9 @@ END_CASE(JSOP_BITAND)
*/ */
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
#define XML_EQUALITY_OP(OP) \ #define XML_EQUALITY_OP(OP) \
if ((lmask == JSVAL_MASK32_NONFUNOBJ && lref.asObject().isXML()) || \ if ((lval.isNonFunObj() && lval.asObject().isXML()) || \
(rmask == JSVAL_MASK32_NONFUNOBJ && rref.asObject().isXML())) { \ (rval.isNonFunObj() && rval.asObject().isXML())) { \
if (!js_TestXMLEquality(cx, lref, rref, &cond)) \ if (!js_TestXMLEquality(cx, lval, rval, &cond)) \
goto error; \ goto error; \
cond = cond OP JS_TRUE; \ cond = cond OP JS_TRUE; \
} else } else
@ -826,7 +826,7 @@ END_CASE(JSOP_BITAND)
#define EXTENDED_EQUALITY_OP(OP) \ #define EXTENDED_EQUALITY_OP(OP) \
if (((clasp = l->getClass())->flags & JSCLASS_IS_EXTENDED) && \ if (((clasp = l->getClass())->flags & JSCLASS_IS_EXTENDED) && \
((ExtendedClass *)clasp)->equality) { \ ((ExtendedClass *)clasp)->equality) { \
if (!((ExtendedClass *)clasp)->equality(cx, l, &rref, &cond)) \ if (!((ExtendedClass *)clasp)->equality(cx, l, &lval, &cond)) \
goto error; \ goto error; \
cond = cond OP JS_TRUE; \ cond = cond OP JS_TRUE; \
} else } else
@ -837,57 +837,42 @@ END_CASE(JSOP_BITAND)
#define EQUALITY_OP(OP, IFNAN) \ #define EQUALITY_OP(OP, IFNAN) \
JS_BEGIN_MACRO \ JS_BEGIN_MACRO \
/* Depends on the value representation. */ \
Class *clasp; \ Class *clasp; \
JSBool cond; \ JSBool cond; \
Value &rref = regs.sp[-1]; \ Value rval = regs.sp[-1]; \
Value &lref = regs.sp[-2]; \ Value lval = regs.sp[-2]; \
uint32 rmask = rref.data.s.mask32; \
uint32 lmask = lref.data.s.mask32; \
XML_EQUALITY_OP(OP) \ XML_EQUALITY_OP(OP) \
if (lmask == rmask || \ if (SamePrimitiveTypeOrBothObjects(lval, rval)) { \
(Value::isObjectMask(lmask) && Value::isObjectMask(rmask))) { \ if (lval.isString()) { \
if (lmask == JSVAL_MASK32_STRING) { \ JSString *l = lval.asString(), *r = rval.asString(); \
JSString *l = lref.asString(), *r = rref.asString(); \
cond = js_EqualStrings(l, r) OP JS_TRUE; \ cond = js_EqualStrings(l, r) OP JS_TRUE; \
} else if (Value::isObjectMask(lmask)) { \ } else if (lval.isDouble()) { \
JSObject *l = &lref.asObject(), *r = &rref.asObject(); \ double l = lval.asDouble(), r = rval.asDouble(); \
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
} else if (lval.isObject()) { \
JSObject *l = &lval.asObject(), *r = &rval.asObject(); \
EXTENDED_EQUALITY_OP(OP) \ EXTENDED_EQUALITY_OP(OP) \
cond = l OP r; \ cond = l OP r; \
} else if (JS_UNLIKELY(Value::isDoubleMask(lmask))) { \
double l = lref.asDouble(), r = rref.asDouble(); \
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
} else { \ } else { \
cond = lref.data.s.payload.u32 OP rref.data.s.payload.u32; \ cond = lval.asRawUint32() OP rval.asRawUint32(); \
} \ } \
} else if (Value::isDoubleMask(lmask) && Value::isDoubleMask(rmask)) { \
double l = lref.asDouble(), r = rref.asDouble(); \
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
} else { \ } else { \
if (Value::isNullOrUndefinedMask(lmask)) { \ if (lval.isNullOrUndefined()) { \
cond = Value::isNullOrUndefinedMask(rmask) OP true; \ cond = rval.isNullOrUndefined() OP true; \
} else if (Value::isNullOrUndefinedMask(rmask)) { \ } else if (rval.isNullOrUndefined()) { \
cond = true OP false; \ cond = true OP false; \
} else { \ } else { \
if (Value::isObjectMask(lmask)) { \ if (lval.isObject()) \
JSObject &obj = lref.asObject(); \ DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval); \
if (!obj.defaultValue(cx, JSTYPE_VOID, &lref)) \ if (rval.isObject()) \
goto error; \ DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval); \
lmask = lref.data.s.mask32; \ if (BothString(lval, rval)) { \
} \ JSString *l = lval.asString(), *r = rval.asString(); \
if (Value::isObjectMask(rmask)) { \
JSObject &obj = rref.asObject(); \
if (!obj.defaultValue(cx, JSTYPE_VOID, &rref)) \
goto error; \
rmask = rref.data.s.mask32; \
} \
if (lmask == JSVAL_MASK32_STRING && rmask == JSVAL_MASK32_STRING) { \
JSString *l = lref.asString(), *r = rref.asString(); \
cond = js_EqualStrings(l, r) OP JS_TRUE; \ cond = js_EqualStrings(l, r) OP JS_TRUE; \
} else { \ } else { \
double l, r; \ double l, r; \
if (!ValueToNumber(cx, lref, &l) || \ if (!ValueToNumber(cx, lval, &l) || \
!ValueToNumber(cx, rref, &r)) { \ !ValueToNumber(cx, rval, &r)) { \
goto error; \ goto error; \
} \ } \
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \ cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
@ -963,39 +948,24 @@ END_CASE(JSOP_CASEX)
#define RELATIONAL_OP(OP) \ #define RELATIONAL_OP(OP) \
JS_BEGIN_MACRO \ JS_BEGIN_MACRO \
/* Depends on the value representation */ \ Value rval = regs.sp[-1]; \
Value &rref = regs.sp[-1]; \ Value lval = regs.sp[-2]; \
Value &lref = regs.sp[-2]; \
uint32 rmask = rref.data.s.mask32; \
uint32 lmask = lref.data.s.mask32; \
uint32 maskand = lmask & rmask; \
bool cond; \ bool cond; \
/* Optimize for two int-tagged operands (typical loop control). */ \ /* Optimize for two int-tagged operands (typical loop control). */ \
if (maskand == JSVAL_MASK32_INT32) { \ if (BothInt32(lval, rval)) { \
cond = lref.asInt32() OP rref.asInt32(); \ cond = lval.asInt32() OP rval.asInt32(); \
} else { \ } else { \
if (Value::isObjectMask(lmask | rmask)) { \ if (lval.isObject()) \
if (Value::isObjectMask(lmask)) { \ DEFAULT_VALUE(cx, -2, JSTYPE_NUMBER, lval); \
JSObject &obj = lref.asObject(); \ if (rval.isObject()) \
if (!obj.defaultValue(cx, JSTYPE_NUMBER, &lref)) \ DEFAULT_VALUE(cx, -1, JSTYPE_NUMBER, rval); \
goto error; \ if (BothString(lval, rval)) { \
lmask = lref.data.s.mask32; \ JSString *l = lval.asString(), *r = rval.asString(); \
} \
if (Value::isObjectMask(rmask)) { \
JSObject &obj = rref.asObject(); \
if (!obj.defaultValue(cx, JSTYPE_NUMBER, &rref)) \
goto error; \
rmask = rref.data.s.mask32; \
} \
maskand = lmask & rmask; \
} \
if (maskand == JSVAL_MASK32_STRING) { \
JSString *l = lref.asString(), *r = rref.asString(); \
cond = js_CompareStrings(l, r) OP 0; \ cond = js_CompareStrings(l, r) OP 0; \
} else { \ } else { \
double l, r; \ double l, r; \
if (!ValueToNumber(cx, lref, &l) || \ if (!ValueToNumber(cx, lval, &l) || \
!ValueToNumber(cx, rref, &r)) { \ !ValueToNumber(cx, rval, &r)) { \
goto error; \ goto error; \
} \ } \
cond = JSDOUBLE_COMPARE(l, OP, r, false); \ cond = JSDOUBLE_COMPARE(l, OP, r, false); \
@ -1058,20 +1028,17 @@ BEGIN_CASE(JSOP_URSH)
u >>= (j & 31); u >>= (j & 31);
regs.sp--; regs.sp--;
Uint32ToValue(u, &regs.sp[-1]); regs.sp[-1].setNumber(uint32(u));
} }
END_CASE(JSOP_URSH) END_CASE(JSOP_URSH)
BEGIN_CASE(JSOP_ADD) BEGIN_CASE(JSOP_ADD)
{ {
/* Depends on the value representation */ Value rval = regs.sp[-1];
Value &rref = regs.sp[-1]; Value lval = regs.sp[-2];
Value &lref = regs.sp[-2];
uint32 rmask = rref.data.s.mask32;
uint32 lmask = lref.data.s.mask32;
if ((lmask & rmask) == JSVAL_MASK32_INT32) { if (BothInt32(lval, rval)) {
int32_t l = lref.asInt32(), r = rref.asInt32(); int32_t l = lval.asInt32(), r = rval.asInt32();
int32_t sum = l + r; int32_t sum = l + r;
regs.sp--; regs.sp--;
if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000))) if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000)))
@ -1080,50 +1047,47 @@ BEGIN_CASE(JSOP_ADD)
regs.sp[-1].setInt32(sum); regs.sp[-1].setInt32(sum);
} else } else
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
if (lmask == JSVAL_MASK32_NONFUNOBJ && lref.asObject().isXML() && if (lval.isNonFunObj() && lval.asObject().isXML() &&
rmask == JSVAL_MASK32_NONFUNOBJ && rref.asObject().isXML()) { rval.isNonFunObj() && rval.asObject().isXML()) {
Value rval; Value rval;
if (!js_ConcatenateXML(cx, &lref.asObject(), &rref.asObject(), &rval)) if (!js_ConcatenateXML(cx, &lval.asObject(), &rval.asObject(), &rval))
goto error; goto error;
regs.sp--; regs.sp--;
regs.sp[-1] = rval; regs.sp[-1] = rval;
} else } else
#endif #endif
{ {
if (Value::isObjectMask(lmask)) { if (lval.isObject())
if (!lref.asObject().defaultValue(cx, JSTYPE_VOID, &lref)) DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval);
goto error; if (rval.isObject())
lmask = lref.data.s.mask32; DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval);
} bool lIsString, rIsString;
if (Value::isObjectMask(rmask)) { if ((lIsString = lval.isString()) | (rIsString = rval.isString())) {
if (!rref.asObject().defaultValue(cx, JSTYPE_VOID, &rref)) JSString *lstr, *rstr;
goto error; if (lIsString) {
rmask = rref.data.s.mask32; lstr = lval.asString();
}
if (lmask == JSVAL_MASK32_STRING || rmask == JSVAL_MASK32_STRING) {
JSString *str1, *str2;
if (lmask == rmask) {
str1 = lref.asString();
str2 = rref.asString();
} else if (lmask == JSVAL_MASK32_STRING) {
str1 = lref.asString();
str2 = js_ValueToString(cx, rref);
if (!str2)
goto error;
} else { } else {
str2 = rref.asString(); lstr = js_ValueToString(cx, lval);
str1 = js_ValueToString(cx, lref); if (!lstr)
if (!str1)
goto error; goto error;
regs.sp[-2].setString(lstr);
} }
JSString *str = js_ConcatStrings(cx, str1, str2); if (rIsString) {
rstr = rval.asString();
} else {
rstr = js_ValueToString(cx, rval);
if (!rstr)
goto error;
regs.sp[-1].setString(rstr);
}
JSString *str = js_ConcatStrings(cx, lstr, rstr);
if (!str) if (!str)
goto error; goto error;
regs.sp--; regs.sp--;
regs.sp[-1].setString(str); regs.sp[-1].setString(str);
} else { } else {
double l, r; double l, r;
if (!ValueToNumber(cx, lref, &l) || !ValueToNumber(cx, rref, &r)) if (!ValueToNumber(cx, lval, &l) || !ValueToNumber(cx, rval, &r))
goto error; goto error;
l += r; l += r;
regs.sp--; regs.sp--;
@ -1788,9 +1752,7 @@ BEGIN_CASE(JSOP_CALLPROP)
if (!atom) { if (!atom) {
ASSERT_VALID_PROPERTY_CACHE_HIT(0, aobj, obj2, entry); ASSERT_VALID_PROPERTY_CACHE_HIT(0, aobj, obj2, entry);
if (entry->vword.isFunObj()) { if (entry->vword.isFunObj()) {
regs.sp[-1].setFunObj(entry->vword.toFunObj()); rval.setFunObj(entry->vword.toFunObj());
PUSH_COPY(lval);
goto end_callprop;
} else if (entry->vword.isSlot()) { } else if (entry->vword.isSlot()) {
uint32 slot = entry->vword.toSlot(); uint32 slot = entry->vword.toSlot();
JS_ASSERT(slot < obj2->scope()->freeslot); JS_ASSERT(slot < obj2->scope()->freeslot);
@ -2150,15 +2112,10 @@ END_CASE(JSOP_GETELEM)
BEGIN_CASE(JSOP_CALLELEM) BEGIN_CASE(JSOP_CALLELEM)
{ {
/* Depends on the value representation. */
/* Fetch the left part and resolve it to a non-null object. */ /* Fetch the left part and resolve it to a non-null object. */
JSObject *obj; JSObject *obj;
FETCH_OBJECT(cx, -2, obj); FETCH_OBJECT(cx, -2, obj);
/* Save the mask so that we don't need to query it later. */
uint32 objmask = regs.sp[-2].data.s.mask32;
/* Fetch index and convert it to id suitable for use with obj. */ /* Fetch index and convert it to id suitable for use with obj. */
jsid id; jsid id;
FETCH_ELEMENT_ID(obj, -1, id); FETCH_ELEMENT_ID(obj, -1, id);
@ -2176,8 +2133,7 @@ BEGIN_CASE(JSOP_CALLELEM)
} else } else
#endif #endif
{ {
regs.sp[-1].data.s.mask32 = objmask; regs.sp[-1].setObject(*obj);
regs.sp[-1].data.s.payload.obj = obj;
} }
} }
END_CASE(JSOP_CALLELEM) END_CASE(JSOP_CALLELEM)

View File

@ -158,35 +158,12 @@ typedef struct JSONParser JSONParser;
*/ */
/* /*
* TODO: wrong, fix, explain more * TODO: explain boxing strategy
* Engine-internal value details:
*
* A jsval has an abstract type which is represented by a mask which assigns a
* bit to each type. This allows fast set-membership queries. However, we give
* one type (null) a mask of 0 for two reasons:
*
* 1. memset'ing values to 0 produces a valid value. This was true of the old,
* boxed jsvals (and now jsboxedwords) and eases the transition.
*
* 2. Testing for null can often be compiled to slightly shorter/faster code.
*
* The down-side is that set-membership queries need to be done more carefully.
* E.g., to test whether a value v is undefined or null, the correct test is:
*
* (v.mask & ~UndefinedMask) == 0
*
* instead of the intuitive (but incorrect) test:
*
* (v.mask & (NullMask | UndefinedMask)) != 0
*
* Since the value representation is kept a private detail of js::Value and
* only exposed to a few functions through friendship, this type of error
* should be hidden behind simple inline methods like v.isNullOrUndefined().
*/ */
typedef enum JSValueMask16 typedef enum JSValueMask16
#if defined(_MSC_VER) && _MSC_VER >= 1400 #if defined(_MSC_VER)
: unsigned short : uint16
#endif #endif
{ {
JSVAL_MASK16_NULL = (uint16)0x0001, JSVAL_MASK16_NULL = (uint16)0x0001,
@ -203,6 +180,11 @@ typedef enum JSValueMask16
JSVAL_MASK16_OBJORNULL = JSVAL_MASK16_OBJECT | JSVAL_MASK16_NULL, JSVAL_MASK16_OBJORNULL = JSVAL_MASK16_OBJECT | JSVAL_MASK16_NULL,
JSVAL_MASK16_GCTHING = JSVAL_MASK16_OBJECT | JSVAL_MASK16_STRING, JSVAL_MASK16_GCTHING = JSVAL_MASK16_OBJECT | JSVAL_MASK16_STRING,
/*
* This enumerator value plus __attribute__((packed)) plus the static
* assert that sizeof(JSValueMask16) == 2 should guarantee that enumerators
* are uint16 in GCC.
*/
JSVAL_NANBOX_PATTERN = ((uint16)0xFFFF) JSVAL_NANBOX_PATTERN = ((uint16)0xFFFF)
} }
#if defined(__GNUC__) #if defined(__GNUC__)
@ -210,45 +192,36 @@ __attribute__((packed))
#endif #endif
JSValueMask16; JSValueMask16;
#define JSVAL_MASK32_CLEAR ((uint32)0xFFFF0000) typedef enum JSValueMask32
#if defined(_MSC_VER)
#define JSVAL_MASK32_NULL ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_NULL)) : uint32
#define JSVAL_MASK32_UNDEFINED ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_UNDEFINED))
#define JSVAL_MASK32_INT32 ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_INT32))
#define JSVAL_MASK32_STRING ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_STRING))
#define JSVAL_MASK32_NONFUNOBJ ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_NONFUNOBJ))
#define JSVAL_MASK32_FUNOBJ ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_FUNOBJ))
#define JSVAL_MASK32_BOOLEAN ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_BOOLEAN))
#define JSVAL_MASK32_MAGIC ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_MAGIC))
#define JSVAL_MASK32_SINGLETON ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_SINGLETON))
#define JSVAL_MASK32_OBJECT ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_OBJECT))
#define JSVAL_MASK32_OBJORNULL ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_OBJORNULL))
#define JSVAL_MASK32_GCTHING ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_GCTHING))
typedef enum JSWhyMagic
{
JS_ARRAY_HOLE, /* a hole in a dense array */
JS_ARGS_HOLE, /* a hole in the args object's array */
JS_NATIVE_ENUMERATE, /* indicates that a custom enumerate hook forwarded
* to js_Enumerate, which really means the object can be
* enumerated like a native object. */
JS_NO_ITER_VALUE, /* there is not a pending iterator value */
JS_GENERATOR_CLOSING /* exception value thrown when closing a generator */
} JSWhyMagic;
typedef union jsval_payload
{
int32 i32;
uint32 u32;
JSBool boo;
#if JS_BITS_PER_WORD == 32
JSString *str;
JSObject *obj;
void *ptr;
#endif #endif
JSWhyMagic why; {
} jsval_data; /*
* This enumerator value plus __attribute__((packed)) plus the static
* assert that sizeof(JSValueMask32) == 4 should guarantee that enumerators
* are uint32 in GCC.
*/
JSVAL_MASK32_CLEAR = ((uint32)0xFFFF0000),
JSVAL_MASK32_NULL = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_NULL)),
JSVAL_MASK32_UNDEFINED = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_UNDEFINED)),
JSVAL_MASK32_INT32 = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_INT32)),
JSVAL_MASK32_STRING = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_STRING)),
JSVAL_MASK32_NONFUNOBJ = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_NONFUNOBJ)),
JSVAL_MASK32_FUNOBJ = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_FUNOBJ)),
JSVAL_MASK32_BOOLEAN = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_BOOLEAN)),
JSVAL_MASK32_MAGIC = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_MAGIC)),
JSVAL_MASK32_SINGLETON = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_SINGLETON)),
JSVAL_MASK32_OBJECT = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_OBJECT)),
JSVAL_MASK32_OBJORNULL = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_OBJORNULL)),
JSVAL_MASK32_GCTHING = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_GCTHING))
}
#if defined(__GNUC__)
__attribute__((packed))
#endif
JSValueMask32;
#ifdef __GNUC__ #ifdef __GNUC__
# define VALUE_ALIGNMENT __attribute__((aligned (8))) # define VALUE_ALIGNMENT __attribute__((aligned (8)))
@ -264,32 +237,376 @@ typedef union jsval_payload
# error "TODO: do something for compiler" # error "TODO: do something for compiler"
#endif #endif
typedef VALUE_ALIGNMENT uint64 jsval;
#define BUILD_JSVAL(mask32, payload) ((jsval)((((uint64)(uint32)(mask32)) << 32) | (uint32)(payload)))
typedef enum JSWhyMagic
{
JS_ARRAY_HOLE, /* a hole in a dense array */
JS_ARGS_HOLE, /* a hole in the args object's array */
JS_NATIVE_ENUMERATE, /* indicates that a custom enumerate hook forwarded
* to js_Enumerate, which really means the object can be
* enumerated like a native object. */
JS_NO_ITER_VALUE, /* there is not a pending iterator value */
JS_GENERATOR_CLOSING /* exception value thrown when closing a generator */
} JSWhyMagic;
#if !defined(IS_LITTLE_ENDIAN) #if !defined(IS_LITTLE_ENDIAN)
# error "Need to fix up jsval_layout" # error "Unsupported configuration"
#endif #endif
// TODO: explain
typedef union jsval_layout typedef union jsval_layout
{ {
uint64 asBits; uint64 asBits;
struct { struct {
jsval_payload payload; union {
int32 i32;
uint32 u32;
JSBool boo;
#if JS_BITS_PER_WORD == 32
JSString *str;
JSObject *obj;
void *ptr;
#elif JS_BITS_PER_WORD == 64
uint32 ptr;
#else
# error "Unsupported configuration"
#endif
JSWhyMagic why;
} payload;
union { union {
struct { struct {
JSValueMask16 mask16; JSValueMask16 mask16;
uint16 nanBits; uint16 nanBits;
} tag; } tag;
uint32 mask32; JSValueMask32 mask32;
}; };
} s; } s;
double asDouble; double asDouble;
} jsval_layout; } jsval_layout;
typedef uint64 jsval; #if JS_BITS_PER_WORD == 32
/* These are engine-internal details, not part of the public API */ static JS_ALWAYS_INLINE JSBool
#define DOUBLE_AS_JSVAL(d) (*(jsval *)&(d)) JSVAL_IS_NULL_IMPL(jsval_layout l)
#define JSVAL_CONSTANT(mask32, payload) ((jsval)((((uint64)(mask32)) << 32) | (payload))) {
return l.s.mask32 == JSVAL_MASK32_NULL;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
{
return l.s.mask32 == JSVAL_MASK32_UNDEFINED;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
{
return l.s.mask32 == JSVAL_MASK32_INT32 && l.s.payload.i32 == i32;
}
static JS_ALWAYS_INLINE jsval_layout
INT32_TO_JSVAL_IMPL(int32 i)
{
jsval_layout l;
l.s.mask32 = JSVAL_MASK32_INT32;
l.s.payload.i32 = i;
return l;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
{
return l.s.mask32 < JSVAL_MASK32_CLEAR;
}
static JS_ALWAYS_INLINE jsval_layout
DOUBLE_TO_JSVAL_IMPL(jsdouble d)
{
jsval_layout l;
l.asDouble = d;
JS_ASSERT(l.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
return l;
}
static JS_ALWAYS_INLINE jsval_layout
STRING_TO_JSVAL_IMPL(JSString *str)
{
jsval_layout l;
l.s.mask32 = JSVAL_MASK32_STRING;
l.s.payload.str = str;
return l;
}
static JS_ALWAYS_INLINE JSString *
JSVAL_TO_STRING_IMPL(jsval_layout l)
{
return l.s.payload.str;
}
static JS_ALWAYS_INLINE JSObject *
JSVAL_TO_OBJECT_IMPL(jsval_layout l)
{
return l.s.payload.obj;
}
static JS_ALWAYS_INLINE jsval_layout
OBJECT_TO_JSVAL_IMPL(JSValueMask32 mask, JSObject *obj)
{
jsval_layout l;
l.s.mask32 = mask;
l.s.payload.obj = obj;
return l;
}
static JS_ALWAYS_INLINE jsval_layout
BOOLEAN_TO_JSVAL_IMPL(JSBool b)
{
jsval_layout l;
l.s.mask32 = JSVAL_MASK32_BOOLEAN;
l.s.payload.boo = b;
return l;
}
static JS_ALWAYS_INLINE void *
JSVAL_TO_GCTHING_IMPL(jsval_layout l)
{
return l.s.payload.ptr;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
{
return (l.s.mask32 == JSVAL_MASK32_BOOLEAN) && (l.s.payload.boo == b);
}
static JS_ALWAYS_INLINE jsval_layout
PRIVATE_TO_JSVAL_IMPL(void *ptr)
{
JS_ASSERT(((uint32)ptr & 1) == 0);
jsval_layout l;
l.s.tag.nanBits = 0;
l.s.payload.ptr = ptr;
return l;
}
static JS_ALWAYS_INLINE void *
JSVAL_TO_PRIVATE_IMPL(jsval_layout l)
{
return l.s.payload.ptr;
}
static JS_ALWAYS_INLINE jsval_layout
MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
{
jsval_layout l;
l.s.mask32 = JSVAL_MASK32_MAGIC;
l.s.payload.why = why;
return l;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_SAME_PRIMITIVE_TYPE_OR_BOTH_OBJECTS_IMPL(jsval_layout lhs, jsval_layout rhs)
{
return ((lhs.s.mask32 ^ rhs.s.mask32) & ~(uint32)JSVAL_MASK16_OBJECT) == 0 ||
(lhs.s.mask32 < JSVAL_MASK32_CLEAR && rhs.s.mask32 < JSVAL_MASK32_CLEAR);
}
static JS_ALWAYS_INLINE JSBool
JSVAL_BOTH_STRING_IMPL(jsval_layout lhs, jsval_layout rhs)
{
return (lhs.s.mask32 & rhs.s.mask32) == JSVAL_MASK32_STRING;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_BOTH_INT32_IMPL(jsval_layout lhs, jsval_layout rhs)
{
return (lhs.s.mask32 & rhs.s.mask32) == JSVAL_MASK32_INT32;
}
#elif JS_BITS_PER_WORD == 64
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_NULL_IMPL(jsval_layout l)
{
return l.asBits == BUILD_JSVAL(JSVAL_MASK32_NULL, 0);
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
{
return l.asBits == BUILD_JSVAL(JSVAL_MASK32_UNDEFINED, 0);
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
{
return l.asBits == BUILD_JSVAL(JSVAL_MASK32_INT32, i32);
}
static JS_ALWAYS_INLINE jsval_layout
INT32_TO_JSVAL_IMPL(int32 i)
{
jsval_layout l;
l.asBits = BUILD_JSVAL(JSVAL_MASK32_INT32, i);
return l;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
{
return l.asBits < BUILD_JSVAL(JSVAL_MASK32_CLEAR, 0);
}
static JS_ALWAYS_INLINE jsval_layout
DOUBLE_TO_JSVAL_IMPL(jsdouble d)
{
jsval_layout l;
l.asDouble = d;
JS_ASSERT(l.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
return l;
}
static JS_ALWAYS_INLINE jsval_layout
STRING_TO_JSVAL_IMPL(JSString *str)
{
JS_ASSERT((size_t)str < (size_t)0xFFFFFFFF);
jsval_layout l;
l.asBits = BUILD_JSVAL(JSVAL_MASK32_STRING, (uint32)(size_t)str);
return l;
}
static JS_ALWAYS_INLINE JSString *
JSVAL_TO_STRING_IMPL(jsval_layout l)
{
return (JSString *)(uint64)l.s.payload.ptr;
}
static JS_ALWAYS_INLINE JSObject *
JSVAL_TO_OBJECT_IMPL(jsval_layout l)
{
return (JSObject *)(uint64)l.s.payload.ptr;
}
static JS_ALWAYS_INLINE jsval_layout
OBJECT_TO_JSVAL_IMPL(JSValueMask32 mask32, JSObject *obj)
{
JS_ASSERT((size_t)obj < (size_t)0xFFFFFFFF);
jsval_layout l;
l.asBits = BUILD_JSVAL(mask32, (uint32)(size_t)obj);
return l;
}
static JS_ALWAYS_INLINE jsval_layout
BOOLEAN_TO_JSVAL_IMPL(JSBool b)
{
jsval_layout l;
l.asBits = BUILD_JSVAL(JSVAL_MASK32_BOOLEAN, b);
return l;
}
static JS_ALWAYS_INLINE void *
JSVAL_TO_GCTHING_IMPL(jsval_layout l)
{
return (void *)(uint64)l.s.payload.ptr;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
{
return l.asBits == BUILD_JSVAL(JSVAL_MASK32_BOOLEAN, b);
}
static JS_ALWAYS_INLINE jsval_layout
PRIVATE_TO_JSVAL_IMPL(void *ptr)
{
JS_ASSERT(((uint32)(size_t)ptr & 1) == 0);
jsval_layout l;
l.asBits = 0x8000000000000000LL | ((size_t)ptr >> 1);
return l;
}
static JS_ALWAYS_INLINE void *
JSVAL_TO_PRIVATE_IMPL(jsval_layout l)
{
return (void *)(l.asBits << 1);
}
static JS_ALWAYS_INLINE jsval_layout
MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
{
jsval_layout l;
l.asBits = BUILD_JSVAL(JSVAL_MASK32_MAGIC, why);
return l;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_SAME_PRIMITIVE_TYPE_OR_BOTH_OBJECTS_IMPL(jsval_layout lhs, jsval_layout rhs)
{
uint32 xor32 = (uint32)((lhs.asBits ^ rhs.asBits) >> 32);
return (xor32 & ~(uint32)JSVAL_MASK16_OBJECT) == 0 ||
(JSVAL_IS_DOUBLE_IMPL(lhs) && JSVAL_IS_DOUBLE_IMPL(rhs));
}
static JS_ALWAYS_INLINE JSBool
JSVAL_BOTH_STRING_IMPL(jsval_layout lhs, jsval_layout rhs)
{
return (uint32)((lhs.asBits & rhs.asBits) >> 32) == JSVAL_MASK32_STRING;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_BOTH_INT32_IMPL(jsval_layout lhs, jsval_layout rhs)
{
return (uint32)((lhs.asBits & rhs.asBits) >> 32) == JSVAL_MASK32_INT32;
}
#else
# error "Unsupported configuration"
#endif
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_SINGLETON_IMPL(jsval_layout l)
{
return (l.s.mask32 & JSVAL_MASK32_SINGLETON) > JSVAL_MASK32_CLEAR;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_NUMBER_IMPL(jsval_layout l)
{
JSValueMask32 mask = l.s.mask32;
return mask < JSVAL_MASK32_CLEAR || mask == JSVAL_MASK32_INT32;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_OBJECT_IMPL(jsval_layout l)
{
return (l.s.mask32 & JSVAL_MASK32_OBJECT) > JSVAL_MASK32_CLEAR;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
{
return (l.s.mask32 & JSVAL_MASK32_OBJORNULL) > JSVAL_MASK32_CLEAR;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
{
return (l.s.mask32 & JSVAL_MASK32_OBJECT) <= JSVAL_MASK32_CLEAR;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_GCTHING_IMPL(jsval_layout l)
{
return (l.s.mask32 & JSVAL_MASK32_GCTHING) > JSVAL_MASK32_CLEAR;
}
static JS_ALWAYS_INLINE uint32
JSVAL_TRACE_KIND_IMPL(jsval_layout l)
{
return (uint32)(l.s.mask32 == JSVAL_MASK32_STRING);
}
/* /*
* Boxed word macros (private engine detail) * Boxed word macros (private engine detail)
@ -396,7 +713,7 @@ static JS_ALWAYS_INLINE jsint
JSBOXEDWORD_TO_SPECIAL(jsboxedword w) JSBOXEDWORD_TO_SPECIAL(jsboxedword w)
{ {
JS_ASSERT(JSBOXEDWORD_IS_SPECIAL(w)); JS_ASSERT(JSBOXEDWORD_IS_SPECIAL(w));
return w >> JSBOXEDWORD_TAGBITS; return jsint(w >> JSBOXEDWORD_TAGBITS);
} }
static JS_ALWAYS_INLINE jsboxedword static JS_ALWAYS_INLINE jsboxedword

View File

@ -633,7 +633,7 @@ Class js_StringClass = {
static JSString * static JSString *
NormalizeThis(JSContext *cx, Value *vp) NormalizeThis(JSContext *cx, Value *vp)
{ {
if (vp[1].isNull() || !ComputeThisFromVpInPlace(cx, vp) || vp[1].isNull()) if (vp[1].isNull() && (!ComputeThisFromVpInPlace(cx, vp) || vp[1].isNull()))
return NULL; return NULL;
/* /*
@ -2640,7 +2640,11 @@ static const jschar UnitStringData[] = {
#pragma pack(push, 8) #pragma pack(push, 8)
#endif #endif
#ifndef _M_X64
JSString JSString::unitStringTable[] JSString JSString::unitStringTable[]
#else
JSString JSString::staticUnitStringTable[]
#endif
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__ ((aligned (8))) __attribute__ ((aligned (8)))
#endif #endif
@ -2679,6 +2683,11 @@ __attribute__ ((aligned (8)))
U(0xf8), U(0xf9), U(0xfa), U(0xfb), U(0xfc), U(0xfd), U(0xfe), U(0xff) U(0xf8), U(0xf9), U(0xfa), U(0xfb), U(0xfc), U(0xfd), U(0xfe), U(0xff)
}; };
#ifdef _M_X64
JSString *JSString::unitStringTable = staticUnitStringTable;
size_t JSString::unitStringTableSize = sizeof(staticUnitStringTable);
#endif
#ifdef __SUNPRO_CC #ifdef __SUNPRO_CC
#pragma pack(0) #pragma pack(0)
#else #else
@ -2749,7 +2758,11 @@ static const jschar Hundreds[] = {
#pragma pack(push, 8) #pragma pack(push, 8)
#endif #endif
#ifndef _M_X64
JSString JSString::intStringTable[] JSString JSString::intStringTable[]
#else
JSString JSString::staticIntStringTable[]
#endif
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__ ((aligned (8))) __attribute__ ((aligned (8)))
#endif #endif
@ -2788,6 +2801,11 @@ __attribute__ ((aligned (8)))
L3(0xf8), L3(0xf9), L3(0xfa), L3(0xfb), L3(0xfc), L3(0xfd), L3(0xfe), L3(0xff) L3(0xf8), L3(0xf9), L3(0xfa), L3(0xfb), L3(0xfc), L3(0xfd), L3(0xfe), L3(0xff)
}; };
#ifdef _M_X64
JSString *JSString::intStringTable = staticIntStringTable;
size_t JSString::intStringTableSize = sizeof(staticIntStringTable);
#endif
#ifdef __SUNPRO_CC #ifdef __SUNPRO_CC
#pragma pack(0) #pragma pack(0)
#else #else

View File

@ -289,8 +289,20 @@ struct JSString {
#pragma align 8 (__1cIJSStringPunitStringTable_, __1cIJSStringOintStringTable_) #pragma align 8 (__1cIJSStringPunitStringTable_, __1cIJSStringOintStringTable_)
#endif #endif
#ifndef _M_X64
static JSString unitStringTable[]; static JSString unitStringTable[];
static JSString intStringTable[]; static JSString intStringTable[];
#else
static JSString staticUnitStringTable[];
static JSString staticIntStringTable[];
static JSString *unitStringTable;
static JSString *intStringTable;
static size_t unitStringTableSize;
static size_t intStringTableSize;
static bool initStringTables();
static void freeStringTables();
#endif
static const char *deflatedIntStringTable[]; static const char *deflatedIntStringTable[];
static const char deflatedUnitStringTable[]; static const char deflatedUnitStringTable[];

View File

@ -3298,10 +3298,10 @@ Scatter(JSContext *cx, uintN argc, jsval *vp)
goto fail; goto fail;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
sd.results[i] = JSVAL_VOID; sd.results[i] = JSVAL_VOID;
ok = JS_AddRoot(cx, &sd.results[i]); ok = JS_AddValueRoot(cx, &sd.results[i]);
if (!ok) { if (!ok) {
while (i-- > 0) while (i-- > 0)
JS_RemoveRoot(cx, &sd.results[i]); JS_RemoveValueRoot(cx, &sd.results[i]);
free(sd.results); free(sd.results);
sd.results = NULL; sd.results = NULL;
goto fail; goto fail;
@ -3318,14 +3318,14 @@ Scatter(JSContext *cx, uintN argc, jsval *vp)
sd.threads[i].cx = NULL; sd.threads[i].cx = NULL;
sd.threads[i].fn = JSVAL_NULL; sd.threads[i].fn = JSVAL_NULL;
ok = JS_AddRoot(cx, &sd.threads[i].fn); ok = JS_AddValueRoot(cx, &sd.threads[i].fn);
if (ok && !JS_GetElement(cx, inArr, (jsint) i, &sd.threads[i].fn)) { if (ok && !JS_GetElement(cx, inArr, (jsint) i, &sd.threads[i].fn)) {
JS_RemoveRoot(cx, &sd.threads[i].fn); JS_RemoveValueRoot(cx, &sd.threads[i].fn);
ok = JS_FALSE; ok = JS_FALSE;
} }
if (!ok) { if (!ok) {
while (i-- > 0) while (i-- > 0)
JS_RemoveRoot(cx, &sd.threads[i].fn); JS_RemoveValueRoot(cx, &sd.threads[i].fn);
free(sd.threads); free(sd.threads);
sd.threads = NULL; sd.threads = NULL;
goto fail; goto fail;
@ -3393,7 +3393,7 @@ out:
JSContext *acx; JSContext *acx;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
JS_RemoveRoot(cx, &sd.threads[i].fn); JS_RemoveValueRoot(cx, &sd.threads[i].fn);
acx = sd.threads[i].cx; acx = sd.threads[i].cx;
if (acx) { if (acx) {
JS_SetContextThread(acx); JS_SetContextThread(acx);
@ -3404,7 +3404,7 @@ out:
} }
if (sd.results) { if (sd.results) {
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
JS_RemoveRoot(cx, &sd.results[i]); JS_RemoveValueRoot(cx, &sd.results[i]);
free(sd.results); free(sd.results);
} }
if (sd.cvar) if (sd.cvar)
@ -5091,7 +5091,7 @@ main(int argc, char **argv, char **envp)
JSObject *newGlobalObject(JSContext *cx) { return NewGlobalObject(cx); } JSObject *newGlobalObject(JSContext *cx) { return NewGlobalObject(cx); }
}; };
ShellWorkerHooks hooks; ShellWorkerHooks hooks;
if (!JS_AddNamedRoot(cx, &gWorkers, "Workers") || if (!JS_AddNamedObjectRoot(cx, &gWorkers, "Workers") ||
!js::workers::init(cx, &hooks, glob, &gWorkers)) { !js::workers::init(cx, &hooks, glob, &gWorkers)) {
return 1; return 1;
} }
@ -5101,7 +5101,7 @@ main(int argc, char **argv, char **envp)
#ifdef JS_THREADSAFE #ifdef JS_THREADSAFE
js::workers::finish(cx, gWorkers); js::workers::finish(cx, gWorkers);
JS_RemoveRoot(cx, &gWorkers); JS_RemoveObjectRoot(cx, &gWorkers);
if (result == 0) if (result == 0)
result = gExitCode; result = gExitCode;
#endif #endif

View File

@ -670,7 +670,7 @@ class Worker : public WorkerParent
return !w->checkTermination(); return !w->checkTermination();
} }
static JSBool jsResolveGlobal(JSContext *cx, JSObject *obj, jsval id, uintN flags, static JSBool jsResolveGlobal(JSContext *cx, JSObject *obj, jsid id, uintN flags,
JSObject **objp) JSObject **objp)
{ {
if ((flags & JSRESOLVE_ASSIGNING) == 0) { if ((flags & JSRESOLVE_ASSIGNING) == 0) {
@ -869,7 +869,7 @@ class InitEvent : public Event
return fail; return fail;
AutoValueRooter rval(cx); AutoValueRooter rval(cx);
JSBool ok = JS_ExecuteScript(cx, child->getGlobal(), script, rval.addr()); JSBool ok = JS_ExecuteScript(cx, child->getGlobal(), script, Jsvalify(rval.addr()));
JS_DestroyScript(cx, script); JS_DestroyScript(cx, script);
return Result(ok); return Result(ok);
} }
@ -906,7 +906,7 @@ class ErrorEvent : public Event
JSString *data = NULL; JSString *data = NULL;
jsval exc; jsval exc;
if (JS_GetPendingException(cx, &exc)) { if (JS_GetPendingException(cx, &exc)) {
AutoValueRooter tvr(cx, exc); AutoValueRooter tvr(cx, Valueify(exc));
JS_ClearPendingException(cx); JS_ClearPendingException(cx);
// Determine what error message to put in the error event. // Determine what error message to put in the error event.

View File

@ -125,10 +125,10 @@ class ResultsSink:
# key is (result, expect, random) # key is (result, expect, random)
# value is (tinderbox label, dev test category) # value is (tinderbox label, dev test category)
LABELS = { LABELS = {
(TestResult.CRASH, False, False): ('TEST-UNEXPECTED-CRASH', 'REGRESSIONS'), (TestResult.CRASH, False, False): ('TEST-UNEXPECTED-FAIL', 'REGRESSIONS'),
(TestResult.CRASH, False, True): ('TEST-UNEXPECTED-CRASH', 'REGRESSIONS'), (TestResult.CRASH, False, True): ('TEST-UNEXPECTED-FAIL', 'REGRESSIONS'),
(TestResult.CRASH, True, False): ('TEST-UNEXPECTED-CRASH', 'REGRESSIONS'), (TestResult.CRASH, True, False): ('TEST-UNEXPECTED-FAIL', 'REGRESSIONS'),
(TestResult.CRASH, True, True): ('TEST-UNEXPECTED-CRASH', 'REGRESSIONS'), (TestResult.CRASH, True, True): ('TEST-UNEXPECTED-FAIL', 'REGRESSIONS'),
(TestResult.FAIL, False, False): ('TEST-KNOWN-FAIL', ''), (TestResult.FAIL, False, False): ('TEST-KNOWN-FAIL', ''),
(TestResult.FAIL, False, True): ('TEST-KNOWN-FAIL (EXPECTED RANDOM)', ''), (TestResult.FAIL, False, True): ('TEST-KNOWN-FAIL (EXPECTED RANDOM)', ''),