[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 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);
static JSBool NameGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool NameGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool SizeGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool SizeGetter(JSContext* cx, JSObject* obj, jsid idval,
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 ToString(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 {
@ -107,11 +107,11 @@ namespace PointerType {
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc,
jsval* argv, jsval* rval);
static JSBool TargetTypeGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool TargetTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool ContentsGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool ContentsGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool ContentsSetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool ContentsSetter(JSContext* cx, JSObject* obj, jsid idval,
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,
jsval* argv, jsval* rval);
static JSBool ElementTypeGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool ElementTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool LengthGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool LengthGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool Getter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool Setter(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, jsid idval, 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,
jsval* argv, jsval* rval);
static JSBool FieldsArrayGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool FieldsArrayGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool FieldGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool FieldGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool FieldSetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool FieldSetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool AddressOfField(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,
jsval* rval);
static JSBool ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool ArgTypesGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool ReturnTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool ABIGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool IsVariadicGetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool ABIGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
static JSBool IsVariadicGetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
}
@ -174,9 +174,9 @@ namespace CClosure {
namespace CData {
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);
static JSBool ValueSetter(JSContext* cx, JSObject* obj, jsval idval,
static JSBool ValueSetter(JSContext* cx, JSObject* obj, jsid idval,
jsval* vp);
static JSBool Address(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)
{
JSString* str = JS_ValueToSource(cx, actual);
js::AutoValueRooter root(cx, str);
js::AutoStringRooter root(cx, str);
const char* src;
if (str) {
@ -682,7 +682,7 @@ InitTypeConstructor(JSContext* cx,
dataProto = JS_NewObject(cx, &sCDataProtoClass, CDataProto, parent);
if (!dataProto)
return false;
js::AutoValueRooter protoroot(cx, dataProto);
js::AutoObjectRooter protoroot(cx, dataProto);
// Define functions and properties on the 'dataProto' object that are common
// to all CData objects created from this type constructor. (These will
@ -816,27 +816,27 @@ InitTypeClasses(JSContext* cx, JSObject* parent)
sPointerInstanceFunctions, sPointerInstanceProps,
protos[SLOT_POINTERPROTO], protos[SLOT_POINTERDATAPROTO]))
return false;
js::AutoValueRooter proot(cx, protos[SLOT_POINTERDATAPROTO]);
js::AutoObjectRooter proot(cx, protos[SLOT_POINTERDATAPROTO]);
if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
sArrayFunction, NULL, sArrayProps,
sArrayInstanceFunctions, sArrayInstanceProps,
protos[SLOT_ARRAYPROTO], protos[SLOT_ARRAYDATAPROTO]))
return false;
js::AutoValueRooter aroot(cx, protos[SLOT_ARRAYDATAPROTO]);
js::AutoObjectRooter aroot(cx, protos[SLOT_ARRAYDATAPROTO]);
if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
sStructFunction, sStructFunctions, sStructProps,
sStructInstanceFunctions, NULL,
protos[SLOT_STRUCTPROTO], protos[SLOT_STRUCTDATAPROTO]))
return false;
js::AutoValueRooter sroot(cx, protos[SLOT_STRUCTDATAPROTO]);
js::AutoObjectRooter sroot(cx, protos[SLOT_STRUCTDATAPROTO]);
if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
sFunctionFunction, NULL, sFunctionProps, NULL, NULL,
protos[SLOT_FUNCTIONPROTO], protos[SLOT_FUNCTIONDATAPROTO]))
return false;
js::AutoValueRooter froot(cx, protos[SLOT_FUNCTIONDATAPROTO]);
js::AutoObjectRooter froot(cx, protos[SLOT_FUNCTIONDATAPROTO]);
protos[SLOT_CDATAPROTO] = CDataProto;
@ -1105,7 +1105,7 @@ jsvalToBool(JSContext* cx, jsval val, bool* result)
return i == 0 || i == 1;
}
if (JSVAL_IS_DOUBLE(val)) {
jsdouble d = *JSVAL_TO_DOUBLE(val);
jsdouble d = JSVAL_TO_DOUBLE(val);
*result = d != 0;
// Allow -0.
return d == 1 || d == 0;
@ -1132,7 +1132,7 @@ jsvalToInteger(JSContext* cx, jsval val, IntegerType* result)
if (JSVAL_IS_DOUBLE(val)) {
// Don't silently lose bits here -- check that val really is an
// integer value, and has the right sign.
jsdouble d = *JSVAL_TO_DOUBLE(val);
jsdouble d = JSVAL_TO_DOUBLE(val);
return ConvertExact(d, result);
}
if (!JSVAL_IS_PRIMITIVE(val)) {
@ -1213,7 +1213,7 @@ jsvalToFloat(JSContext *cx, jsval val, FloatType* result)
return true;
}
if (JSVAL_IS_DOUBLE(val)) {
*result = FloatType(*JSVAL_TO_DOUBLE(val));
*result = FloatType(JSVAL_TO_DOUBLE(val));
return true;
}
if (!JSVAL_IS_PRIMITIVE(val)) {
@ -1275,7 +1275,7 @@ jsvalToBigInteger(JSContext* cx,
if (JSVAL_IS_DOUBLE(val)) {
// Don't silently lose bits here -- check that val really is an
// integer value, and has the right sign.
jsdouble d = *JSVAL_TO_DOUBLE(val);
jsdouble d = JSVAL_TO_DOUBLE(val);
return ConvertExact(d, result);
}
if (allowString && JSVAL_IS_STRING(val)) {
@ -1338,7 +1338,7 @@ jsvalToIntegerExplicit(JSContext* cx, jsval val, IntegerType* result)
if (JSVAL_IS_DOUBLE(val)) {
// 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;
return true;
}
@ -1371,7 +1371,7 @@ jsvalToPtrExplicit(JSContext* cx, jsval val, uintptr_t* result)
return true;
}
if (JSVAL_IS_DOUBLE(val)) {
jsdouble d = *JSVAL_TO_DOUBLE(val);
jsdouble d = JSVAL_TO_DOUBLE(val);
if (d < 0) {
// Cast through an intptr_t intermediate to sign-extend.
intptr_t i = Convert<intptr_t>(d);
@ -1858,11 +1858,11 @@ ImplicitConvert(JSContext* cx,
for (jsuint i = 0; i < sourceLength; ++i) {
js::AutoValueRooter item(cx);
if (!JS_GetElement(cx, sourceArray, i, item.addr()))
if (!JS_GetElement(cx, sourceArray, i, Jsvalify(item.addr())))
return false;
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;
}
@ -1883,7 +1883,7 @@ ImplicitConvert(JSContext* cx,
JSObject* iter = JS_NewPropertyIterator(cx, obj);
if (!iter)
return false;
js::AutoValueRooter iterroot(cx, iter);
js::AutoObjectRooter iterroot(cx, iter);
// Convert into an intermediate, in case of failure.
size_t structSize = CType::GetSize(cx, targetType);
@ -1902,26 +1902,25 @@ ImplicitConvert(JSContext* cx,
break;
js::AutoValueRooter fieldVal(cx);
if (!JS_IdToValue(cx, id, fieldVal.addr()))
return false;
if (!JSVAL_IS_STRING(fieldVal.value())) {
JS_IdToValue(cx, id, Jsvalify(fieldVal.addr()));
if (!fieldVal.value().isString()) {
JS_ReportError(cx, "property name is not a string");
return false;
}
const FieldInfo* field = StructType::LookupField(cx, targetType,
fieldVal.value());
Jsvalify(fieldVal.value()));
if (!field)
return false;
JSString* name = JSVAL_TO_STRING(fieldVal.value());
JSString* name = fieldVal.value().asString();
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;
// Convert the field via ImplicitConvert().
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;
++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).
// We store any pending exception in case we need to re-throw it.
js::AutoValueRooter ex(cx);
if (!JS_GetPendingException(cx, ex.addr()))
if (!JS_GetPendingException(cx, Jsvalify(ex.addr())))
return false;
// 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_struct:
// ImplicitConvert is sufficient. Re-throw the exception it generated.
JS_SetPendingException(cx, ex.value());
JS_SetPendingException(cx, Jsvalify(ex.value()));
return false;
case TYPE_void_t:
case TYPE_function:
@ -2528,7 +2527,7 @@ CType::Create(JSContext* cx,
JSObject* typeObj = JS_NewObject(cx, &sCTypeClass, typeProto, parent);
if (!typeObj)
return NULL;
js::AutoValueRooter root(cx, typeObj);
js::AutoObjectRooter root(cx, typeObj);
// Set up the reserved slots.
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);
if (!prototype)
return NULL;
js::AutoValueRooter protoroot(cx, prototype);
js::AutoObjectRooter protoroot(cx, prototype);
if (!JS_DefineProperty(cx, prototype, "constructor", OBJECT_TO_JSVAL(typeObj),
NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT))
@ -2581,7 +2580,7 @@ CType::DefineBuiltin(JSContext* cx,
JSString* nameStr = JS_NewStringCopyZ(cx, name);
if (!nameStr)
return NULL;
js::AutoValueRooter nameRoot(cx, nameStr);
js::AutoStringRooter nameRoot(cx, nameStr);
// Create a new CType object with the common properties and slots.
JSObject* typeObj = Create(cx, typeProto, dataProto, type, nameStr, size,
@ -2807,7 +2806,7 @@ CType::GetSafeSize(JSContext* cx, JSObject* obj, size_t* result)
return true;
}
if (JSVAL_IS_DOUBLE(size)) {
*result = Convert<size_t>(*JSVAL_TO_DOUBLE(size));
*result = Convert<size_t>(JSVAL_TO_DOUBLE(size));
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.
if (JSVAL_IS_INT(size))
return JSVAL_TO_INT(size);
return Convert<size_t>(*JSVAL_TO_DOUBLE(size));
return Convert<size_t>(JSVAL_TO_DOUBLE(size));
}
bool
@ -2943,7 +2942,7 @@ CType::GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
}
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)) {
JS_ReportError(cx, "not a CType");
@ -2956,7 +2955,7 @@ CType::PrototypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
}
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)) {
JS_ReportError(cx, "not a CType");
@ -2972,7 +2971,7 @@ CType::NameGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
}
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)) {
JS_ReportError(cx, "not a CType");
@ -2985,7 +2984,7 @@ CType::SizeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
}
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)) {
JS_ReportError(cx, "not a CType");
@ -3078,7 +3077,7 @@ CType::ToSource(JSContext* cx, uintN argc, jsval *vp)
}
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));
@ -3089,10 +3088,10 @@ CType::HasInstance(JSContext* cx, JSObject* obj, jsval v, JSBool* bp)
JS_ASSERT(JS_GET_CLASS(cx, prototype) == &sCDataProtoClass);
*bp = JS_FALSE;
if (JSVAL_IS_PRIMITIVE(v))
if (JSVAL_IS_PRIMITIVE(*vp))
return JS_TRUE;
JSObject* proto = JSVAL_TO_OBJECT(v);
JSObject* proto = JSVAL_TO_OBJECT(*vp);
while ((proto = JS_GetPrototype(cx, proto))) {
if (proto == prototype) {
*bp = JS_TRUE;
@ -3152,7 +3151,7 @@ PointerType::CreateInternal(JSContext* cx, JSObject* baseType)
&ffi_type_pointer);
if (!typeObj)
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.)
if (!JS_SetReservedSlot(cx, typeObj, SLOT_TARGET_T, OBJECT_TO_JSVAL(baseType)))
@ -3237,7 +3236,7 @@ PointerType::GetBaseType(JSContext* cx, JSObject* obj)
JSBool
PointerType::TargetTypeGetter(JSContext* cx,
JSObject* obj,
jsval idval,
jsid idval,
jsval* vp)
{
if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_pointer) {
@ -3277,7 +3276,7 @@ PointerType::IsNull(JSContext* cx, uintN argc, jsval* vp)
JSBool
PointerType::ContentsGetter(JSContext* cx,
JSObject* obj,
jsval idval,
jsid idval,
jsval* vp)
{
if (!CData::IsCData(cx, obj)) {
@ -3315,7 +3314,7 @@ PointerType::ContentsGetter(JSContext* cx,
JSBool
PointerType::ContentsSetter(JSContext* cx,
JSObject* obj,
jsval idval,
jsid idval,
jsval* vp)
{
if (!CData::IsCData(cx, obj)) {
@ -3422,7 +3421,7 @@ ArrayType::CreateInternal(JSContext* cx,
sizeVal, INT_TO_JSVAL(align), NULL);
if (!typeObj)
return NULL;
js::AutoValueRooter root(cx, typeObj);
js::AutoObjectRooter root(cx, typeObj);
// Set the element type.
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.
JSObject* arg = JSVAL_TO_OBJECT(argv[0]);
js::AutoValueRooter lengthVal(cx);
if (!JS_GetProperty(cx, arg, "length", lengthVal.addr()) ||
!jsvalToSize(cx, lengthVal.value(), false, &length)) {
if (!JS_GetProperty(cx, arg, "length", Jsvalify(lengthVal.addr())) ||
!jsvalToSize(cx, Jsvalify(lengthVal.value()), false, &length)) {
JS_ReportError(cx, "argument must be an array object or length");
return JS_FALSE;
}
@ -3521,7 +3520,7 @@ ArrayType::ConstructData(JSContext* cx,
}
// 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);
if (!result)
@ -3565,7 +3564,7 @@ ArrayType::GetSafeLength(JSContext* cx, JSObject* obj, size_t* result)
return true;
}
if (JSVAL_IS_DOUBLE(length)) {
*result = Convert<size_t>(*JSVAL_TO_DOUBLE(length));
*result = Convert<size_t>(JSVAL_TO_DOUBLE(length));
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.
if (JSVAL_IS_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*
@ -3636,7 +3635,7 @@ ArrayType::BuildFFIType(JSContext* cx, JSObject* obj)
}
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) {
JS_ReportError(cx, "not an ArrayType");
@ -3649,7 +3648,7 @@ ArrayType::ElementTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* v
}
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.
// 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
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.
if (!CData::IsCData(cx, obj)) {
@ -3702,7 +3701,7 @@ ArrayType::Getter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
}
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.
if (!CData::IsCData(cx, obj)) {
@ -3762,7 +3761,7 @@ ArrayType::AddressOfElement(JSContext* cx, uintN argc, jsval *vp)
JSObject* pointerType = PointerType::CreateInternal(cx, baseType);
if (!pointerType)
return JS_FALSE;
js::AutoValueRooter root(cx, pointerType);
js::AutoObjectRooter root(cx, pointerType);
// Create a PointerType CData object containing null.
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);
if (!iter)
return NULL;
js::AutoValueRooter iterroot(cx, iter);
js::AutoObjectRooter iterroot(cx, iter);
jsid id;
if (!JS_NextProperty(cx, iter, &id))
return NULL;
js::AutoValueRooter nameVal(cx);
if (!JS_IdToValue(cx, id, nameVal.addr()))
return NULL;
if (!JSVAL_IS_STRING(nameVal.value())) {
JS_IdToValue(cx, id, Jsvalify(nameVal.addr()));
if (!nameVal.value().isString()) {
JS_ReportError(cx, "struct field descriptors require a valid name and type");
return NULL;
}
JSString* name = JSVAL_TO_STRING(nameVal.value());
JSString* name = nameVal.value().asString();
// make sure we have one, and only one, property
if (!JS_NextProperty(cx, iter, &id))
@ -3829,11 +3827,11 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
}
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;
if (JSVAL_IS_PRIMITIVE(propVal.value()) ||
!CType::IsCType(cx, JSVAL_TO_OBJECT(propVal.value()))) {
if (propVal.value().isPrimitive() ||
!CType::IsCType(cx, &propVal.value().asObject())) {
JS_ReportError(cx, "struct field descriptors require a valid name and type");
return NULL;
}
@ -3841,7 +3839,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
// Undefined size or zero size struct members are illegal.
// (Zero-size arrays are legal as struct members in C++, but libffi will
// choke on a zero-size struct, so we disallow them.)
*typeObj = JSVAL_TO_OBJECT(propVal.value());
*typeObj = &propVal.value().asObject();
size_t size;
if (!CType::GetSafeSize(cx, *typeObj, &size) || size == 0) {
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);
if (!result)
return JS_FALSE;
js::AutoValueRooter root(cx, result);
js::AutoObjectRooter root(cx, result);
if (argc == 2) {
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);
if (!prototype)
return JS_FALSE;
js::AutoValueRooter protoroot(cx, prototype);
js::AutoObjectRooter protoroot(cx, prototype);
if (!JS_DefineProperty(cx, prototype, "constructor", OBJECT_TO_JSVAL(typeObj),
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) {
js::AutoValueRooter item(cx);
if (!JS_GetElement(cx, fieldsObj, i, item.addr()))
if (!JS_GetElement(cx, fieldsObj, i, Jsvalify(item.addr())))
return JS_FALSE;
JSObject* fieldType;
JSString* name = ExtractStructField(cx, item.value(), &fieldType);
JSString* name = ExtractStructField(cx, Jsvalify(item.value()), &fieldType);
if (!name)
return JS_FALSE;
@ -4268,10 +4266,10 @@ StructType::BuildFieldsArray(JSContext* cx, JSObject* obj)
// Prepare a new array for the 'fields' property of the StructType.
jsval* fieldsVec;
JSObject* fieldsProp =
js_NewArrayObjectWithCapacity(cx, len, &fieldsVec);
js_NewArrayObjectWithCapacity(cx, len, Valueify(&fieldsVec));
if (!fieldsProp)
return NULL;
js::AutoValueRooter root(cx, fieldsProp);
js::AutoObjectRooter root(cx, fieldsProp);
JS_ASSERT(len == 0 || fieldsVec);
for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
@ -4290,7 +4288,7 @@ StructType::BuildFieldsArray(JSContext* cx, JSObject* obj)
}
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) {
JS_ReportError(cx, "not a StructType");
@ -4320,7 +4318,7 @@ StructType::FieldsArrayGetter(JSContext* cx, JSObject* obj, jsval idval, jsval*
}
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)) {
JS_ReportError(cx, "not a CData");
@ -4342,7 +4340,7 @@ StructType::FieldGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
}
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)) {
JS_ReportError(cx, "not a CData");
@ -4393,7 +4391,7 @@ StructType::AddressOfField(JSContext* cx, uintN argc, jsval *vp)
JSObject* pointerType = PointerType::CreateInternal(cx, baseType);
if (!pointerType)
return JS_FALSE;
js::AutoValueRooter root(cx, pointerType);
js::AutoObjectRooter root(cx, pointerType);
// Create a PointerType CData object containing null.
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.
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) {
if (!JS_GetElement(cx, arrayObj, i, &argTypes[i]))
return JS_FALSE;
@ -4728,7 +4726,7 @@ FunctionType::CreateInternal(JSContext* cx,
NULL, JSVAL_VOID, JSVAL_VOID, NULL);
if (!typeObj)
return NULL;
js::AutoValueRooter root(cx, typeObj);
js::AutoObjectRooter root(cx, typeObj);
// Stash the FunctionInfo in a reserved slot.
if (!JS_SetReservedSlot(cx, typeObj, SLOT_FNINFO,
@ -4759,7 +4757,7 @@ FunctionType::ConstructData(JSContext* cx,
JSObject* closureObj = CClosure::Create(cx, typeObj, fnObj, thisObj, data);
if (!closureObj)
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.
if (!JS_SetReservedSlot(cx, dataObj, SLOT_REFERENT,
@ -4944,7 +4942,7 @@ CheckFunctionType(JSContext* cx, JSObject* obj)
}
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))
return JS_FALSE;
@ -4960,10 +4958,10 @@ FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* v
// Prepare a new array.
jsval* vec;
JSObject* argTypes =
js_NewArrayObjectWithCapacity(cx, len, &vec);
js_NewArrayObjectWithCapacity(cx, len, Valueify(&vec));
if (!argTypes)
return JS_FALSE;
js::AutoValueRooter argsroot(cx, argTypes);
js::AutoObjectRooter argsroot(cx, argTypes);
JS_ASSERT(len == 0 || vec);
for (size_t i = 0; i < len; ++i)
@ -4979,7 +4977,7 @@ FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* v
}
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))
return JS_FALSE;
@ -4990,7 +4988,7 @@ FunctionType::ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval*
}
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))
return JS_FALSE;
@ -5001,7 +4999,7 @@ FunctionType::ABIGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
}
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))
return JS_FALSE;
@ -5024,7 +5022,7 @@ CClosure::Create(JSContext* cx,
JSObject* result = JS_NewObject(cx, &sCClosureClass, NULL, NULL);
if (!result)
return NULL;
js::AutoValueRooter root(cx, result);
js::AutoObjectRooter root(cx, result);
// Get the FunctionInfo from the FunctionType.
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);
// 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.
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)
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) {
// Convert each argument, and have any CData objects created depend on
// the existing buffers.
@ -5262,7 +5260,7 @@ CData::Create(JSContext* cx,
JSObject* dataObj = JS_NewObject(cx, &sCDataClass, proto, parent);
if (!dataObj)
return NULL;
js::AutoValueRooter root(cx, dataObj);
js::AutoObjectRooter root(cx, dataObj);
// set the CData's associated type
if (!JS_SetReservedSlot(cx, dataObj, SLOT_CTYPE, OBJECT_TO_JSVAL(typeObj)))
@ -5368,7 +5366,7 @@ CData::IsCData(JSContext* cx, JSObject* obj)
}
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)) {
JS_ReportError(cx, "not a CData");
@ -5383,7 +5381,7 @@ CData::ValueGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
}
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)) {
JS_ReportError(cx, "not a CData");
@ -5413,7 +5411,7 @@ CData::Address(JSContext* cx, uintN argc, jsval *vp)
JSObject* pointerType = PointerType::CreateInternal(cx, typeObj);
if (!pointerType)
return JS_FALSE;
js::AutoValueRooter root(cx, pointerType);
js::AutoObjectRooter root(cx, pointerType);
// Create a PointerType CData object containing null.
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));
if (!result)
return NULL;
js::AutoValueRooter root(cx, result);
js::AutoObjectRooter root(cx, result);
// attach the Int64's 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);
if (!libraryObj)
return NULL;
js::AutoValueRooter root(cx, libraryObj);
js::AutoObjectRooter root(cx, libraryObj);
// initialize the library
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;
JSObject* typeObj;
js::AutoValueRooter root(cx);
js::AutoObjectRooter root(cx);
bool isFunction = argc > 2;
if (isFunction) {
// Case 1).

View File

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

View File

@ -52,12 +52,12 @@
JS_BEGIN_EXTERN_C
/* Well-known JS values, initialized on startup. */
#define JSVAL_NULL JSVAL_CONSTANT(JSVAL_MASK32_NULL, 0)
#define JSVAL_ZERO JSVAL_CONSTANT(JSVAL_MASK32_INT32, 0)
#define JSVAL_ONE JSVAL_CONSTANT(JSVAL_MASK32_INT32, 1)
#define JSVAL_FALSE JSVAL_CONSTANT(JSVAL_MASK32_BOOLEAN, JS_FALSE)
#define JSVAL_TRUE JSVAL_CONSTANT(JSVAL_MASK32_BOOLEAN, JS_TRUE)
#define JSVAL_VOID JSVAL_CONSTANT(JSVAL_MASK32_UNDEFINED, 0)
#define JSVAL_NULL BUILD_JSVAL(JSVAL_MASK32_NULL, 0)
#define JSVAL_ZERO BUILD_JSVAL(JSVAL_MASK32_INT32, 0)
#define JSVAL_ONE BUILD_JSVAL(JSVAL_MASK32_INT32, 1)
#define JSVAL_FALSE BUILD_JSVAL(JSVAL_MASK32_BOOLEAN, JS_FALSE)
#define JSVAL_TRUE BUILD_JSVAL(JSVAL_MASK32_BOOLEAN, JS_TRUE)
#define JSVAL_VOID BUILD_JSVAL(JSVAL_MASK32_UNDEFINED, 0)
/* Predicates for type testing. */
@ -65,14 +65,14 @@ static JS_ALWAYS_INLINE JSBool
JSVAL_IS_NULL(jsval v)
{
jsval_layout l = { v };
return l.s.mask32 == JSVAL_MASK32_NULL;
return JSVAL_IS_NULL_IMPL(l);
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_VOID(jsval v)
{
jsval_layout l = { v };
return l.s.mask32 == JSVAL_MASK32_UNDEFINED;
return JSVAL_IS_UNDEFINED_IMPL(l);
}
static JS_ALWAYS_INLINE JSBool
@ -103,17 +103,14 @@ INT_FITS_IN_JSVAL(jsint i)
static JS_ALWAYS_INLINE jsval
INT_TO_JSVAL(int32 i)
{
jsval_layout l;
l.s.mask32 = JSVAL_MASK32_INT32;
l.s.payload.i32 = i;
return l.asBits;
return INT32_TO_JSVAL_IMPL(i).asBits;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_DOUBLE(jsval v)
{
jsval_layout l = { v };
return l.s.mask32 < JSVAL_MASK32_CLEAR;
return JSVAL_IS_DOUBLE_IMPL(l);
}
static JS_ALWAYS_INLINE jsdouble
@ -127,16 +124,14 @@ JSVAL_TO_DOUBLE(jsval v)
static JS_ALWAYS_INLINE jsval
DOUBLE_TO_JSVAL(jsdouble d)
{
jsval_layout l;
l.asDouble = d;
JS_ASSERT(l.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
return l.asBits;
return DOUBLE_TO_JSVAL_IMPL(d).asBits;
}
static JS_ALWAYS_INLINE JSBool
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
@ -151,30 +146,20 @@ JSVAL_TO_STRING(jsval v)
{
JS_ASSERT(JSVAL_IS_STRING(v));
jsval_layout l = { v };
return l.s.payload.str;
return JSVAL_TO_STRING_IMPL(l);
}
static JS_ALWAYS_INLINE jsval
STRING_TO_JSVAL(JSString *str)
{
jsval_layout l;
l.s.mask32 = JSVAL_MASK32_STRING;
l.s.payload.str = str;
return l.asBits;
return STRING_TO_JSVAL_IMPL(str).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
JSVAL_IS_OBJECT(jsval 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 *
@ -182,9 +167,10 @@ JSVAL_TO_OBJECT(jsval v)
{
JS_ASSERT(JSVAL_IS_OBJECT(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
OBJECT_TO_JSVAL(JSObject *obj)
{
@ -193,12 +179,10 @@ OBJECT_TO_JSVAL(JSObject *obj)
if (!obj)
return JSVAL_NULL;
uint32 mask = JS_ObjectIsFunction(NULL, obj) ? JSVAL_MASK32_FUNOBJ
: JSVAL_MASK32_NONFUNOBJ;
jsval_layout l;
l.s.mask32 = mask;
l.s.payload.obj = obj;
return l.asBits;
JSValueMask32 mask = JS_ObjectIsFunction(NULL, obj) ? JSVAL_MASK32_FUNOBJ
: JSVAL_MASK32_NONFUNOBJ;
return OBJECT_TO_JSVAL_IMPL(mask, obj).asBits;
}
static JS_ALWAYS_INLINE JSBool
@ -219,24 +203,21 @@ JSVAL_TO_BOOLEAN(jsval v)
static JS_ALWAYS_INLINE jsval
BOOLEAN_TO_JSVAL(JSBool b)
{
jsval_layout l;
l.s.mask32 = JSVAL_MASK32_BOOLEAN;
l.s.payload.boo = b;
return l.asBits;
return BOOLEAN_TO_JSVAL_IMPL(b).asBits;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_PRIMITIVE(jsval 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
JSVAL_IS_GCTHING(jsval 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 *
@ -244,24 +225,23 @@ JSVAL_TO_GCTHING(jsval v)
{
JS_ASSERT(JSVAL_IS_GCTHING(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
PRIVATE_TO_JSVAL(void *ptr)
{
jsval_layout l;
l.s.mask32 = JSVAL_MASK32_INT32;
l.s.payload.ptr = ptr;
return l.asBits;
return PRIVATE_TO_JSVAL_IMPL(ptr).asBits;
}
static JS_ALWAYS_INLINE void *
JSVAL_TO_PRIVATE(jsval v)
{
JS_ASSERT(JSVAL_IS_INT(v));
JS_ASSERT(JSVAL_IS_DOUBLE(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. */
@ -1189,7 +1169,7 @@ JSVAL_TRACE_KIND(jsval v)
{
JS_ASSERT(JSVAL_IS_GCTHING(v));
jsval_layout l = { v };
return (uint32)(l.s.mask32 == JSVAL_MASK32_STRING);
return JSVAL_TRACE_KIND_IMPL(l);
}
struct JSTracer {
@ -3007,44 +2987,26 @@ class Value
* break this encapsulation should be listed as friends below. Also see
* 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;
protected:
/* Type masks */
template <int I> class T {};
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(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(((jsval_layout *)0)->s.payload) == 4);
JS_STATIC_ASSERT(sizeof(jsval) == 8);
}
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:
/* Constructors */
@ -3075,18 +3037,15 @@ class Value
/* Change to a Value of a single type */
void setNull() {
data.s.mask32 = JSVAL_MASK32_NULL;
data.s.payload.obj = NULL;
data.asBits = JSVAL_NULL;
}
void setUndefined() {
data.s.mask32 = JSVAL_MASK32_UNDEFINED;
data.s.payload.obj = NULL;
data.asBits = JSVAL_VOID;
}
void setInt32(int32 i) {
data.s.mask32 = JSVAL_MASK32_INT32;
data.s.payload.i32 = i;
data = INT32_TO_JSVAL_IMPL(i);
}
int32 &asInt32Ref() {
@ -3096,8 +3055,7 @@ class Value
void setDouble(double d) {
ASSERT_DOUBLE_ALIGN();
data.asDouble = d;
JS_ASSERT(data.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
data = DOUBLE_TO_JSVAL_IMPL(d);
}
double &asDoubleRef() {
@ -3107,62 +3065,54 @@ class Value
}
void setString(JSString *str) {
data.s.mask32 = JSVAL_MASK32_STRING;
data.s.payload.str = str;
data = STRING_TO_JSVAL_IMPL(str);
}
void setFunObj(JSObject &arg) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &arg));
data.s.mask32 = JSVAL_MASK32_FUNOBJ;
data.s.payload.obj = &arg;
data = OBJECT_TO_JSVAL_IMPL(JSVAL_MASK32_FUNOBJ, &arg);
}
void setNonFunObj(JSObject &arg) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, &arg));
data.s.mask32 = JSVAL_MASK32_NONFUNOBJ;
data.s.payload.obj = &arg;
data = OBJECT_TO_JSVAL_IMPL(JSVAL_MASK32_NONFUNOBJ, &arg);
}
void setBoolean(bool b) {
data.s.mask32 = JSVAL_MASK32_BOOLEAN;
data.s.payload.boo = b;
data = BOOLEAN_TO_JSVAL_IMPL(b);
}
void setMagic(JSWhyMagic why) {
data.s.mask32 = JSVAL_MASK32_MAGIC;
data.s.payload.why = why;
data = MAGIC_TO_JSVAL_IMPL(why);
}
/* Change to a Value of a type dynamically chosen from a set of types */
void setNumber(uint32 ui) {
if (ui > JSVAL_INT_MAX) {
data.asDouble = ui;
JS_ASSERT(data.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
} else {
data.s.mask32 = JSVAL_MASK32_INT32;
data.s.payload.i32 = (int32)ui;
}
if (ui > JSVAL_INT_MAX)
data = DOUBLE_TO_JSVAL_IMPL(ui);
else
data = INT32_TO_JSVAL_IMPL((int32)ui);
}
inline void setNumber(double d);
void setFunObjOrNull(JSObject *arg) {
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
data.s.mask32 = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_NULL;
data.s.payload.obj = arg;
JSValueMask32 mask = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_NULL;
data = OBJECT_TO_JSVAL_IMPL(mask, arg);
}
void setFunObjOrUndefined(JSObject *arg) {
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
data.s.mask32 = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_UNDEFINED;
data.s.payload.obj = arg;
JSValueMask32 mask = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_UNDEFINED;
data = OBJECT_TO_JSVAL_IMPL(mask, arg);
}
void setNonFunObjOrNull(JSObject *arg) {
JS_ASSERT_IF(arg, !JS_ObjectIsFunction(NULL, arg));
data.s.mask32 = arg ? JSVAL_MASK32_NONFUNOBJ : JSVAL_MASK32_NULL;
data.s.payload.obj = arg;
JSValueMask32 mask = arg ? JSVAL_MASK32_NONFUNOBJ : JSVAL_MASK32_NULL;
data = OBJECT_TO_JSVAL_IMPL(mask, arg);
}
inline void setObject(JSObject &arg);
@ -3171,15 +3121,15 @@ class Value
/* Query a Value's type */
bool isUndefined() const {
return data.s.mask32 == JSVAL_MASK32_UNDEFINED;
return JSVAL_IS_UNDEFINED_IMPL(data);
}
bool isNull() const {
return data.s.mask32 == JSVAL_MASK32_NULL;
return JSVAL_IS_NULL_IMPL(data);
}
bool isNullOrUndefined() const {
return isNullOrUndefinedMask(data.s.mask32);
return JSVAL_IS_SINGLETON_IMPL(data);
}
bool isInt32() const {
@ -3187,16 +3137,15 @@ class Value
}
bool isInt32(int32 i32) const {
return (data.s.mask32 == JSVAL_MASK32_INT32) &
(data.s.payload.i32 == i32);
return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
}
bool isDouble() const {
return isDoubleMask(data.s.mask32);
return JSVAL_IS_DOUBLE_IMPL(data);
}
bool isNumber() const {
return isNumberMask(data.s.mask32);
return JSVAL_IS_NUMBER_IMPL(data);
}
bool isString() const {
@ -3212,19 +3161,19 @@ class Value
}
bool isObject() const {
return isObjectMask(data.s.mask32);
return JSVAL_IS_OBJECT_IMPL(data);
}
bool isPrimitive() const {
return !isObject();
return JSVAL_IS_PRIMITIVE_IMPL(data);
}
bool isObjectOrNull() const {
return isObjectOrNullMask(data.s.mask32);
return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
}
bool isGCThing() const {
return (data.s.mask32 & JSVAL_MASK32_GCTHING) > JSVAL_MASK32_CLEAR;
return JSVAL_IS_GCTHING_IMPL(data);
}
bool isBoolean() const {
@ -3232,13 +3181,11 @@ class Value
}
bool isTrue() const {
return data.s.mask32 == JSVAL_MASK32_BOOLEAN &&
data.s.payload.boo == JS_TRUE;
return JSVAL_IS_SPECIFIC_BOOLEAN(data, true);
}
bool isFalse() const {
return data.s.mask32 == JSVAL_MASK32_BOOLEAN &&
data.s.payload.boo == JS_FALSE;
return JSVAL_IS_SPECIFIC_BOOLEAN(data, false);
}
bool isMagic() const {
@ -3252,13 +3199,17 @@ class Value
int32 traceKind() const {
JS_ASSERT(isGCThing());
return (int32)(data.s.mask32 == JSVAL_MASK32_STRING);
return JSVAL_TRACE_KIND_IMPL(data);
}
#ifdef DEBUG
JSWhyMagic whyMagic() const {
JS_ASSERT(isMagic());
return data.s.payload.why;
}
#endif
/* Comparison */
bool operator==(const Value &rhs) const {
return data.asBits == rhs.data.asBits;
@ -3268,6 +3219,18 @@ class Value
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 */
int32 asInt32() const {
@ -3288,32 +3251,32 @@ class Value
JSString *asString() const {
JS_ASSERT(isString());
return data.s.payload.str;
return JSVAL_TO_STRING_IMPL(data);
}
JSObject &asNonFunObj() const {
JS_ASSERT(isNonFunObj());
return *data.s.payload.obj;
return *JSVAL_TO_OBJECT_IMPL(data);
}
JSObject &asFunObj() const {
JS_ASSERT(isFunObj());
return *data.s.payload.obj;
return *JSVAL_TO_OBJECT_IMPL(data);
}
JSObject &asObject() const {
JS_ASSERT(isObject());
return *data.s.payload.obj;
return *JSVAL_TO_OBJECT_IMPL(data);
}
JSObject *asObjectOrNull() const {
JS_ASSERT(isObjectOrNull());
return data.s.payload.obj;
return JSVAL_TO_OBJECT_IMPL(data);
}
void *asGCThing() const {
JS_ASSERT(isGCThing());
return data.s.payload.ptr;
return JSVAL_TO_GCTHING_IMPL(data);
}
bool asBoolean() const {
@ -3321,6 +3284,11 @@ class Value
return data.s.payload.boo;
}
uint32 asRawUint32() const {
JS_ASSERT(!isDouble());
return data.s.payload.u32;
}
/* Swap two Values */
void swap(Value &rhs) {
@ -3343,28 +3311,25 @@ class Value
}
void setPrivateVoidPtr(void *ptr) {
data.s.mask32 = JSVAL_MASK32_INT32;
data.s.payload.ptr = ptr;
data = PRIVATE_TO_JSVAL_IMPL(ptr);
}
void *asPrivateVoidPtr() const {
JS_ASSERT(data.s.mask32 == JSVAL_MASK32_INT32);
return data.s.payload.ptr;
JS_ASSERT(isDouble());
return JSVAL_TO_PRIVATE_IMPL(data);
}
void setPrivateUint32(uint32 u) {
data.s.mask32 = JSVAL_MASK32_INT32;
data.s.payload.u32 = u;
setInt32((int32)u);
}
uint32 asPrivateUint32() const {
JS_ASSERT(data.s.mask32 == JSVAL_MASK32_INT32);
return data.s.payload.u32;
return (uint32)asInt32();
}
uint32 &asPrivateUint32Ref() {
JS_ASSERT(data.s.mask32 == JSVAL_MASK32_INT32);
return data.s.payload.u32;
JS_ASSERT(isInt32());
return data.s.payload.u32;
}
} VALUE_ALIGNMENT;
@ -3372,14 +3337,15 @@ class Value
* As asserted above, js::Value and jsval are layout equivalent. To provide
* widespread casting, the following safe casts are provided.
*/
static inline jsval * Jsvalify(Value *v) { return (jsval *)v; }
static inline const jsval * Jsvalify(const Value *v) { return (const jsval *)v; }
static inline jsval & Jsvalify(Value &v) { return (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 const Value * Valueify(const jsval *v) { return (const 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 jsval * Jsvalify(Value *v) { return (jsval *)v; }
static inline const jsval * Jsvalify(const Value *v) { return (const jsval *)v; }
static inline jsval & Jsvalify(Value &v) { return (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 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 const Value & Valueify(const jsval &v) { return (const Value &)v; }
/* Convenience inlines. */
static inline Value undefinedValue() { return UndefinedTag(); }

View File

@ -2040,8 +2040,10 @@ array_sort(JSContext *cx, uintN argc, Value *vp)
str = js_ValueToString(cx, v);
if (!str)
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].setString(str);
} while (i != 0);
JS_ASSERT(tvr.array == vec);
@ -2730,7 +2732,7 @@ array_indexOfHelper(JSContext *cx, JSBool isLast, uintN argc, Value *vp)
return JS_FALSE;
}
if (!hole && StrictlyEqual(cx, *vp, tosearch)) {
Uint32ToValue(i, vp);
vp->setNumber(i);
return JS_TRUE;
}
if (i == stop)

View File

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

View File

@ -39,6 +39,10 @@
#ifdef XP_WIN
# include <windows.h>
#ifdef _M_X64
# include "jsstr.h"
#endif
# ifdef _MSC_VER
# pragma warning( disable: 4267 4996 4146 )
# endif
@ -140,6 +144,68 @@ UnmapPages(void *p, size_t size)
# 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 *
MapPages(void *addr, size_t size)
{
@ -154,6 +220,8 @@ UnmapPages(void *addr, size_t size)
JS_ALWAYS_TRUE(VirtualFree(addr, 0, MEM_RELEASE));
}
# endif /* _M_X64 */
# endif /* !WINCE */
#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*
* 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,
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)
return NULL;
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*
* 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);
if (p == MAP_FAILED)
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_MASK = GC_CHUNK_SIZE - 1;
#if defined(XP_WIN) && defined(_M_X64)
bool InitNtAllocAPIs();
#endif
void *
AllocGCChunk();

View File

@ -387,8 +387,7 @@ NoSuchMethod(JSContext *cx, uintN argc, Value *vp, uint32 flags)
namespace js {
static const uint32 FAKE_NUMBER_MASK = JSVAL_MASK32_INT32 |
PrimitiveValue::DOUBLE_MASK;
static const uint32 FAKE_NUMBER_MASK = JSVAL_MASK32_INT32 | PrimitiveValue::DOUBLE_MASK;
const uint32 PrimitiveValue::Masks[PrimitiveValue::THISP_ARRAY_SIZE] = {
0, /* 000 */
@ -1001,36 +1000,29 @@ EqualObjects(JSContext *cx, JSObject *lobj, JSObject *robj)
}
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;
uint32 rmask = rval.data.s.mask32;
if (lmask == rmask) {
if (lmask == JSVAL_MASK32_STRING)
return js_EqualStrings(lval.data.s.payload.str, rval.data.s.payload.str);
if (Value::isObjectMask(lmask))
return EqualObjects(cx, lval.data.s.payload.obj, rval.data.s.payload.obj);
if (Value::isDoubleMask(lmask))
return JSDOUBLE_COMPARE(lval.data.asDouble, ==, rval.data.asDouble, JS_FALSE);
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;
Value lval = lref, rval = rref;
if (SamePrimitiveTypeOrBothObjects(lval, rval)) {
if (lval.isString())
return js_EqualStrings(lval.asString(), rval.asString());
if (lval.isDouble())
return JSDOUBLE_COMPARE(lval.asDouble(), ==, rval.asDouble(), JS_FALSE);
if (lval.isObject())
return EqualObjects(cx, &lval.asObject(), &rval.asObject());
return lval.asRawUint32() == rval.asRawUint32();
}
if (Value::isNumberMask(lmask) && Value::isNumberMask(rmask)) {
double ld = lmask == JSVAL_MASK32_INT32 ? lval.data.s.payload.i32
: lval.data.asDouble;
double rd = rmask == JSVAL_MASK32_INT32 ? rval.data.s.payload.i32
: rval.data.asDouble;
if (lval.isDouble() && rval.isInt32()) {
double ld = lval.asDouble();
double rd = rval.asInt32();
return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
}
if (lval.isInt32() && rval.isDouble()) {
double ld = lval.asInt32();
double rd = rval.asDouble();
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;
}
@ -1824,9 +1816,11 @@ namespace reprmeter {
if ((vp)->isObject()) { \
obj = &(vp)->asObject(); \
} else { \
if (!js_ValueToNonNullObject(cx, *(vp), (vp))) \
Value v; \
if (!js_ValueToNonNullObject(cx, *(vp), &v)) \
goto error; \
obj = &(vp)->asObject(); \
*(vp) = v; \
obj = &v.asObject(); \
} \
JS_END_MACRO
@ -1836,6 +1830,15 @@ namespace reprmeter {
VALUE_TO_OBJECT(cx, vp_, obj); \
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] */
static JS_ALWAYS_INLINE bool
CanIncDecWithoutOverflow(int32_t i)

View File

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

View File

@ -493,16 +493,16 @@ FinishSharingTitle(JSContext *cx, JSTitle *title)
uint32 nslots = scope->freeslot;
JS_ASSERT(nslots >= JSSLOT_START(obj->getClass()));
for (uint32 i = JSSLOT_START(obj->getClass()); i != nslots; ++i) {
jsval v = obj->getSlot(i);
if (JSVAL_IS_STRING(v) &&
!js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) {
Value v = obj->getSlot(i);
if (v.isString() &&
!js_MakeStringImmutable(cx, v.asString())) {
/*
* FIXME bug 363059: The following error recovery changes
* runtime execution semantics, arbitrarily and silently
* ignoring errors except out-of-memory, which should have been
* 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) ||
scope->sealed() ||
(title->ownercx && ClaimTitle(title, cx))) {
return obj->getSlot(slot);
return Jsvalify(obj->getSlot(slot));
}
#ifndef NSPR_LOCK
@ -725,7 +725,7 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
* lock release followed by fat lock acquisition.
*/
if (scope == obj->scope()) {
v = obj->getSlot(slot);
v = Jsvalify(obj->getSlot(slot));
if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
/* Assert that scope locks never revert to flyweight. */
JS_ASSERT(title->ownercx != cx);
@ -739,12 +739,12 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
js_Dequeue(tl);
}
else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
return obj->getSlot(slot);
return Jsvalify(obj->getSlot(slot));
}
#endif
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.
@ -798,7 +798,7 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
if (CX_THREAD_IS_RUNNING_GC(cx) ||
scope->sealed() ||
(title->ownercx && ClaimTitle(title, cx))) {
obj->lockedSetSlot(slot, v);
obj->lockedSetSlot(slot, Valueify(v));
return;
}
@ -808,7 +808,7 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
JS_ASSERT(CURRENT_THREAD_IS_ME(me));
if (NativeCompareAndSwap(&tl->owner, 0, me)) {
if (scope == obj->scope()) {
obj->lockedSetSlot(slot, v);
obj->lockedSetSlot(slot, Valueify(v));
if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
/* Assert that scope locks never revert to flyweight. */
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))
js_Dequeue(tl);
} else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
obj->lockedSetSlot(slot, v);
obj->lockedSetSlot(slot, Valueify(v));
return;
}
#endif
js_LockObj(cx, obj);
obj->lockedSetSlot(slot, v);
obj->lockedSetSlot(slot, Valueify(v));
/*
* 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);
}
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
Value::Value(NumberTag arg)
{

View File

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

View File

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

View File

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

View File

@ -158,35 +158,12 @@ typedef struct JSONParser JSONParser;
*/
/*
* TODO: wrong, fix, explain more
* 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().
* TODO: explain boxing strategy
*/
typedef enum JSValueMask16
#if defined(_MSC_VER) && _MSC_VER >= 1400
: unsigned short
#if defined(_MSC_VER)
: uint16
#endif
{
JSVAL_MASK16_NULL = (uint16)0x0001,
@ -203,6 +180,11 @@ typedef enum JSValueMask16
JSVAL_MASK16_OBJORNULL = JSVAL_MASK16_OBJECT | JSVAL_MASK16_NULL,
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)
}
#if defined(__GNUC__)
@ -210,45 +192,36 @@ __attribute__((packed))
#endif
JSValueMask16;
#define JSVAL_MASK32_CLEAR ((uint32)0xFFFF0000)
#define JSVAL_MASK32_NULL ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_NULL))
#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;
typedef enum JSValueMask32
#if defined(_MSC_VER)
: uint32
#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__
# define VALUE_ALIGNMENT __attribute__((aligned (8)))
@ -264,32 +237,376 @@ typedef union jsval_payload
# error "TODO: do something for compiler"
#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)
# error "Need to fix up jsval_layout"
# error "Unsupported configuration"
#endif
// TODO: explain
typedef union jsval_layout
{
uint64 asBits;
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 {
struct {
JSValueMask16 mask16;
uint16 nanBits;
} tag;
uint32 mask32;
JSValueMask32 mask32;
};
} s;
double asDouble;
} jsval_layout;
typedef uint64 jsval;
#if JS_BITS_PER_WORD == 32
/* These are engine-internal details, not part of the public API */
#define DOUBLE_AS_JSVAL(d) (*(jsval *)&(d))
#define JSVAL_CONSTANT(mask32, payload) ((jsval)((((uint64)(mask32)) << 32) | (payload)))
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_NULL_IMPL(jsval_layout l)
{
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)
@ -396,7 +713,7 @@ static JS_ALWAYS_INLINE jsint
JSBOXEDWORD_TO_SPECIAL(jsboxedword w)
{
JS_ASSERT(JSBOXEDWORD_IS_SPECIAL(w));
return w >> JSBOXEDWORD_TAGBITS;
return jsint(w >> JSBOXEDWORD_TAGBITS);
}
static JS_ALWAYS_INLINE jsboxedword

View File

@ -633,7 +633,7 @@ Class js_StringClass = {
static JSString *
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;
/*
@ -2640,7 +2640,11 @@ static const jschar UnitStringData[] = {
#pragma pack(push, 8)
#endif
#ifndef _M_X64
JSString JSString::unitStringTable[]
#else
JSString JSString::staticUnitStringTable[]
#endif
#ifdef __GNUC__
__attribute__ ((aligned (8)))
#endif
@ -2679,6 +2683,11 @@ __attribute__ ((aligned (8)))
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
#pragma pack(0)
#else
@ -2749,7 +2758,11 @@ static const jschar Hundreds[] = {
#pragma pack(push, 8)
#endif
#ifndef _M_X64
JSString JSString::intStringTable[]
#else
JSString JSString::staticIntStringTable[]
#endif
#ifdef __GNUC__
__attribute__ ((aligned (8)))
#endif
@ -2788,6 +2801,11 @@ __attribute__ ((aligned (8)))
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
#pragma pack(0)
#else

View File

@ -289,8 +289,20 @@ struct JSString {
#pragma align 8 (__1cIJSStringPunitStringTable_, __1cIJSStringOintStringTable_)
#endif
#ifndef _M_X64
static JSString unitStringTable[];
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 deflatedUnitStringTable[];

View File

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

View File

@ -670,7 +670,7 @@ class Worker : public WorkerParent
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)
{
if ((flags & JSRESOLVE_ASSIGNING) == 0) {
@ -869,7 +869,7 @@ class InitEvent : public Event
return fail;
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);
return Result(ok);
}
@ -906,7 +906,7 @@ class ErrorEvent : public Event
JSString *data = NULL;
jsval exc;
if (JS_GetPendingException(cx, &exc)) {
AutoValueRooter tvr(cx, exc);
AutoValueRooter tvr(cx, Valueify(exc));
JS_ClearPendingException(cx);
// Determine what error message to put in the error event.

View File

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