зеркало из https://github.com/mozilla/gecko-dev.git
merge
This commit is contained in:
Коммит
8400dfe655
|
@ -505,7 +505,7 @@ CreatePrototypeObjectForComplexTypeInstance(JSContext *cx,
|
|||
return result;
|
||||
}
|
||||
|
||||
const Class ArrayTypeDescr::class_ = {
|
||||
const Class UnsizedArrayTypeDescr::class_ = {
|
||||
"ArrayType",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
|
||||
JS_PropertyStub,
|
||||
|
@ -518,7 +518,24 @@ const Class ArrayTypeDescr::class_ = {
|
|||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
TypedObject::construct,
|
||||
OutlineTypedObject::constructUnsized,
|
||||
nullptr
|
||||
};
|
||||
|
||||
const Class SizedArrayTypeDescr::class_ = {
|
||||
"ArrayType",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
|
||||
JS_PropertyStub,
|
||||
JS_DeletePropertyStub,
|
||||
JS_PropertyStub,
|
||||
JS_StrictPropertyStub,
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
TypedObject::constructSized,
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
@ -528,6 +545,7 @@ const JSPropertySpec ArrayMetaTypeDescr::typeObjectProperties[] = {
|
|||
|
||||
const JSFunctionSpec ArrayMetaTypeDescr::typeObjectMethods[] = {
|
||||
{"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
|
||||
JS_FN("dimension", UnsizedArrayTypeDescr::dimension, 1, 0),
|
||||
JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
|
||||
{"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
|
||||
JS_SELF_HOSTED_FN("build", "TypedObjectArrayTypeBuild", 3, 0),
|
||||
|
@ -559,9 +577,11 @@ bool
|
|||
js::CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr descr)
|
||||
{
|
||||
// If data is transparent, also store the public slots.
|
||||
if (descr->transparent()) {
|
||||
if (descr->transparent() && descr->is<SizedTypeDescr>()) {
|
||||
Rooted<SizedTypeDescr*> sizedDescr(cx, &descr->as<SizedTypeDescr>());
|
||||
|
||||
// byteLength
|
||||
RootedValue typeByteLength(cx, Int32Value(descr->size()));
|
||||
RootedValue typeByteLength(cx, Int32Value(sizedDescr->size()));
|
||||
if (!JSObject::defineProperty(cx, descr, cx->names().byteLength,
|
||||
typeByteLength,
|
||||
nullptr, nullptr,
|
||||
|
@ -571,7 +591,7 @@ js::CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr descr)
|
|||
}
|
||||
|
||||
// byteAlignment
|
||||
RootedValue typeByteAlignment(cx, Int32Value(descr->alignment()));
|
||||
RootedValue typeByteAlignment(cx, Int32Value(sizedDescr->alignment()));
|
||||
if (!JSObject::defineProperty(cx, descr, cx->names().byteAlignment,
|
||||
typeByteAlignment,
|
||||
nullptr, nullptr,
|
||||
|
@ -599,29 +619,38 @@ js::CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr descr)
|
|||
}
|
||||
}
|
||||
|
||||
// variable -- true for unsized arrays
|
||||
RootedValue variable(cx, BooleanValue(!descr->is<SizedTypeDescr>()));
|
||||
if (!JSObject::defineProperty(cx, descr, cx->names().variable,
|
||||
variable,
|
||||
nullptr, nullptr,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ArrayTypeDescr *
|
||||
template<class T>
|
||||
T *
|
||||
ArrayMetaTypeDescr::create(JSContext *cx,
|
||||
HandleObject arrayTypePrototype,
|
||||
HandleTypeDescr elementType,
|
||||
HandleSizedTypeDescr elementType,
|
||||
HandleAtom stringRepr,
|
||||
int32_t size,
|
||||
int32_t length)
|
||||
int32_t size)
|
||||
{
|
||||
Rooted<ArrayTypeDescr*> obj(cx);
|
||||
obj = NewObjectWithProto<ArrayTypeDescr>(cx, arrayTypePrototype, nullptr, SingletonObject);
|
||||
Rooted<T*> obj(cx);
|
||||
obj = NewObjectWithProto<T>(cx, arrayTypePrototype, nullptr, SingletonObject);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
obj->initReservedSlot(JS_DESCR_SLOT_KIND, Int32Value(ArrayTypeDescr::Kind));
|
||||
obj->initReservedSlot(JS_DESCR_SLOT_KIND, Int32Value(T::Kind));
|
||||
obj->initReservedSlot(JS_DESCR_SLOT_STRING_REPR, StringValue(stringRepr));
|
||||
obj->initReservedSlot(JS_DESCR_SLOT_ALIGNMENT, Int32Value(elementType->alignment()));
|
||||
obj->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(size));
|
||||
obj->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(elementType->opaque()));
|
||||
obj->initReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE, ObjectValue(*elementType));
|
||||
obj->initReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH, Int32Value(length));
|
||||
|
||||
RootedValue elementTypeVal(cx, ObjectValue(*elementType));
|
||||
if (!JSObject::defineProperty(cx, obj, cx->names().elementType,
|
||||
|
@ -629,12 +658,6 @@ ArrayMetaTypeDescr::create(JSContext *cx,
|
|||
JSPROP_READONLY | JSPROP_PERMANENT))
|
||||
return nullptr;
|
||||
|
||||
RootedValue lengthValue(cx, NumberValue(length));
|
||||
if (!JSObject::defineProperty(cx, obj, cx->names().length,
|
||||
lengthValue, nullptr, nullptr,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT))
|
||||
return nullptr;
|
||||
|
||||
if (!CreateUserSizeAndAlignmentProperties(cx, obj))
|
||||
return nullptr;
|
||||
|
||||
|
@ -664,42 +687,25 @@ ArrayMetaTypeDescr::construct(JSContext *cx, unsigned argc, Value *vp)
|
|||
|
||||
RootedObject arrayTypeGlobal(cx, &args.callee());
|
||||
|
||||
// Expect two arguments. The first is a type object, the second is a length.
|
||||
if (args.length() < 2) {
|
||||
// Expect one argument which is a sized type object
|
||||
if (args.length() < 1) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
|
||||
"ArrayType", "1", "");
|
||||
"ArrayType", "0", "");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!args[0].isObject() || !args[0].toObject().is<TypeDescr>()) {
|
||||
if (!args[0].isObject() || !args[0].toObject().is<SizedTypeDescr>()) {
|
||||
ReportCannotConvertTo(cx, args[0], "ArrayType element specifier");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!args[1].isInt32() || args[1].toInt32() < 0) {
|
||||
ReportCannotConvertTo(cx, args[1], "ArrayType length specifier");
|
||||
return false;
|
||||
}
|
||||
Rooted<SizedTypeDescr*> elementType(cx);
|
||||
elementType = &args[0].toObject().as<SizedTypeDescr>();
|
||||
|
||||
Rooted<TypeDescr*> elementType(cx, &args[0].toObject().as<TypeDescr>());
|
||||
|
||||
int32_t length = args[1].toInt32();
|
||||
|
||||
// Compute the byte size.
|
||||
CheckedInt32 size = CheckedInt32(elementType->size()) * length;
|
||||
if (!size.isValid()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_TYPEDOBJECT_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Construct a canonical string `new ArrayType(<elementType>, N)`:
|
||||
// Construct a canonical string `new ArrayType(<elementType>)`:
|
||||
StringBuffer contents(cx);
|
||||
contents.append("new ArrayType(");
|
||||
contents.append(&elementType->stringRepr());
|
||||
contents.append(", ");
|
||||
if (!NumberValueToStringBuffer(cx, NumberValue(length), contents))
|
||||
return false;
|
||||
contents.append(")");
|
||||
RootedAtom stringRepr(cx, contents.finishAtom());
|
||||
if (!stringRepr)
|
||||
|
@ -711,11 +717,91 @@ ArrayMetaTypeDescr::construct(JSContext *cx, unsigned argc, Value *vp)
|
|||
return false;
|
||||
|
||||
// Create the instance of ArrayType
|
||||
Rooted<ArrayTypeDescr *> obj(cx);
|
||||
obj = create(cx, arrayTypePrototype, elementType, stringRepr, size.value(), length);
|
||||
Rooted<UnsizedArrayTypeDescr *> obj(cx);
|
||||
obj = create<UnsizedArrayTypeDescr>(cx, arrayTypePrototype, elementType,
|
||||
stringRepr, 0);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
// Add `length` property, which is undefined for an unsized array.
|
||||
if (!JSObject::defineProperty(cx, obj, cx->names().length,
|
||||
UndefinedHandleValue, nullptr, nullptr,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT))
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
UnsizedArrayTypeDescr::dimension(JSContext *cx, unsigned int argc, jsval *vp)
|
||||
{
|
||||
// Expect that the `this` pointer is an unsized array type
|
||||
// and the first argument is an integer size.
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() != 1 ||
|
||||
!args.thisv().isObject() ||
|
||||
!args.thisv().toObject().is<UnsizedArrayTypeDescr>() ||
|
||||
!args[0].isInt32() ||
|
||||
args[0].toInt32() < 0)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract arguments.
|
||||
Rooted<UnsizedArrayTypeDescr*> unsizedTypeDescr(cx);
|
||||
unsizedTypeDescr = &args.thisv().toObject().as<UnsizedArrayTypeDescr>();
|
||||
int32_t length = args[0].toInt32();
|
||||
Rooted<SizedTypeDescr*> elementType(cx, &unsizedTypeDescr->elementType());
|
||||
|
||||
// Compute the size.
|
||||
CheckedInt32 size = CheckedInt32(elementType->size()) * length;
|
||||
if (!size.isValid()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_TYPEDOBJECT_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Construct a canonical string `new ArrayType(<elementType>).dimension(N)`:
|
||||
StringBuffer contents(cx);
|
||||
contents.append("new ArrayType(");
|
||||
contents.append(&elementType->stringRepr());
|
||||
contents.append(").dimension(");
|
||||
if (!NumberValueToStringBuffer(cx, NumberValue(length), contents))
|
||||
return false;
|
||||
contents.append(")");
|
||||
RootedAtom stringRepr(cx, contents.finishAtom());
|
||||
if (!stringRepr)
|
||||
return false;
|
||||
|
||||
// Create the sized type object.
|
||||
Rooted<SizedArrayTypeDescr*> obj(cx);
|
||||
obj = ArrayMetaTypeDescr::create<SizedArrayTypeDescr>(cx, unsizedTypeDescr,
|
||||
elementType,
|
||||
stringRepr, size.value());
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
obj->initReservedSlot(JS_DESCR_SLOT_SIZED_ARRAY_LENGTH,
|
||||
Int32Value(length));
|
||||
|
||||
// Add `length` property.
|
||||
RootedValue lengthVal(cx, Int32Value(length));
|
||||
if (!JSObject::defineProperty(cx, obj, cx->names().length,
|
||||
lengthVal, nullptr, nullptr,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT))
|
||||
return false;
|
||||
|
||||
// Add `unsized` property, which is a link from the sized
|
||||
// array to the unsized array.
|
||||
RootedValue unsizedTypeDescrValue(cx, ObjectValue(*unsizedTypeDescr));
|
||||
if (!JSObject::defineProperty(cx, obj, cx->names().unsized,
|
||||
unsizedTypeDescrValue, nullptr, nullptr,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT))
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
@ -726,7 +812,7 @@ js::IsTypedObjectArray(JSObject &obj)
|
|||
if (!obj.is<TypedObject>())
|
||||
return false;
|
||||
TypeDescr& d = obj.as<TypedObject>().typeDescr();
|
||||
return d.is<ArrayTypeDescr>();
|
||||
return d.is<SizedArrayTypeDescr>() || d.is<UnsizedArrayTypeDescr>();
|
||||
}
|
||||
|
||||
/*********************************
|
||||
|
@ -746,7 +832,7 @@ const Class StructTypeDescr::class_ = {
|
|||
nullptr, /* finalize */
|
||||
nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
TypedObject::construct,
|
||||
TypedObject::constructSized,
|
||||
nullptr /* trace */
|
||||
};
|
||||
|
||||
|
@ -807,7 +893,7 @@ StructMetaTypeDescr::create(JSContext *cx,
|
|||
|
||||
RootedValue fieldTypeVal(cx);
|
||||
RootedId id(cx);
|
||||
Rooted<TypeDescr*> fieldType(cx);
|
||||
Rooted<SizedTypeDescr*> fieldType(cx);
|
||||
for (unsigned int i = 0; i < ids.length(); i++) {
|
||||
id = ids[i];
|
||||
|
||||
|
@ -823,7 +909,7 @@ StructMetaTypeDescr::create(JSContext *cx,
|
|||
// The value should be a type descriptor.
|
||||
if (!JSObject::getGeneric(cx, fields, fields, id, &fieldTypeVal))
|
||||
return nullptr;
|
||||
fieldType = ToObjectIf<TypeDescr>(fieldTypeVal);
|
||||
fieldType = ToObjectIf<SizedTypeDescr>(fieldTypeVal);
|
||||
if (!fieldType) {
|
||||
ReportCannotConvertTo(cx, fieldTypeVal, "StructType field specifier");
|
||||
return nullptr;
|
||||
|
@ -1082,22 +1168,22 @@ StructTypeDescr::maybeForwardedFieldOffset(size_t index) const
|
|||
return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32());
|
||||
}
|
||||
|
||||
TypeDescr&
|
||||
SizedTypeDescr&
|
||||
StructTypeDescr::fieldDescr(size_t index) const
|
||||
{
|
||||
NativeObject &fieldDescrs = fieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_TYPES);
|
||||
MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength());
|
||||
return fieldDescrs.getDenseElement(index).toObject().as<TypeDescr>();
|
||||
return fieldDescrs.getDenseElement(index).toObject().as<SizedTypeDescr>();
|
||||
}
|
||||
|
||||
TypeDescr&
|
||||
SizedTypeDescr&
|
||||
StructTypeDescr::maybeForwardedFieldDescr(size_t index) const
|
||||
{
|
||||
NativeObject &fieldDescrs = maybeForwardedFieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_TYPES);
|
||||
MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength());
|
||||
JSObject &descr =
|
||||
*MaybeForwarded(&fieldDescrs.getDenseElement(index).toObject());
|
||||
return descr.as<TypeDescr>();
|
||||
return descr.as<SizedTypeDescr>();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -1382,7 +1468,9 @@ TypedObject::offset() const
|
|||
int32_t
|
||||
TypedObject::length() const
|
||||
{
|
||||
return typeDescr().as<ArrayTypeDescr>().length();
|
||||
if (typeDescr().is<SizedArrayTypeDescr>())
|
||||
return typeDescr().as<SizedArrayTypeDescr>().length();
|
||||
return as<OutlineTypedObject>().unsizedLength();
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
|
@ -1529,14 +1617,18 @@ OutlineTypedObject::createUnattachedWithClass(JSContext *cx,
|
|||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
gc::AllocKind allocKind = allocKindForTypeDescriptor(type);
|
||||
NewObjectKind newKind = (heap == gc::TenuredHeap) ? MaybeSingletonObject : GenericObject;
|
||||
JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, nullptr, gc::FINALIZE_OBJECT0, newKind);
|
||||
JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, nullptr, allocKind, newKind);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
OutlineTypedObject *typedObj = &obj->as<OutlineTypedObject>();
|
||||
|
||||
typedObj->setOwnerAndData(nullptr, nullptr);
|
||||
if (type->kind() == type::UnsizedArray)
|
||||
typedObj->setUnsizedLength(length);
|
||||
|
||||
return typedObj;
|
||||
}
|
||||
|
||||
|
@ -1576,7 +1668,7 @@ OutlineTypedObject::attach(JSContext *cx, TypedObject &typedObj, int32_t offset)
|
|||
}
|
||||
|
||||
// Returns a suitable JS_TYPEDOBJ_SLOT_LENGTH value for an instance of
|
||||
// the type `type`.
|
||||
// the type `type`. `type` must not be an unsized array.
|
||||
static int32_t
|
||||
TypedObjLengthFromType(TypeDescr &descr)
|
||||
{
|
||||
|
@ -1587,14 +1679,17 @@ TypedObjLengthFromType(TypeDescr &descr)
|
|||
case type::Simd:
|
||||
return 0;
|
||||
|
||||
case type::Array:
|
||||
return descr.as<ArrayTypeDescr>().length();
|
||||
case type::SizedArray:
|
||||
return descr.as<SizedArrayTypeDescr>().length();
|
||||
|
||||
case type::UnsizedArray:
|
||||
MOZ_CRASH("TypedObjLengthFromType() invoked on unsized type");
|
||||
}
|
||||
MOZ_CRASH("Invalid kind");
|
||||
}
|
||||
|
||||
/*static*/ OutlineTypedObject *
|
||||
OutlineTypedObject::createDerived(JSContext *cx, HandleTypeDescr type,
|
||||
OutlineTypedObject::createDerived(JSContext *cx, HandleSizedTypeDescr type,
|
||||
HandleTypedObject typedObj, int32_t offset)
|
||||
{
|
||||
MOZ_ASSERT(offset <= typedObj->size());
|
||||
|
@ -1618,9 +1713,11 @@ OutlineTypedObject::createDerived(JSContext *cx, HandleTypeDescr type,
|
|||
TypedObject::createZeroed(JSContext *cx, HandleTypeDescr descr, int32_t length, gc::InitialHeap heap)
|
||||
{
|
||||
// If possible, create an object with inline data.
|
||||
if ((size_t) descr->size() <= InlineTypedObject::MaximumSize) {
|
||||
if (descr->is<SizedTypeDescr>() &&
|
||||
(size_t) descr->as<SizedTypeDescr>().size() <= InlineTypedObject::MaximumSize)
|
||||
{
|
||||
InlineTypedObject *obj = InlineTypedObject::create(cx, descr, heap);
|
||||
descr->initInstances(cx->runtime(), obj->inlineTypedMem(), 1);
|
||||
descr->as<SizedTypeDescr>().initInstances(cx->runtime(), obj->inlineTypedMem(), 1);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -1630,14 +1727,49 @@ TypedObject::createZeroed(JSContext *cx, HandleTypeDescr descr, int32_t length,
|
|||
return nullptr;
|
||||
|
||||
// Allocate and initialize the memory for this instance.
|
||||
size_t totalSize = descr->size();
|
||||
Rooted<ArrayBufferObject*> buffer(cx);
|
||||
buffer = ArrayBufferObject::create(cx, totalSize);
|
||||
if (!buffer)
|
||||
return nullptr;
|
||||
descr->initInstances(cx->runtime(), buffer->dataPointer(), 1);
|
||||
obj->attach(cx, *buffer, 0);
|
||||
return obj;
|
||||
// Also initialize the JS_TYPEDOBJ_SLOT_LENGTH slot.
|
||||
switch (descr->kind()) {
|
||||
case type::Scalar:
|
||||
case type::Reference:
|
||||
case type::Struct:
|
||||
case type::Simd:
|
||||
case type::SizedArray:
|
||||
{
|
||||
size_t totalSize = descr->as<SizedTypeDescr>().size();
|
||||
Rooted<ArrayBufferObject*> buffer(cx);
|
||||
buffer = ArrayBufferObject::create(cx, totalSize);
|
||||
if (!buffer)
|
||||
return nullptr;
|
||||
descr->as<SizedTypeDescr>().initInstances(cx->runtime(), buffer->dataPointer(), 1);
|
||||
obj->attach(cx, *buffer, 0);
|
||||
return obj;
|
||||
}
|
||||
|
||||
case type::UnsizedArray:
|
||||
{
|
||||
Rooted<SizedTypeDescr*> elementTypeRepr(cx);
|
||||
elementTypeRepr = &descr->as<UnsizedArrayTypeDescr>().elementType();
|
||||
|
||||
CheckedInt32 totalSize = CheckedInt32(elementTypeRepr->size()) * length;
|
||||
if (!totalSize.isValid()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_TYPEDOBJECT_TOO_BIG);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Rooted<ArrayBufferObject*> buffer(cx);
|
||||
buffer = ArrayBufferObject::create(cx, totalSize.value());
|
||||
if (!buffer)
|
||||
return nullptr;
|
||||
|
||||
if (length)
|
||||
elementTypeRepr->initInstances(cx->runtime(), buffer->dataPointer(), length);
|
||||
obj->attach(cx, *buffer, 0);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_CRASH("Bad TypeRepresentation Kind");
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1691,7 +1823,22 @@ OutlineTypedObject::obj_trace(JSTracer *trc, JSObject *object)
|
|||
if (!descr.opaque() || !typedObj.maybeForwardedIsAttached())
|
||||
return;
|
||||
|
||||
descr.traceInstances(trc, mem, 1);
|
||||
switch (descr.kind()) {
|
||||
case type::Scalar:
|
||||
case type::Reference:
|
||||
case type::Struct:
|
||||
case type::SizedArray:
|
||||
case type::Simd:
|
||||
descr.as<SizedTypeDescr>().traceInstances(trc, mem, 1);
|
||||
break;
|
||||
|
||||
case type::UnsizedArray:
|
||||
{
|
||||
SizedTypeDescr &elemType = descr.as<UnsizedArrayTypeDescr>().maybeForwardedElementType();
|
||||
elemType.traceInstances(trc, mem, typedObj.unsizedLength());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1707,7 +1854,8 @@ TypedObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
|||
case type::Simd:
|
||||
break;
|
||||
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
case type::UnsizedArray:
|
||||
{
|
||||
uint32_t index;
|
||||
if (js_IdIsIndex(id, &index))
|
||||
|
@ -1834,7 +1982,8 @@ TypedObject::obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiv
|
|||
case type::Simd:
|
||||
break;
|
||||
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
case type::UnsizedArray:
|
||||
if (JSID_IS_ATOM(id, cx->names().length)) {
|
||||
if (!typedObj->isAttached()) {
|
||||
JS_ReportErrorNumber(
|
||||
|
@ -1856,7 +2005,7 @@ TypedObject::obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiv
|
|||
break;
|
||||
|
||||
size_t offset = descr->fieldOffset(fieldIndex);
|
||||
Rooted<TypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
|
||||
Rooted<SizedTypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
|
||||
return Reify(cx, fieldType, typedObj, offset, vp);
|
||||
}
|
||||
}
|
||||
|
@ -1893,8 +2042,13 @@ TypedObject::obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiv
|
|||
case type::Struct:
|
||||
break;
|
||||
|
||||
case type::Array:
|
||||
return obj_getArrayElement(cx, typedObj, descr, index, vp);
|
||||
case type::SizedArray:
|
||||
return obj_getArrayElement<SizedArrayTypeDescr>(cx, typedObj, descr,
|
||||
index, vp);
|
||||
|
||||
case type::UnsizedArray:
|
||||
return obj_getArrayElement<UnsizedArrayTypeDescr>(cx, typedObj, descr,
|
||||
index, vp);
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
|
@ -1906,6 +2060,7 @@ TypedObject::obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiv
|
|||
return JSObject::getElement(cx, proto, receiver, index, vp);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
/*static*/ bool
|
||||
TypedObject::obj_getArrayElement(JSContext *cx,
|
||||
Handle<TypedObject*> typedObj,
|
||||
|
@ -1913,12 +2068,14 @@ TypedObject::obj_getArrayElement(JSContext *cx,
|
|||
uint32_t index,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
MOZ_ASSERT(typeDescr->is<T>());
|
||||
|
||||
if (index >= (size_t) typedObj->length()) {
|
||||
vp.setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
Rooted<TypeDescr*> elementType(cx, &typeDescr->as<ArrayTypeDescr>().elementType());
|
||||
Rooted<SizedTypeDescr*> elementType(cx, &typeDescr->as<T>().elementType());
|
||||
size_t offset = elementType->size() * index;
|
||||
return Reify(cx, elementType, typedObj, offset, vp);
|
||||
}
|
||||
|
@ -1942,7 +2099,8 @@ TypedObject::obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
|||
case type::Simd:
|
||||
break;
|
||||
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
case type::UnsizedArray:
|
||||
if (JSID_IS_ATOM(id, cx->names().length)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
|
||||
|
@ -1958,7 +2116,7 @@ TypedObject::obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
|||
break;
|
||||
|
||||
size_t offset = descr->fieldOffset(fieldIndex);
|
||||
Rooted<TypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
|
||||
Rooted<SizedTypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
|
||||
return ConvertAndCopyTo(cx, fieldType, typedObj, offset, vp);
|
||||
}
|
||||
}
|
||||
|
@ -1990,13 +2148,17 @@ TypedObject::obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
|
|||
case type::Struct:
|
||||
break;
|
||||
|
||||
case type::Array:
|
||||
return obj_setArrayElement(cx, typedObj, descr, index, vp);
|
||||
case type::SizedArray:
|
||||
return obj_setArrayElement<SizedArrayTypeDescr>(cx, typedObj, descr, index, vp);
|
||||
|
||||
case type::UnsizedArray:
|
||||
return obj_setArrayElement<UnsizedArrayTypeDescr>(cx, typedObj, descr, index, vp);
|
||||
}
|
||||
|
||||
return ReportTypedObjTypeError(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, typedObj);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
/*static*/ bool
|
||||
TypedObject::obj_setArrayElement(JSContext *cx,
|
||||
Handle<TypedObject*> typedObj,
|
||||
|
@ -2004,14 +2166,16 @@ TypedObject::obj_setArrayElement(JSContext *cx,
|
|||
uint32_t index,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
MOZ_ASSERT(descr->is<T>());
|
||||
|
||||
if (index >= (size_t) typedObj->length()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BINARYARRAY_BAD_INDEX);
|
||||
return false;
|
||||
}
|
||||
|
||||
Rooted<TypeDescr*> elementType(cx);
|
||||
elementType = &descr->as<ArrayTypeDescr>().elementType();
|
||||
Rooted<SizedTypeDescr*> elementType(cx);
|
||||
elementType = &descr->as<T>().elementType();
|
||||
size_t offset = elementType->size() * index;
|
||||
return ConvertAndCopyTo(cx, elementType, typedObj, offset, vp);
|
||||
}
|
||||
|
@ -2030,7 +2194,8 @@ TypedObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj,
|
|||
case type::Simd:
|
||||
break;
|
||||
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
case type::UnsizedArray:
|
||||
if (js_IdIsIndex(id, &index)) {
|
||||
*attrsp = JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
||||
return true;
|
||||
|
@ -2070,7 +2235,8 @@ IsOwnId(JSContext *cx, HandleObject obj, HandleId id)
|
|||
case type::Simd:
|
||||
return false;
|
||||
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
case type::UnsizedArray:
|
||||
return js_IdIsIndex(id, &index) || JSID_IS_ATOM(id, cx->names().length);
|
||||
|
||||
case type::Struct:
|
||||
|
@ -2139,7 +2305,8 @@ TypedObject::obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
|
|||
}
|
||||
break;
|
||||
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
case type::UnsizedArray:
|
||||
switch (enum_op) {
|
||||
case JSENUMERATE_INIT_ALL:
|
||||
case JSENUMERATE_INIT:
|
||||
|
@ -2199,6 +2366,8 @@ TypedObject::obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
|
|||
void
|
||||
OutlineTypedObject::neuter(void *newData)
|
||||
{
|
||||
if (typeDescr().kind() == type::UnsizedArray)
|
||||
setUnsizedLength(0);
|
||||
setData(reinterpret_cast<uint8_t *>(newData));
|
||||
}
|
||||
|
||||
|
@ -2249,7 +2418,7 @@ InlineTypedObject::obj_trace(JSTracer *trc, JSObject *object)
|
|||
// may not have had their slots updated yet.
|
||||
TypeDescr &descr = typedObj.maybeForwardedTypeDescr();
|
||||
|
||||
descr.traceInstances(trc, typedObj.inlineTypedMem(), 1);
|
||||
descr.as<SizedTypeDescr>().traceInstances(trc, typedObj.inlineTypedMem(), 1);
|
||||
}
|
||||
|
||||
ArrayBufferObject *
|
||||
|
@ -2268,7 +2437,7 @@ InlineTransparentTypedObject::getOrCreateBuffer(JSContext *cx)
|
|||
|
||||
ArrayBufferObject::BufferContents contents =
|
||||
ArrayBufferObject::BufferContents::createPlain(inlineTypedMem());
|
||||
size_t nbytes = typeDescr().size();
|
||||
size_t nbytes = typeDescr().as<SizedTypeDescr>().size();
|
||||
|
||||
// Prevent GC under ArrayBufferObject::create, which might move this object
|
||||
// and its contents.
|
||||
|
@ -2425,8 +2594,11 @@ LengthForType(TypeDescr &descr)
|
|||
case type::Simd:
|
||||
return 0;
|
||||
|
||||
case type::Array:
|
||||
return descr.as<ArrayTypeDescr>().length();
|
||||
case type::SizedArray:
|
||||
return descr.as<SizedArrayTypeDescr>().length();
|
||||
|
||||
case type::UnsizedArray:
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOZ_CRASH("Invalid kind");
|
||||
|
@ -2461,15 +2633,15 @@ CheckOffset(int32_t offset,
|
|||
}
|
||||
|
||||
/*static*/ bool
|
||||
TypedObject::construct(JSContext *cx, unsigned int argc, Value *vp)
|
||||
TypedObject::constructSized(JSContext *cx, unsigned int argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
MOZ_ASSERT(args.callee().is<TypeDescr>());
|
||||
Rooted<TypeDescr*> callee(cx, &args.callee().as<TypeDescr>());
|
||||
MOZ_ASSERT(args.callee().is<SizedTypeDescr>());
|
||||
Rooted<SizedTypeDescr*> callee(cx, &args.callee().as<SizedTypeDescr>());
|
||||
|
||||
// Typed object constructors are overloaded in three ways, in order of
|
||||
// precedence:
|
||||
// Typed object constructors for sized types are overloaded in
|
||||
// three ways, in order of precedence:
|
||||
//
|
||||
// new TypeObj()
|
||||
// new TypeObj(buffer, [offset])
|
||||
|
@ -2554,6 +2726,162 @@ TypedObject::construct(JSContext *cx, unsigned int argc, Value *vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
TypedObject::constructUnsized(JSContext *cx, unsigned int argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
MOZ_ASSERT(args.callee().is<TypeDescr>());
|
||||
Rooted<UnsizedArrayTypeDescr*> callee(cx);
|
||||
callee = &args.callee().as<UnsizedArrayTypeDescr>();
|
||||
|
||||
// Typed object constructors for unsized arrays are overloaded in
|
||||
// four ways, in order of precedence:
|
||||
//
|
||||
// new TypeObj(buffer, [offset, [length]]) // [1]
|
||||
// new TypeObj(length) // [1]
|
||||
// new TypeObj(data)
|
||||
// new TypeObj()
|
||||
//
|
||||
// [1] Explicit lengths only available for unsized arrays.
|
||||
|
||||
// Zero argument constructor:
|
||||
if (args.length() == 0) {
|
||||
Rooted<TypedObject*> obj(cx, createZeroed(cx, callee, 0));
|
||||
if (!obj)
|
||||
return false;
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Length constructor.
|
||||
if (args[0].isInt32()) {
|
||||
int32_t length = args[0].toInt32();
|
||||
if (length < 0) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
Rooted<TypedObject*> obj(cx, createZeroed(cx, callee, length));
|
||||
if (!obj)
|
||||
return false;
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Buffer constructor.
|
||||
if (args[0].isObject() && args[0].toObject().is<ArrayBufferObject>()) {
|
||||
Rooted<ArrayBufferObject*> buffer(cx);
|
||||
buffer = &args[0].toObject().as<ArrayBufferObject>();
|
||||
|
||||
if (callee->opaque()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t offset;
|
||||
if (args.length() >= 2 && !args[1].isUndefined()) {
|
||||
if (!args[1].isInt32()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
offset = args[1].toInt32();
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if (!CheckOffset(offset, 0, callee->alignment(), buffer->byteLength())) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t elemSize = callee->elementType().size();
|
||||
int32_t bytesRemaining = buffer->byteLength() - offset;
|
||||
int32_t maximumLength = bytesRemaining / elemSize;
|
||||
|
||||
int32_t length;
|
||||
if (args.length() >= 3 && !args[2].isUndefined()) {
|
||||
if (!args[2].isInt32()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
length = args[2].toInt32();
|
||||
|
||||
if (length < 0 || length > maximumLength) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ((bytesRemaining % elemSize) != 0) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
length = maximumLength;
|
||||
}
|
||||
|
||||
if (buffer->isNeutered()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
Rooted<OutlineTypedObject*> obj(cx);
|
||||
obj = OutlineTypedObject::createUnattached(cx, callee, length);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
obj->attach(cx, args[0].toObject().as<ArrayBufferObject>(), offset);
|
||||
}
|
||||
|
||||
// Data constructor for unsized values
|
||||
if (args[0].isObject()) {
|
||||
// Read length out of the object.
|
||||
RootedObject arg(cx, &args[0].toObject());
|
||||
RootedValue lengthVal(cx);
|
||||
if (!JSObject::getProperty(cx, arg, arg, cx->names().length, &lengthVal))
|
||||
return false;
|
||||
if (!lengthVal.isInt32()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
int32_t length = lengthVal.toInt32();
|
||||
|
||||
// Check that length * elementSize does not overflow.
|
||||
int32_t elementSize = callee->elementType().size();
|
||||
int32_t byteLength;
|
||||
if (!SafeMul(elementSize, length, &byteLength)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the unsized array.
|
||||
Rooted<TypedObject*> obj(cx, createZeroed(cx, callee, length));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
// Initialize from `arg`
|
||||
if (!ConvertAndCopyTo(cx, obj, args[0]))
|
||||
return false;
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Something bogus.
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage,
|
||||
nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Intrinsics
|
||||
*/
|
||||
|
@ -2563,9 +2891,9 @@ js::NewOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp)
|
|||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<TypeDescr>());
|
||||
MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<SizedTypeDescr>());
|
||||
|
||||
Rooted<TypeDescr*> descr(cx, &args[0].toObject().as<TypeDescr>());
|
||||
Rooted<SizedTypeDescr*> descr(cx, &args[0].toObject().as<SizedTypeDescr>());
|
||||
int32_t length = TypedObjLengthFromType(*descr);
|
||||
Rooted<OutlineTypedObject*> obj(cx);
|
||||
obj = OutlineTypedObject::createUnattachedWithClass(cx, &OutlineOpaqueTypedObject::class_, descr, length);
|
||||
|
@ -2580,11 +2908,11 @@ js::NewDerivedTypedObject(JSContext *cx, unsigned argc, Value *vp)
|
|||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 3);
|
||||
MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<TypeDescr>());
|
||||
MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<SizedTypeDescr>());
|
||||
MOZ_ASSERT(args[1].isObject() && args[1].toObject().is<TypedObject>());
|
||||
MOZ_ASSERT(args[2].isInt32());
|
||||
|
||||
Rooted<TypeDescr*> descr(cx, &args[0].toObject().as<TypeDescr>());
|
||||
Rooted<SizedTypeDescr*> descr(cx, &args[0].toObject().as<SizedTypeDescr>());
|
||||
Rooted<TypedObject*> typedObj(cx, &args[1].toObject().as<TypedObject>());
|
||||
int32_t offset = args[2].toInt32();
|
||||
|
||||
|
@ -2729,7 +3057,8 @@ js::TypeDescrIsArrayType(ThreadSafeContext *, unsigned argc, Value *vp)
|
|||
MOZ_ASSERT(args[0].isObject());
|
||||
MOZ_ASSERT(args[0].toObject().is<js::TypeDescr>());
|
||||
JSObject& obj = args[0].toObject();
|
||||
args.rval().setBoolean(obj.is<js::ArrayTypeDescr>());
|
||||
args.rval().setBoolean(obj.is<js::SizedArrayTypeDescr>() ||
|
||||
obj.is<js::UnsizedArrayTypeDescr>());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2737,6 +3066,36 @@ JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypeDescrIsArrayTypeJitInfo,
|
|||
TypeDescrIsArrayTypeJitInfo,
|
||||
js::TypeDescrIsArrayType);
|
||||
|
||||
bool
|
||||
js::TypeDescrIsSizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
MOZ_ASSERT(args[0].isObject());
|
||||
MOZ_ASSERT(args[0].toObject().is<js::TypeDescr>());
|
||||
args.rval().setBoolean(args[0].toObject().is<js::SizedArrayTypeDescr>());
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypeDescrIsSizedArrayTypeJitInfo,
|
||||
TypeDescrIsSizedArrayTypeJitInfo,
|
||||
js::TypeDescrIsSizedArrayType);
|
||||
|
||||
bool
|
||||
js::TypeDescrIsUnsizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
MOZ_ASSERT(args[0].isObject());
|
||||
MOZ_ASSERT(args[0].toObject().is<js::TypeDescr>());
|
||||
args.rval().setBoolean(args[0].toObject().is<js::UnsizedArrayTypeDescr>());
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypeDescrIsUnsizedArrayTypeJitInfo,
|
||||
TypeDescrIsUnsizedArrayTypeJitInfo,
|
||||
js::TypeDescrIsUnsizedArrayType);
|
||||
|
||||
bool
|
||||
js::TypedObjectIsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
|
@ -2952,7 +3311,7 @@ JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_LOAD_REFERENCE_CLASS_IMPL)
|
|||
|
||||
template<typename V>
|
||||
static void
|
||||
visitReferences(TypeDescr &descr,
|
||||
visitReferences(SizedTypeDescr &descr,
|
||||
uint8_t *mem,
|
||||
V& visitor)
|
||||
{
|
||||
|
@ -2968,10 +3327,10 @@ visitReferences(TypeDescr &descr,
|
|||
visitor.visitReference(descr.as<ReferenceTypeDescr>(), mem);
|
||||
return;
|
||||
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
{
|
||||
ArrayTypeDescr &arrayDescr = descr.as<ArrayTypeDescr>();
|
||||
TypeDescr &elementDescr = arrayDescr.maybeForwardedElementType();
|
||||
SizedArrayTypeDescr &arrayDescr = descr.as<SizedArrayTypeDescr>();
|
||||
SizedTypeDescr &elementDescr = arrayDescr.maybeForwardedElementType();
|
||||
for (int32_t i = 0; i < arrayDescr.length(); i++) {
|
||||
visitReferences(elementDescr, mem, visitor);
|
||||
mem += elementDescr.size();
|
||||
|
@ -2979,11 +3338,16 @@ visitReferences(TypeDescr &descr,
|
|||
return;
|
||||
}
|
||||
|
||||
case type::UnsizedArray:
|
||||
{
|
||||
MOZ_CRASH("Only Sized Type representations");
|
||||
}
|
||||
|
||||
case type::Struct:
|
||||
{
|
||||
StructTypeDescr &structDescr = descr.as<StructTypeDescr>();
|
||||
for (size_t i = 0; i < structDescr.maybeForwardedFieldCount(); i++) {
|
||||
TypeDescr &descr = structDescr.maybeForwardedFieldDescr(i);
|
||||
SizedTypeDescr &descr = structDescr.maybeForwardedFieldDescr(i);
|
||||
size_t offset = structDescr.maybeForwardedFieldOffset(i);
|
||||
visitReferences(descr, mem + offset, visitor);
|
||||
}
|
||||
|
@ -3042,7 +3406,7 @@ js::MemoryInitVisitor::visitReference(ReferenceTypeDescr &descr, uint8_t *mem)
|
|||
}
|
||||
|
||||
void
|
||||
TypeDescr::initInstances(const JSRuntime *rt, uint8_t *mem, size_t length)
|
||||
SizedTypeDescr::initInstances(const JSRuntime *rt, uint8_t *mem, size_t length)
|
||||
{
|
||||
MOZ_ASSERT(length >= 1);
|
||||
|
||||
|
@ -3112,7 +3476,7 @@ js::MemoryTracingVisitor::visitReference(ReferenceTypeDescr &descr, uint8_t *mem
|
|||
}
|
||||
|
||||
void
|
||||
TypeDescr::traceInstances(JSTracer *trace, uint8_t *mem, size_t length)
|
||||
SizedTypeDescr::traceInstances(JSTracer *trace, uint8_t *mem, size_t length)
|
||||
{
|
||||
MemoryTracingVisitor visitor(trace);
|
||||
|
||||
|
|
|
@ -119,19 +119,25 @@ enum Kind {
|
|||
Reference = JS_TYPEREPR_REFERENCE_KIND,
|
||||
Simd = JS_TYPEREPR_SIMD_KIND,
|
||||
Struct = JS_TYPEREPR_STRUCT_KIND,
|
||||
Array = JS_TYPEREPR_ARRAY_KIND
|
||||
SizedArray = JS_TYPEREPR_SIZED_ARRAY_KIND,
|
||||
UnsizedArray = JS_TYPEREPR_UNSIZED_ARRAY_KIND,
|
||||
};
|
||||
|
||||
static inline bool isSized(type::Kind kind) {
|
||||
return kind > JS_TYPEREPR_MAX_UNSIZED_KIND;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Typed Prototypes
|
||||
|
||||
class SizedTypeDescr;
|
||||
class SimpleTypeDescr;
|
||||
class ComplexTypeDescr;
|
||||
class SimdTypeDescr;
|
||||
class StructTypeDescr;
|
||||
class TypedProto;
|
||||
class SizedTypedProto;
|
||||
|
||||
/*
|
||||
* The prototype for a typed object. Currently, carries a link to the
|
||||
|
@ -168,6 +174,10 @@ class TypeDescr : public NativeObject
|
|||
static const Class class_;
|
||||
|
||||
public:
|
||||
static bool isSized(type::Kind kind) {
|
||||
return kind > JS_TYPEREPR_MAX_UNSIZED_KIND;
|
||||
}
|
||||
|
||||
TypedProto &typedProto() const {
|
||||
return getReservedSlot(JS_DESCR_SLOT_TYPROTO).toObject().as<TypedProto>();
|
||||
}
|
||||
|
@ -191,7 +201,13 @@ class TypeDescr : public NativeObject
|
|||
int32_t alignment() const {
|
||||
return getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32();
|
||||
}
|
||||
};
|
||||
|
||||
typedef Handle<TypeDescr*> HandleTypeDescr;
|
||||
|
||||
class SizedTypeDescr : public TypeDescr
|
||||
{
|
||||
public:
|
||||
int32_t size() const {
|
||||
return getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32();
|
||||
}
|
||||
|
@ -200,9 +216,9 @@ class TypeDescr : public NativeObject
|
|||
void traceInstances(JSTracer *trace, uint8_t *mem, size_t length);
|
||||
};
|
||||
|
||||
typedef Handle<TypeDescr*> HandleTypeDescr;
|
||||
typedef Handle<SizedTypeDescr*> HandleSizedTypeDescr;
|
||||
|
||||
class SimpleTypeDescr : public TypeDescr
|
||||
class SimpleTypeDescr : public SizedTypeDescr
|
||||
{
|
||||
};
|
||||
|
||||
|
@ -312,7 +328,7 @@ class ReferenceTypeDescr : public SimpleTypeDescr
|
|||
|
||||
// Type descriptors whose instances are objects and hence which have
|
||||
// an associated `prototype` property.
|
||||
class ComplexTypeDescr : public TypeDescr
|
||||
class ComplexTypeDescr : public SizedTypeDescr
|
||||
{
|
||||
public:
|
||||
// Returns the prototype that instances of this type descriptor
|
||||
|
@ -356,8 +372,6 @@ bool IsTypedObjectArray(JSObject& obj);
|
|||
|
||||
bool CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr obj);
|
||||
|
||||
class ArrayTypeDescr;
|
||||
|
||||
/*
|
||||
* Properties and methods of the `ArrayType` meta type object. There
|
||||
* is no `class_` field because `ArrayType` is just a native
|
||||
|
@ -366,18 +380,25 @@ class ArrayTypeDescr;
|
|||
class ArrayMetaTypeDescr : public JSObject
|
||||
{
|
||||
private:
|
||||
// Helper for creating a new ArrayType object.
|
||||
friend class UnsizedArrayTypeDescr;
|
||||
|
||||
// Helper for creating a new ArrayType object, either sized or unsized.
|
||||
// The template parameter `T` should be either `UnsizedArrayTypeDescr`
|
||||
// or `SizedArrayTypeDescr`.
|
||||
//
|
||||
// - `arrayTypePrototype` - prototype for the new object to be created
|
||||
// - `arrayTypePrototype` - prototype for the new object to be created,
|
||||
// either ArrayType.prototype or
|
||||
// unsizedArrayType.__proto__ depending on
|
||||
// whether this is a sized or unsized array
|
||||
// - `elementType` - type object for the elements in the array
|
||||
// - `stringRepr` - canonical string representation for the array
|
||||
// - `size` - length of the array
|
||||
static ArrayTypeDescr *create(JSContext *cx,
|
||||
HandleObject arrayTypePrototype,
|
||||
HandleTypeDescr elementType,
|
||||
HandleAtom stringRepr,
|
||||
int32_t size,
|
||||
int32_t length);
|
||||
// - `size` - length of the array (0 if unsized)
|
||||
template<class T>
|
||||
static T *create(JSContext *cx,
|
||||
HandleObject arrayTypePrototype,
|
||||
HandleSizedTypeDescr elementType,
|
||||
HandleAtom stringRepr,
|
||||
int32_t size);
|
||||
|
||||
public:
|
||||
// Properties and methods to be installed on ArrayType.prototype,
|
||||
|
@ -396,25 +417,54 @@ class ArrayMetaTypeDescr : public JSObject
|
|||
};
|
||||
|
||||
/*
|
||||
* Type descriptor created by `new ArrayType(type, n)`
|
||||
* Type descriptor created by `new ArrayType(typeObj)`
|
||||
*
|
||||
* These have a prototype, and hence *could* be a subclass of
|
||||
* `ComplexTypeDescr`, but it would require some reshuffling of the
|
||||
* hierarchy, and it's not worth the trouble since they will be going
|
||||
* away as part of bug 973238.
|
||||
*/
|
||||
class ArrayTypeDescr : public ComplexTypeDescr
|
||||
class UnsizedArrayTypeDescr : public TypeDescr
|
||||
{
|
||||
public:
|
||||
static const Class class_;
|
||||
static const type::Kind Kind = type::Array;
|
||||
static const type::Kind Kind = type::UnsizedArray;
|
||||
|
||||
TypeDescr &elementType() const {
|
||||
return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<TypeDescr>();
|
||||
// This is the sized method on unsized array type objects. It
|
||||
// produces a sized variant.
|
||||
static bool dimension(JSContext *cx, unsigned int argc, jsval *vp);
|
||||
|
||||
SizedTypeDescr &elementType() const {
|
||||
return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>();
|
||||
}
|
||||
|
||||
TypeDescr &maybeForwardedElementType() const {
|
||||
SizedTypeDescr &maybeForwardedElementType() const {
|
||||
JSObject *elemType =
|
||||
MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject());
|
||||
return elemType->as<SizedTypeDescr>();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Type descriptor created by `unsizedArrayTypeObj.dimension()`
|
||||
*/
|
||||
class SizedArrayTypeDescr : public ComplexTypeDescr
|
||||
{
|
||||
public:
|
||||
static const Class class_;
|
||||
static const type::Kind Kind = type::SizedArray;
|
||||
|
||||
SizedTypeDescr &elementType() const {
|
||||
return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>();
|
||||
}
|
||||
|
||||
SizedTypeDescr &maybeForwardedElementType() const {
|
||||
JSObject *elemType = &getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject();
|
||||
return MaybeForwarded(elemType)->as<TypeDescr>();
|
||||
return MaybeForwarded(elemType)->as<SizedTypeDescr>();
|
||||
}
|
||||
|
||||
int32_t length() const {
|
||||
return getReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH).toInt32();
|
||||
return getReservedSlot(JS_DESCR_SLOT_SIZED_ARRAY_LENGTH).toInt32();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -462,8 +512,8 @@ class StructTypeDescr : public ComplexTypeDescr
|
|||
JSAtom &fieldName(size_t index) const;
|
||||
|
||||
// Return the type descr of the field at index `index`.
|
||||
TypeDescr &fieldDescr(size_t index) const;
|
||||
TypeDescr &maybeForwardedFieldDescr(size_t index) const;
|
||||
SizedTypeDescr &fieldDescr(size_t index) const;
|
||||
SizedTypeDescr &maybeForwardedFieldDescr(size_t index) const;
|
||||
|
||||
// Return the offset of the field at index `index`.
|
||||
size_t fieldOffset(size_t index) const;
|
||||
|
@ -503,12 +553,14 @@ class TypedObject : public JSObject
|
|||
private:
|
||||
static const bool IsTypedObjectClass = true;
|
||||
|
||||
template<class T>
|
||||
static bool obj_getArrayElement(JSContext *cx,
|
||||
Handle<TypedObject*> typedObj,
|
||||
Handle<TypeDescr*> typeDescr,
|
||||
uint32_t index,
|
||||
MutableHandleValue vp);
|
||||
|
||||
template<class T>
|
||||
static bool obj_setArrayElement(JSContext *cx,
|
||||
Handle<TypedObject*> typedObj,
|
||||
Handle<TypeDescr*> typeDescr,
|
||||
|
@ -548,6 +600,9 @@ class TypedObject : public JSObject
|
|||
static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp);
|
||||
|
||||
static bool obj_getUnsizedArrayElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp);
|
||||
|
||||
static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||
MutableHandleValue vp, bool strict);
|
||||
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||
|
@ -590,7 +645,20 @@ class TypedObject : public JSObject
|
|||
bool maybeForwardedIsAttached() const;
|
||||
|
||||
int32_t size() const {
|
||||
return typeDescr().size();
|
||||
switch (typeDescr().kind()) {
|
||||
case type::Scalar:
|
||||
case type::Simd:
|
||||
case type::Reference:
|
||||
case type::Struct:
|
||||
case type::SizedArray:
|
||||
return typeDescr().as<SizedTypeDescr>().size();
|
||||
|
||||
case type::UnsizedArray: {
|
||||
SizedTypeDescr &elementType = typeDescr().as<UnsizedArrayTypeDescr>().elementType();
|
||||
return elementType.size() * length();
|
||||
}
|
||||
}
|
||||
MOZ_CRASH("unhandled typerepresentation kind");
|
||||
}
|
||||
|
||||
uint8_t *typedMem(size_t offset) const {
|
||||
|
@ -611,9 +679,12 @@ class TypedObject : public JSObject
|
|||
static TypedObject *createZeroed(JSContext *cx, HandleTypeDescr typeObj, int32_t length,
|
||||
gc::InitialHeap heap = gc::DefaultHeap);
|
||||
|
||||
// User-accessible constructor (`new TypeDescriptor(...)`). Note that the
|
||||
// callee here is the type descriptor.
|
||||
static bool construct(JSContext *cx, unsigned argc, Value *vp);
|
||||
// User-accessible constructor (`new TypeDescriptor(...)`) used for sized
|
||||
// types. Note that the callee here is the type descriptor.
|
||||
static bool constructSized(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
// As `constructSized`, but for unsized array types.
|
||||
static bool constructUnsized(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
/* Accessors for self hosted code. */
|
||||
static bool GetBuffer(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
@ -632,12 +703,30 @@ class OutlineTypedObject : public TypedObject
|
|||
// Data pointer to some offset in the owner's contents.
|
||||
uint8_t *data_;
|
||||
|
||||
// The length for unsized array objects. For other outline objects the
|
||||
// space for this field is not allocated and cannot be accessed.
|
||||
uint32_t unsizedLength_;
|
||||
|
||||
void setOwnerAndData(JSObject *owner, uint8_t *data);
|
||||
|
||||
void setUnsizedLength(uint32_t length) {
|
||||
MOZ_ASSERT(typeDescr().is<UnsizedArrayTypeDescr>());
|
||||
unsizedLength_ = length;
|
||||
}
|
||||
|
||||
public:
|
||||
static gc::AllocKind allocKindForTypeDescriptor(TypeDescr *descr) {
|
||||
// Use a larger allocation kind for unsized arrays, to accommodate the
|
||||
// unsized length.
|
||||
if (descr->is<UnsizedArrayTypeDescr>())
|
||||
return gc::FINALIZE_OBJECT2;
|
||||
return gc::FINALIZE_OBJECT0;
|
||||
}
|
||||
|
||||
// JIT accessors.
|
||||
static size_t offsetOfData() { return offsetof(OutlineTypedObject, data_); }
|
||||
static size_t offsetOfOwner() { return offsetof(OutlineTypedObject, owner_); }
|
||||
static size_t offsetOfUnsizedLength() { return offsetof(OutlineTypedObject, unsizedLength_); }
|
||||
|
||||
JSObject &owner() const {
|
||||
MOZ_ASSERT(owner_);
|
||||
|
@ -652,6 +741,11 @@ class OutlineTypedObject : public TypedObject
|
|||
return data_;
|
||||
}
|
||||
|
||||
int32_t unsizedLength() const {
|
||||
MOZ_ASSERT(typeDescr().is<UnsizedArrayTypeDescr>());
|
||||
return unsizedLength_;
|
||||
}
|
||||
|
||||
void setData(uint8_t *data) {
|
||||
data_ = data;
|
||||
}
|
||||
|
@ -678,7 +772,7 @@ class OutlineTypedObject : public TypedObject
|
|||
// at the given offset. The typedObj will be a handle iff type is a
|
||||
// handle and a typed object otherwise.
|
||||
static OutlineTypedObject *createDerived(JSContext *cx,
|
||||
HandleTypeDescr type,
|
||||
HandleSizedTypeDescr type,
|
||||
Handle<TypedObject*> typedContents,
|
||||
int32_t offset);
|
||||
|
||||
|
@ -722,7 +816,7 @@ class InlineTypedObject : public TypedObject
|
|||
sizeof(NativeObject) - sizeof(TypedObject) + NativeObject::MAX_FIXED_SLOTS * sizeof(Value);
|
||||
|
||||
static gc::AllocKind allocKindForTypeDescriptor(TypeDescr *descr) {
|
||||
size_t nbytes = descr->size();
|
||||
size_t nbytes = descr->as<SizedTypeDescr>().size();
|
||||
MOZ_ASSERT(nbytes <= MaximumSize);
|
||||
|
||||
size_t dataSlots = AlignBytes(nbytes, sizeof(Value) / sizeof(Value));
|
||||
|
@ -838,6 +932,12 @@ extern const JSJitInfo TypeDescrIsSimpleTypeJitInfo;
|
|||
bool TypeDescrIsArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
|
||||
extern const JSJitInfo TypeDescrIsArrayTypeJitInfo;
|
||||
|
||||
bool TypeDescrIsSizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
|
||||
extern const JSJitInfo TypeDescrIsSizedArrayTypeJitInfo;
|
||||
|
||||
bool TypeDescrIsUnsizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
|
||||
extern const JSJitInfo TypeDescrIsUnsizedArrayTypeJitInfo;
|
||||
|
||||
/*
|
||||
* Usage: TypedObjectIsAttached(obj)
|
||||
*
|
||||
|
@ -1001,15 +1101,22 @@ inline bool
|
|||
IsComplexTypeDescrClass(const Class* clasp)
|
||||
{
|
||||
return clasp == &StructTypeDescr::class_ ||
|
||||
clasp == &ArrayTypeDescr::class_ ||
|
||||
clasp == &SizedArrayTypeDescr::class_ ||
|
||||
clasp == &SimdTypeDescr::class_;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsSizedTypeDescrClass(const Class* clasp)
|
||||
{
|
||||
return IsSimpleTypeDescrClass(clasp) ||
|
||||
IsComplexTypeDescrClass(clasp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsTypeDescrClass(const Class* clasp)
|
||||
{
|
||||
return IsSimpleTypeDescrClass(clasp) ||
|
||||
IsComplexTypeDescrClass(clasp);
|
||||
return IsSizedTypeDescrClass(clasp) ||
|
||||
clasp == &UnsizedArrayTypeDescr::class_;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -1054,6 +1161,13 @@ JSObject::is<js::SimpleTypeDescr>() const
|
|||
return IsSimpleTypeDescrClass(getClass());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool
|
||||
JSObject::is<js::SizedTypeDescr>() const
|
||||
{
|
||||
return IsSizedTypeDescrClass(getClass());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool
|
||||
JSObject::is<js::ComplexTypeDescr>() const
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_TYPE)
|
||||
#define DESCR_ARRAY_ELEMENT_TYPE(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_ARRAY_ELEM_TYPE)
|
||||
#define DESCR_ARRAY_LENGTH(obj) \
|
||||
TO_INT32(UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_ARRAY_LENGTH))
|
||||
#define DESCR_SIZED_ARRAY_LENGTH(obj) \
|
||||
TO_INT32(UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_SIZED_ARRAY_LENGTH))
|
||||
#define DESCR_STRUCT_FIELD_NAMES(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_NAMES)
|
||||
#define DESCR_STRUCT_FIELD_TYPES(obj) \
|
||||
|
@ -70,9 +70,12 @@ function TypedObjectGet(descr, typedObj, offset) {
|
|||
case JS_TYPEREPR_SIMD_KIND:
|
||||
return TypedObjectGetSimd(descr, typedObj, offset);
|
||||
|
||||
case JS_TYPEREPR_ARRAY_KIND:
|
||||
case JS_TYPEREPR_SIZED_ARRAY_KIND:
|
||||
case JS_TYPEREPR_STRUCT_KIND:
|
||||
return TypedObjectGetDerived(descr, typedObj, offset);
|
||||
|
||||
case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
|
||||
assert(false, "Unhandled repr kind: " + DESCR_KIND(descr));
|
||||
}
|
||||
|
||||
assert(false, "Unhandled kind: " + DESCR_KIND(descr));
|
||||
|
@ -198,8 +201,14 @@ function TypedObjectSet(descr, typedObj, offset, fromValue) {
|
|||
TypedObjectSetSimd(descr, typedObj, offset, fromValue);
|
||||
return;
|
||||
|
||||
case JS_TYPEREPR_ARRAY_KIND:
|
||||
var length = DESCR_ARRAY_LENGTH(descr);
|
||||
case JS_TYPEREPR_SIZED_ARRAY_KIND:
|
||||
var length = DESCR_SIZED_ARRAY_LENGTH(descr);
|
||||
if (TypedObjectSetArray(descr, length, typedObj, offset, fromValue))
|
||||
return;
|
||||
break;
|
||||
|
||||
case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
|
||||
var length = typedObj.length;
|
||||
if (TypedObjectSetArray(descr, length, typedObj, offset, fromValue))
|
||||
return;
|
||||
break;
|
||||
|
@ -418,13 +427,22 @@ function TypedArrayRedimension(newArrayType) {
|
|||
// Peel away the outermost array layers from the type of `this` to find
|
||||
// the core element type. In the process, count the number of elements.
|
||||
var oldArrayType = TypedObjectTypeDescr(this);
|
||||
var oldArrayReprKind = DESCR_KIND(oldArrayType);
|
||||
var oldElementType = oldArrayType;
|
||||
var oldElementCount = 1;
|
||||
switch (oldArrayReprKind) {
|
||||
case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
|
||||
oldElementCount *= this.length;
|
||||
oldElementType = oldElementType.elementType;
|
||||
break;
|
||||
|
||||
if (DESCR_KIND(oldArrayType) != JS_TYPEREPR_ARRAY_KIND)
|
||||
case JS_TYPEREPR_SIZED_ARRAY_KIND:
|
||||
break;
|
||||
|
||||
default:
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
|
||||
while (DESCR_KIND(oldElementType) === JS_TYPEREPR_ARRAY_KIND) {
|
||||
}
|
||||
while (DESCR_KIND(oldElementType) === JS_TYPEREPR_SIZED_ARRAY_KIND) {
|
||||
oldElementCount *= oldElementType.length;
|
||||
oldElementType = oldElementType.elementType;
|
||||
}
|
||||
|
@ -433,7 +451,7 @@ function TypedArrayRedimension(newArrayType) {
|
|||
// process, count the number of elements.
|
||||
var newElementType = newArrayType;
|
||||
var newElementCount = 1;
|
||||
while (DESCR_KIND(newElementType) == JS_TYPEREPR_ARRAY_KIND) {
|
||||
while (DESCR_KIND(newElementType) == JS_TYPEREPR_SIZED_ARRAY_KIND) {
|
||||
newElementCount *= newElementType.length;
|
||||
newElementType = newElementType.elementType;
|
||||
}
|
||||
|
@ -518,11 +536,11 @@ function ArrayShorthand(...dims) {
|
|||
var T = GetTypedObjectModule();
|
||||
|
||||
if (dims.length == 0)
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return new T.ArrayType(this);
|
||||
|
||||
var accum = this;
|
||||
for (var i = dims.length - 1; i >= 0; i--)
|
||||
accum = new T.ArrayType(accum, dims[i]);
|
||||
accum = new T.ArrayType(accum).dimension(dims[i]);
|
||||
return accum;
|
||||
}
|
||||
|
||||
|
@ -542,7 +560,11 @@ function StorageOfTypedObject(obj) {
|
|||
ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED);
|
||||
|
||||
var descr = TypedObjectTypeDescr(obj);
|
||||
var byteLength = DESCR_SIZE(descr);
|
||||
var byteLength;
|
||||
if (DESCR_KIND(descr) == JS_TYPEREPR_UNSIZED_ARRAY_KIND)
|
||||
byteLength = DESCR_SIZE(descr.elementType) * obj.length;
|
||||
else
|
||||
byteLength = DESCR_SIZE(descr);
|
||||
|
||||
return { buffer: TypedObjectBuffer(obj),
|
||||
byteLength: byteLength,
|
||||
|
@ -583,13 +605,14 @@ function TypeOfTypedObject(obj) {
|
|||
|
||||
// Warning: user exposed!
|
||||
function TypedObjectArrayTypeBuild(a,b,c) {
|
||||
// Arguments : [depth], func
|
||||
// Arguments (this sized) : [depth], func
|
||||
// Arguments (this unsized) : length, [depth], func
|
||||
|
||||
if (!IsObject(this) || !ObjectIsTypeDescr(this))
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
var kind = DESCR_KIND(this);
|
||||
switch (kind) {
|
||||
case JS_TYPEREPR_ARRAY_KIND:
|
||||
case JS_TYPEREPR_SIZED_ARRAY_KIND:
|
||||
if (typeof a === "function") // XXX here and elsewhere: these type dispatches are fragile at best.
|
||||
return BuildTypedSeqImpl(this, this.length, 1, a);
|
||||
else if (typeof a === "number" && typeof b === "function")
|
||||
|
@ -598,6 +621,16 @@ function TypedObjectArrayTypeBuild(a,b,c) {
|
|||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
else
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
|
||||
var len = a;
|
||||
if (typeof b === "function")
|
||||
return BuildTypedSeqImpl(this, len, 1, b);
|
||||
else if (typeof b === "number" && typeof c === "function")
|
||||
return BuildTypedSeqImpl(this, len, b, c);
|
||||
else if (typeof b === "number")
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
else
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
default:
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
}
|
||||
|
@ -698,7 +731,7 @@ function TypedArrayScatter(a, b, c, d) {
|
|||
if (!TypeDescrIsArrayType(thisType))
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
|
||||
if (!IsObject(a) || !ObjectIsTypeDescr(a) || !TypeDescrIsArrayType(a))
|
||||
if (!IsObject(a) || !ObjectIsTypeDescr(a) || !TypeDescrIsSizedArrayType(a))
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
|
||||
if (d !== undefined && typeof d !== "function")
|
||||
|
@ -795,7 +828,7 @@ function BuildTypedSeqImpl(arrayType, len, depth, func) {
|
|||
ComputeIterationSpace(arrayType, depth, len);
|
||||
|
||||
// Create a zeroed instance with no data
|
||||
var result = new arrayType();
|
||||
var result = arrayType.variable ? new arrayType(len) : new arrayType();
|
||||
|
||||
var indices = NewDenseArray(depth);
|
||||
for (var i = 0; i < depth; i++) {
|
||||
|
@ -888,11 +921,11 @@ function MapUntypedSeqImpl(inArray, outputType, maybeFunc) {
|
|||
// Skip check for compatible iteration spaces; any normal JS array
|
||||
// is trivially compatible with any iteration space of depth 1.
|
||||
|
||||
var outLength = outputType.length;
|
||||
var outLength = outputType.variable ? inArray.length : outputType.length;
|
||||
var outGrainType = outputType.elementType;
|
||||
|
||||
// Create a zeroed instance with no data
|
||||
var result = new outputType();
|
||||
var result = outputType.variable ? new outputType(inArray.length) : new outputType();
|
||||
|
||||
var outUnitSize = DESCR_SIZE(outGrainType);
|
||||
var outGrainTypeIsComplex = !TypeDescrIsSimpleType(outGrainType);
|
||||
|
@ -942,14 +975,14 @@ function MapTypedSeqImpl(inArray, depth, outputType, func) {
|
|||
if (!IsObject(inGrainType) || !ObjectIsTypeDescr(inGrainType))
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
var [iterationSpace, outGrainType, totalLength] =
|
||||
ComputeIterationSpace(outputType, depth, outputType.length);
|
||||
ComputeIterationSpace(outputType, depth, outputType.variable ? inArray.length : outputType.length);
|
||||
for (var i = 0; i < depth; i++)
|
||||
if (inIterationSpace[i] !== iterationSpace[i])
|
||||
// TypeError("Incompatible iteration space in input and output type");
|
||||
ThrowError(JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
|
||||
|
||||
// Create a zeroed instance with no data
|
||||
var result = new outputType();
|
||||
var result = outputType.variable ? new outputType(inArray.length) : new outputType();
|
||||
|
||||
var inGrainTypeIsComplex = !TypeDescrIsSimpleType(inGrainType);
|
||||
var outGrainTypeIsComplex = !TypeDescrIsSimpleType(outGrainType);
|
||||
|
@ -1050,7 +1083,7 @@ function MapTypedParImpl(inArray, depth, outputType, func) {
|
|||
depth <= 0 ||
|
||||
TO_INT32(depth) !== depth ||
|
||||
!TypeDescrIsArrayType(inArrayType) ||
|
||||
!TypeDescrIsArrayType(outputType))
|
||||
!TypeDescrIsUnsizedArrayType(outputType))
|
||||
{
|
||||
// defer error cases to seq implementation:
|
||||
return MapTypedSeqImpl(inArray, depth, outputType, func);
|
||||
|
@ -1128,7 +1161,7 @@ function MapTypedParImplDepth1(inArray, inArrayType, outArrayType, func) {
|
|||
const length = inArray.length;
|
||||
const mode = undefined;
|
||||
|
||||
const outArray = new outArrayType();
|
||||
const outArray = new outArrayType(length);
|
||||
if (length === 0)
|
||||
return outArray;
|
||||
|
||||
|
@ -1274,7 +1307,7 @@ function ReduceTypedSeqImpl(array, outputType, func, initial) {
|
|||
function ScatterTypedSeqImpl(array, outputType, indices, defaultValue, conflictFunc) {
|
||||
assert(IsObject(array) && ObjectIsTypedObject(array), "Scatter called on non-object or untyped input array.");
|
||||
assert(IsObject(outputType) && ObjectIsTypeDescr(outputType), "Scatter called on non-type-object outputType");
|
||||
assert(TypeDescrIsArrayType(outputType), "Scatter called on non-array type");
|
||||
assert(TypeDescrIsSizedArrayType(outputType), "Scatter called on non-sized array type");
|
||||
assert(conflictFunc === undefined || typeof conflictFunc === "function", "Scatter called with invalid conflictFunc");
|
||||
|
||||
var result = new outputType();
|
||||
|
@ -1323,10 +1356,8 @@ function FilterTypedSeqImpl(array, func) {
|
|||
inOffset += size;
|
||||
}
|
||||
|
||||
var T = GetTypedObjectModule();
|
||||
|
||||
var resultType = new T.ArrayType(elementType, count);
|
||||
var result = new resultType();
|
||||
var resultType = (arrayType.variable ? arrayType : arrayType.unsized);
|
||||
var result = new resultType(count);
|
||||
for (var i = 0, j = 0; i < array.length; i++) {
|
||||
if (GET_BIT(flags, i))
|
||||
result[j++] = array[i];
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define JS_DESCR_SLOT_KIND 0 // Atomized string representation
|
||||
#define JS_DESCR_SLOT_STRING_REPR 1 // Atomized string representation
|
||||
#define JS_DESCR_SLOT_ALIGNMENT 2 // Alignment in bytes
|
||||
#define JS_DESCR_SLOT_SIZE 3 // Size in bytes, else 0
|
||||
#define JS_DESCR_SLOT_SIZE 3 // Size in bytes, if sized, else 0
|
||||
#define JS_DESCR_SLOT_OPAQUE 4 // Atomized string representation
|
||||
#define JS_DESCR_SLOT_TYPROTO 5 // Prototype for instances, if any
|
||||
|
||||
|
@ -37,8 +37,8 @@
|
|||
// Slots on all array descriptors
|
||||
#define JS_DESCR_SLOT_ARRAY_ELEM_TYPE 6
|
||||
|
||||
// Slots on array descriptors
|
||||
#define JS_DESCR_SLOT_ARRAY_LENGTH 7
|
||||
// Slots on sized array descriptors
|
||||
#define JS_DESCR_SLOT_SIZED_ARRAY_LENGTH 7
|
||||
|
||||
// Slots on struct type objects
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_NAMES 6
|
||||
|
@ -51,10 +51,12 @@
|
|||
// These constants are for use exclusively in JS code. In C++ code,
|
||||
// prefer TypeRepresentation::Scalar etc, which allows you to
|
||||
// write a switch which will receive a warning if you omit a case.
|
||||
#define JS_TYPEREPR_UNSIZED_ARRAY_KIND 0
|
||||
#define JS_TYPEREPR_MAX_UNSIZED_KIND 0 // Unsized kinds go above here
|
||||
#define JS_TYPEREPR_SCALAR_KIND 1
|
||||
#define JS_TYPEREPR_REFERENCE_KIND 2
|
||||
#define JS_TYPEREPR_STRUCT_KIND 3
|
||||
#define JS_TYPEREPR_ARRAY_KIND 4
|
||||
#define JS_TYPEREPR_SIZED_ARRAY_KIND 4
|
||||
#define JS_TYPEREPR_SIMD_KIND 5
|
||||
|
||||
// These constants are for use exclusively in JS code. In C++ code,
|
||||
|
|
|
@ -404,9 +404,11 @@ GetObjectAllocKindForCopy(const Nursery &nursery, JSObject *obj)
|
|||
return InlineTypedObject::allocKindForTypeDescriptor(descr);
|
||||
}
|
||||
|
||||
// Outline typed objects use the minimum allocation kind.
|
||||
if (obj->is<OutlineTypedObject>())
|
||||
return FINALIZE_OBJECT0;
|
||||
// Outline typed objects have special requirements for their allocation kind.
|
||||
if (obj->is<OutlineTypedObject>()) {
|
||||
TypeDescr *descr = &obj->as<OutlineTypedObject>().typeDescr();
|
||||
return OutlineTypedObject::allocKindForTypeDescriptor(descr);
|
||||
}
|
||||
|
||||
// The only non-native objects in existence are proxies and typed objects.
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
// Fuzz bug 981650: Test creating an array type based on an instance of
|
||||
// Fuzz bug 981650: Test creating an unsized array type based on an instance of
|
||||
// that same type.
|
||||
|
||||
if (typeof TypedObject === "undefined")
|
||||
quit();
|
||||
|
||||
var T = TypedObject;
|
||||
var v = new T.ArrayType(T.int32, 10);
|
||||
new v(v);
|
||||
var AT = new T.ArrayType(T.int32);
|
||||
var v = new AT(10);
|
||||
new AT(v);
|
||||
|
|
|
@ -9,14 +9,14 @@ load(libdir + "asserts.js")
|
|||
var {StructType, uint32, Object, Any, storage, objectType} = TypedObject;
|
||||
|
||||
function main(variant) { // once a C programmer, always a C programmer.
|
||||
var Uints = uint32.array(0);
|
||||
var Uints = uint32.array();
|
||||
var Unit = new StructType({}); // Empty struct type
|
||||
var buffer = new ArrayBuffer(0); // Empty buffer
|
||||
var p = new Unit(buffer); // OK
|
||||
neuter(buffer, variant);
|
||||
assertThrowsInstanceOf(() => new Unit(buffer), TypeError,
|
||||
"Able to instantiate atop neutered buffer");
|
||||
assertThrowsInstanceOf(() => new Uints(buffer), TypeError,
|
||||
assertThrowsInstanceOf(() => new Uints(buffer, 0), TypeError,
|
||||
"Able to instantiate atop neutered buffer");
|
||||
}
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ if (!this.hasOwnProperty("TypedObject"))
|
|||
var N = 100;
|
||||
var T = TypedObject;
|
||||
var Point = new T.StructType({x: T.uint32, y: T.uint32, z: T.uint32});
|
||||
var PointArray = Point.array(N);
|
||||
var PointArray = Point.array();
|
||||
function foo(arr) {
|
||||
var sum = 0;
|
||||
for (var i = 0; i < N; i++) {
|
||||
sum += arr[i].x + arr[i].y + arr[i].z;
|
||||
}
|
||||
}
|
||||
foo(new PointArray());
|
||||
foo(new PointArray(N));
|
||||
|
|
|
@ -8,11 +8,11 @@ if (!this.hasOwnProperty("TypedObject"))
|
|||
|
||||
// bug 953111
|
||||
|
||||
var A = TypedObject.uint8.array(0);
|
||||
var a = new A();
|
||||
var A = TypedObject.uint8.array();
|
||||
var a = new A(0);
|
||||
a.forEach(function(val, i) {});
|
||||
|
||||
// bug 951356 (dup, but a dup that is more likely to crash)
|
||||
|
||||
var AA = TypedObject.uint8.array(2147483647).array(0);
|
||||
var aa = new AA();
|
||||
var AA = TypedObject.uint8.array(2147483647).array();
|
||||
var aa = new AA(0);
|
||||
|
|
|
@ -11,7 +11,7 @@ setJitCompilerOption("ion.warmup.trigger", 30);
|
|||
var N = 100;
|
||||
var T = TypedObject;
|
||||
var Point = new T.StructType({x: T.uint32, y: T.uint32, z: T.uint32});
|
||||
var PointArray = Point.array(N);
|
||||
var PointArray = Point.array();
|
||||
|
||||
function bar(array, i, x, y, z) {
|
||||
assertEq(array[i].x, x);
|
||||
|
@ -20,7 +20,7 @@ function bar(array, i, x, y, z) {
|
|||
}
|
||||
|
||||
function foo() {
|
||||
var array = new PointArray();
|
||||
var array = new PointArray(N);
|
||||
for (var i = 0; i < N; i++) {
|
||||
array[i].x = i + 0;
|
||||
array[i].y = i + 1;
|
||||
|
|
|
@ -6,14 +6,14 @@ if (!this.hasOwnProperty("TypedObject"))
|
|||
|
||||
var {StructType, uint32, storage} = TypedObject;
|
||||
var S = new StructType({f: uint32, g: uint32});
|
||||
var A = S.array(10);
|
||||
var A = S.array();
|
||||
|
||||
function readFrom(a) {
|
||||
return a[2].f + a[2].g;
|
||||
}
|
||||
|
||||
function main(variant) {
|
||||
var a = new A();
|
||||
var a = new A(10);
|
||||
a[2].f = 22;
|
||||
a[2].g = 44;
|
||||
|
||||
|
|
|
@ -14,6 +14,11 @@ var Unit = new StructType(({ f : Object, } ));
|
|||
assertThrowsInstanceOf(() => new Unit(buffer), TypeError,
|
||||
"Able to instantiate opaque type atop buffer");
|
||||
|
||||
var Units = new ArrayType(Unit, 2);
|
||||
var Units = new ArrayType(Unit);
|
||||
assertThrowsInstanceOf(() => new Units(buffer), TypeError,
|
||||
"Able to instantiate opaque type atop buffer");
|
||||
|
||||
var Units2 = Units.dimension(2);
|
||||
assertThrowsInstanceOf(() => new Units2(buffer), TypeError,
|
||||
"Able to instantiate opaque type atop buffer");
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ var uint32 = TypedObject.uint32;
|
|||
var ObjectType = TypedObject.Object;
|
||||
function runTests() {
|
||||
(function DimensionLinkedToUndimension() {
|
||||
var FiveUintsA = uint32.array(5);
|
||||
var UintsA = uint32.array();
|
||||
var FiveUintsA = UintsA.dimension(5);
|
||||
var FiveUintsB = uint32.array(5);
|
||||
assertEq(true,
|
||||
FiveUintsA.equivalent(FiveUintsB)
|
||||
|
@ -16,7 +17,7 @@ function runTests() {
|
|||
})();
|
||||
(function PrototypeHierarchy() {
|
||||
schedulegc(3);
|
||||
var Uint8s = uint8.array(5);
|
||||
var Uint8s = uint8.array();
|
||||
})();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,14 +29,14 @@ if (!this.TypedObject) {
|
|||
}
|
||||
|
||||
var T = TypedObject;
|
||||
var AT = new T.ArrayType(T.int32, 100);
|
||||
var AT = new T.ArrayType(T.int32);
|
||||
|
||||
function check(v) {
|
||||
return v.map(x => x+1);
|
||||
}
|
||||
|
||||
function test() {
|
||||
var w1 = AT.build(x => x+1);
|
||||
var w1 = AT.build(100, x => x+1);
|
||||
var w2 = Array.build(100, x => x+1);
|
||||
w2.map = w1.map;
|
||||
var a = [ w1, w2 ];
|
||||
|
|
|
@ -25,14 +25,14 @@ if (!this.TypedObject) {
|
|||
}
|
||||
|
||||
var T = TypedObject;
|
||||
var AT = new T.ArrayType(T.int32, 100);
|
||||
var AT = new T.ArrayType(T.int32);
|
||||
|
||||
function check(v) {
|
||||
return v.map(x => x+1);
|
||||
}
|
||||
|
||||
function test() {
|
||||
var w = new AT();
|
||||
var w = new AT(100);
|
||||
for ( var i=0 ; i < 1000 ; i++ )
|
||||
w = check(w);
|
||||
return w;
|
||||
|
|
|
@ -23,10 +23,10 @@ if (!this.TypedObject) {
|
|||
}
|
||||
|
||||
var T = TypedObject;
|
||||
var AT = new T.ArrayType(T.uint32, 100);
|
||||
var AT = new T.ArrayType(T.uint32);
|
||||
|
||||
function check() {
|
||||
return AT.build(x => x+1);
|
||||
return AT.build(100, x => x+1);
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
|
|
@ -21,8 +21,9 @@ if (!this.TypedObject) {
|
|||
}
|
||||
|
||||
var T = TypedObject;
|
||||
var IT = new T.ArrayType(T.int32, 100);
|
||||
var ix = IT.build(x => x == 0 ? 99 : x-1); // [99, 0, 1, ..., 98]
|
||||
var AT = new T.ArrayType(T.int32);
|
||||
var IT = AT.dimension(100);
|
||||
var ix = AT.build(100, x => x == 0 ? 99 : x-1); // [99, 0, 1, ..., 98]
|
||||
|
||||
// This is a left-rotate by one place
|
||||
function check(v) {
|
||||
|
@ -30,7 +31,7 @@ function check(v) {
|
|||
}
|
||||
|
||||
function test() {
|
||||
var w = IT.build(x => x);
|
||||
var w = AT.build(100, x => x);
|
||||
for ( var i=0 ; i < 77 ; i++ )
|
||||
w = check(w);
|
||||
return w;
|
||||
|
|
|
@ -27,7 +27,7 @@ function check(v) {
|
|||
|
||||
function test() {
|
||||
var AT = new T.ArrayType(T.Any,10);
|
||||
var v = new AT();
|
||||
var v = new AT(10);
|
||||
for ( var i=0 ; i < 1000 ; i++ )
|
||||
check(v);
|
||||
return check(v);
|
||||
|
|
|
@ -26,8 +26,8 @@ function check(v) {
|
|||
}
|
||||
|
||||
function test() {
|
||||
var AT = new T.ArrayType(T.int32, 10);
|
||||
var v = new AT();
|
||||
var AT = new T.ArrayType(T.int32,10);
|
||||
var v = new AT(10);
|
||||
for ( var i=0 ; i < 1000 ; i++ )
|
||||
check(v);
|
||||
return check(v);
|
||||
|
|
|
@ -29,7 +29,7 @@ function check(v) {
|
|||
function test() {
|
||||
var AT = new T.ArrayType(T.int32,10);
|
||||
var v = new Object; // Not actually a typed object
|
||||
var w = new AT(); // Actually a typed object
|
||||
var w = new AT(10); // Actually a typed object
|
||||
var a = [v,w];
|
||||
for ( var i=0 ; i < 1000 ; i++ )
|
||||
try { check(a[i%2]); } catch (e) {}
|
||||
|
|
|
@ -17,7 +17,7 @@ function test() {
|
|||
matrix[i][0] = i;
|
||||
|
||||
var Point = new StructType({x: uint32, y: uint32});
|
||||
var Points = Point.array(L);
|
||||
var Points = Point.array();
|
||||
|
||||
assertParallelExecSucceeds(
|
||||
// FIXME Bug 983692 -- no where to pass `m` to
|
||||
|
|
|
@ -10,7 +10,7 @@ var { uint8, uint32 } = TypedObject;
|
|||
function test() {
|
||||
var L = minItemsTestingThreshold;
|
||||
var Uints = uint32.array(L);
|
||||
var Uint8s = uint8.array(L);
|
||||
var Uint8s = uint8.array();
|
||||
|
||||
var uint32s = new Uints();
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ var { ArrayType, StructType, uint32 } = TypedObject;
|
|||
function test() {
|
||||
var L = minItemsTestingThreshold;
|
||||
var Point = new StructType({x: uint32, y: uint32});
|
||||
var Points = Point.array(L);
|
||||
var points = new Points();
|
||||
var Points = Point.array();
|
||||
var points = new Points(L);
|
||||
for (var i = 0; i < L; i++)
|
||||
points[i].x = i;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ if (!this.hasOwnProperty("TypedObject"))
|
|||
|
||||
var { ArrayType, StructType, uint32 } = TypedObject;
|
||||
var Point = new StructType({x: uint32, y: uint32});
|
||||
var Points = Point.array(0);
|
||||
var Points = Point.array();
|
||||
var points = new Points();
|
||||
points.mapPar(function() {});
|
||||
|
||||
|
|
|
@ -8593,7 +8593,7 @@ static bool
|
|||
GetTemplateObjectForClassHook(JSContext *cx, JSNative hook, CallArgs &args,
|
||||
MutableHandleObject templateObject)
|
||||
{
|
||||
if (hook == TypedObject::construct) {
|
||||
if (hook == TypedObject::constructSized) {
|
||||
Rooted<TypeDescr *> descr(cx, &args.callee().as<TypeDescr>());
|
||||
JSObject *obj = TypedObject::createZeroed(cx, descr, 1, gc::TenuredHeap);
|
||||
if (!obj)
|
||||
|
|
|
@ -5097,6 +5097,16 @@ CodeGenerator::visitTypedObjectProto(LTypedObjectProto *lir)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitTypedObjectUnsizedLength(LTypedObjectUnsizedLength *lir)
|
||||
{
|
||||
Register obj = ToRegister(lir->object());
|
||||
Register out = ToRegister(lir->output());
|
||||
|
||||
masm.load32(Address(obj, OutlineTypedObject::offsetOfUnsizedLength()), out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitTypedObjectElements(LTypedObjectElements *lir)
|
||||
{
|
||||
|
|
|
@ -186,6 +186,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitTypedObjectElements(LTypedObjectElements *lir);
|
||||
bool visitSetTypedObjectOffset(LSetTypedObjectOffset *lir);
|
||||
bool visitTypedObjectProto(LTypedObjectProto *ins);
|
||||
bool visitTypedObjectUnsizedLength(LTypedObjectUnsizedLength *ins);
|
||||
bool visitStringLength(LStringLength *lir);
|
||||
bool visitInitializedLength(LInitializedLength *lir);
|
||||
bool visitSetInitializedLength(LSetInitializedLength *lir);
|
||||
|
|
|
@ -7235,6 +7235,8 @@ IonBuilder::getElemTryTypedObject(bool *emitted, MDefinition *obj, MDefinition *
|
|||
if (elemPrediction.isUseless())
|
||||
return true;
|
||||
|
||||
MOZ_ASSERT(TypeDescr::isSized(elemPrediction.kind()));
|
||||
|
||||
int32_t elemSize;
|
||||
if (!elemPrediction.hasKnownSize(&elemSize))
|
||||
return true;
|
||||
|
@ -7245,7 +7247,7 @@ IonBuilder::getElemTryTypedObject(bool *emitted, MDefinition *obj, MDefinition *
|
|||
return true;
|
||||
|
||||
case type::Struct:
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
return getElemTryComplexElemOfTypedObject(emitted,
|
||||
obj,
|
||||
index,
|
||||
|
@ -7266,6 +7268,9 @@ IonBuilder::getElemTryTypedObject(bool *emitted, MDefinition *obj, MDefinition *
|
|||
index,
|
||||
objPrediction,
|
||||
elemPrediction);
|
||||
|
||||
case type::UnsizedArray:
|
||||
MOZ_CRASH("Unsized arrays cannot be element types");
|
||||
}
|
||||
|
||||
MOZ_CRASH("Bad kind");
|
||||
|
@ -7299,6 +7304,12 @@ IonBuilder::checkTypedObjectIndexInBounds(int32_t elemSize,
|
|||
types::TypeObjectKey *globalType = types::TypeObjectKey::get(&script()->global());
|
||||
if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED))
|
||||
return false;
|
||||
} else if (objPrediction.kind() == type::UnsizedArray) {
|
||||
// Note: unsized arrays will have their length set to zero if they are
|
||||
// neutered, so we don't need to make sure that no neutering has
|
||||
// occurred which affects this object.
|
||||
length = MTypedObjectUnsizedLength::New(alloc(), obj);
|
||||
current->add(length->toInstruction());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -8191,6 +8202,8 @@ IonBuilder::setElemTryTypedObject(bool *emitted, MDefinition *obj,
|
|||
if (elemPrediction.isUseless())
|
||||
return true;
|
||||
|
||||
MOZ_ASSERT(TypeDescr::isSized(elemPrediction.kind()));
|
||||
|
||||
int32_t elemSize;
|
||||
if (!elemPrediction.hasKnownSize(&elemSize))
|
||||
return true;
|
||||
|
@ -8214,7 +8227,8 @@ IonBuilder::setElemTryTypedObject(bool *emitted, MDefinition *obj,
|
|||
elemSize);
|
||||
|
||||
case type::Struct:
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
case type::UnsizedArray:
|
||||
// Not yet optimized.
|
||||
return true;
|
||||
}
|
||||
|
@ -8706,6 +8720,8 @@ IonBuilder::jsop_length_fastPath()
|
|||
if (prediction.hasKnownArrayLength(&sizedLength)) {
|
||||
obj->setImplicitlyUsedUnchecked();
|
||||
length = MConstant::New(alloc(), Int32Value(sizedLength));
|
||||
} else if (prediction.kind() == type::UnsizedArray) {
|
||||
length = MTypedObjectUnsizedLength::New(alloc(), obj);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -9433,7 +9449,7 @@ IonBuilder::getPropTryTypedObject(bool *emitted,
|
|||
return true;
|
||||
|
||||
case type::Struct:
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
return getPropTryComplexPropOfTypedObject(emitted,
|
||||
obj,
|
||||
fieldOffset,
|
||||
|
@ -9454,6 +9470,9 @@ IonBuilder::getPropTryTypedObject(bool *emitted,
|
|||
fieldOffset,
|
||||
fieldPrediction,
|
||||
resultTypes);
|
||||
|
||||
case type::UnsizedArray:
|
||||
MOZ_CRASH("Field of unsized array type");
|
||||
}
|
||||
|
||||
MOZ_CRASH("Bad kind");
|
||||
|
@ -10147,7 +10166,8 @@ IonBuilder::setPropTryTypedObject(bool *emitted, MDefinition *obj,
|
|||
value, fieldPrediction);
|
||||
|
||||
case type::Struct:
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
case type::UnsizedArray:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -777,7 +777,7 @@ class IonBuilder
|
|||
InliningStatus inlineSetTypedObjectOffset(CallInfo &callInfo);
|
||||
bool elementAccessIsTypedObjectArrayOfScalarType(MDefinition* obj, MDefinition* id,
|
||||
ScalarTypeDescr::Type *arrayType);
|
||||
InliningStatus inlineConstructTypedObject(CallInfo &callInfo, TypeDescr *target);
|
||||
InliningStatus inlineConstructTypedObject(CallInfo &callInfo, SizedTypeDescr *target);
|
||||
|
||||
// Utility intrinsics.
|
||||
InliningStatus inlineIsCallable(CallInfo &callInfo);
|
||||
|
|
|
@ -4231,6 +4231,20 @@ class LTypedObjectProto : public LCallInstructionHelper<1, 1, 1>
|
|||
}
|
||||
};
|
||||
|
||||
// Load an unsized typed object's length.
|
||||
class LTypedObjectUnsizedLength : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(TypedObjectUnsizedLength)
|
||||
|
||||
explicit LTypedObjectUnsizedLength(const LAllocation &object) {
|
||||
setOperand(0, object);
|
||||
}
|
||||
const LAllocation *object() {
|
||||
return getOperand(0);
|
||||
}
|
||||
};
|
||||
|
||||
// Load a typed object's elements vector.
|
||||
class LTypedObjectElements : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
|
|
|
@ -284,6 +284,7 @@
|
|||
_(TypedArrayLength) \
|
||||
_(TypedArrayElements) \
|
||||
_(TypedObjectProto) \
|
||||
_(TypedObjectUnsizedLength) \
|
||||
_(TypedObjectElements) \
|
||||
_(SetTypedObjectOffset) \
|
||||
_(StringLength) \
|
||||
|
|
|
@ -2522,6 +2522,13 @@ LIRGenerator::visitTypedObjectProto(MTypedObjectProto *ins)
|
|||
ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitTypedObjectUnsizedLength(MTypedObjectUnsizedLength *ins)
|
||||
{
|
||||
MOZ_ASSERT(ins->type() == MIRType_Int32);
|
||||
return define(new(alloc()) LTypedObjectUnsizedLength(useRegisterAtStart(ins->object())), ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitTypedObjectElements(MTypedObjectElements *ins)
|
||||
{
|
||||
|
|
|
@ -192,6 +192,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
bool visitTypedObjectElements(MTypedObjectElements *ins);
|
||||
bool visitSetTypedObjectOffset(MSetTypedObjectOffset *ins);
|
||||
bool visitTypedObjectProto(MTypedObjectProto *ins);
|
||||
bool visitTypedObjectUnsizedLength(MTypedObjectUnsizedLength *ins);
|
||||
bool visitInitializedLength(MInitializedLength *ins);
|
||||
bool visitSetInitializedLength(MSetInitializedLength *ins);
|
||||
bool visitNot(MNot *ins);
|
||||
|
|
|
@ -219,7 +219,12 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSFunction *target)
|
|||
return inlineHasClass(callInfo,
|
||||
&ScalarTypeDescr::class_, &ReferenceTypeDescr::class_);
|
||||
if (native == intrinsic_TypeDescrIsArrayType)
|
||||
return inlineHasClass(callInfo, &ArrayTypeDescr::class_);
|
||||
return inlineHasClass(callInfo,
|
||||
&SizedArrayTypeDescr::class_, &UnsizedArrayTypeDescr::class_);
|
||||
if (native == intrinsic_TypeDescrIsSizedArrayType)
|
||||
return inlineHasClass(callInfo, &SizedArrayTypeDescr::class_);
|
||||
if (native == intrinsic_TypeDescrIsUnsizedArrayType)
|
||||
return inlineHasClass(callInfo, &UnsizedArrayTypeDescr::class_);
|
||||
if (native == intrinsic_SetTypedObjectOffset)
|
||||
return inlineSetTypedObjectOffset(callInfo);
|
||||
|
||||
|
@ -281,8 +286,8 @@ IonBuilder::inlineNonFunctionCall(CallInfo &callInfo, JSObject *target)
|
|||
// Inline a call to a non-function object, invoking the object's call or
|
||||
// construct hook.
|
||||
|
||||
if (callInfo.constructing() && target->constructHook() == TypedObject::construct)
|
||||
return inlineConstructTypedObject(callInfo, &target->as<TypeDescr>());
|
||||
if (callInfo.constructing() && target->constructHook() == TypedObject::constructSized)
|
||||
return inlineConstructTypedObject(callInfo, &target->as<SizedTypeDescr>());
|
||||
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
@ -1647,6 +1652,7 @@ IonBuilder::elementAccessIsTypedObjectArrayOfScalarType(MDefinition* obj, MDefin
|
|||
if (elemPrediction.isUseless() || elemPrediction.kind() != type::Scalar)
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(type::isSized(elemPrediction.kind()));
|
||||
*arrayType = elemPrediction.scalarType();
|
||||
return true;
|
||||
}
|
||||
|
@ -2513,7 +2519,7 @@ IonBuilder::inlineIsConstructing(CallInfo &callInfo)
|
|||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineConstructTypedObject(CallInfo &callInfo, TypeDescr *descr)
|
||||
IonBuilder::inlineConstructTypedObject(CallInfo &callInfo, SizedTypeDescr *descr)
|
||||
{
|
||||
// Only inline default constructors for now.
|
||||
if (callInfo.argc() != 0)
|
||||
|
|
|
@ -2807,6 +2807,36 @@ class MTypedObjectProto
|
|||
}
|
||||
};
|
||||
|
||||
class MTypedObjectUnsizedLength
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy::Data
|
||||
{
|
||||
private:
|
||||
explicit MTypedObjectUnsizedLength(MDefinition *object)
|
||||
: MUnaryInstruction(object)
|
||||
{
|
||||
setResultType(MIRType_Int32);
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(TypedObjectUnsizedLength)
|
||||
|
||||
static MTypedObjectUnsizedLength *New(TempAllocator &alloc, MDefinition *object) {
|
||||
return new(alloc) MTypedObjectUnsizedLength(object);
|
||||
}
|
||||
|
||||
MDefinition *object() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
bool congruentTo(const MDefinition *ins) const {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
};
|
||||
|
||||
// Creates a new derived type object. At runtime, this is just a call
|
||||
// to `BinaryBlock::createDerived()`. That is, the MIR itself does not
|
||||
// compile to particularly optimized code. However, using a distinct
|
||||
|
|
|
@ -163,6 +163,7 @@ namespace jit {
|
|||
_(TypedArrayLength) \
|
||||
_(TypedArrayElements) \
|
||||
_(TypedObjectProto) \
|
||||
_(TypedObjectUnsizedLength) \
|
||||
_(TypedObjectElements) \
|
||||
_(SetTypedObjectOffset) \
|
||||
_(InitializedLength) \
|
||||
|
|
|
@ -249,6 +249,7 @@ class ParallelSafetyVisitor : public MDefinitionVisitor
|
|||
SAFE_OP(TypedArrayLength)
|
||||
SAFE_OP(TypedArrayElements)
|
||||
SAFE_OP(TypedObjectProto)
|
||||
SAFE_OP(TypedObjectUnsizedLength)
|
||||
SAFE_OP(TypedObjectElements)
|
||||
SAFE_OP(SetTypedObjectOffset)
|
||||
SAFE_OP(InitializedLength)
|
||||
|
|
|
@ -1113,7 +1113,7 @@ RNewDerivedTypedObject::RNewDerivedTypedObject(CompactBufferReader &reader)
|
|||
bool
|
||||
RNewDerivedTypedObject::recover(JSContext *cx, SnapshotIterator &iter) const
|
||||
{
|
||||
Rooted<TypeDescr *> descr(cx, &iter.read().toObject().as<TypeDescr>());
|
||||
Rooted<SizedTypeDescr *> descr(cx, &iter.read().toObject().as<SizedTypeDescr>());
|
||||
Rooted<TypedObject *> owner(cx, &iter.read().toObject().as<TypedObject>());
|
||||
int32_t offset = iter.read().toInt32();
|
||||
|
||||
|
|
|
@ -123,13 +123,24 @@ TypedObjectPrediction::ofArrayKind() const
|
|||
case type::Struct:
|
||||
return false;
|
||||
|
||||
case type::Array:
|
||||
case type::SizedArray:
|
||||
case type::UnsizedArray:
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_CRASH("Bad kind");
|
||||
}
|
||||
|
||||
static bool
|
||||
DescrHasKnownSize(const TypeDescr &descr, int32_t *out)
|
||||
{
|
||||
if (!descr.is<SizedTypeDescr>())
|
||||
return false;
|
||||
|
||||
*out = descr.as<SizedTypeDescr>().size();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TypedObjectPrediction::hasKnownSize(int32_t *out) const
|
||||
{
|
||||
|
@ -139,8 +150,7 @@ TypedObjectPrediction::hasKnownSize(int32_t *out) const
|
|||
break;
|
||||
|
||||
case TypedObjectPrediction::Descr:
|
||||
*out = descr().size();
|
||||
return true;
|
||||
return DescrHasKnownSize(descr(), out);
|
||||
|
||||
case TypedObjectPrediction::Prefix:
|
||||
// We only know a prefix of the struct fields, hence we do not
|
||||
|
@ -223,8 +233,8 @@ TypedObjectPrediction::hasKnownArrayLength(int32_t *length) const
|
|||
case TypedObjectPrediction::Descr:
|
||||
// In later patches, this condition will always be true
|
||||
// so long as this represents an array
|
||||
if (descr().is<ArrayTypeDescr>()) {
|
||||
*length = descr().as<ArrayTypeDescr>().length();
|
||||
if (descr().is<SizedArrayTypeDescr>()) {
|
||||
*length = descr().as<SizedArrayTypeDescr>().length();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -235,6 +245,13 @@ TypedObjectPrediction::hasKnownArrayLength(int32_t *length) const
|
|||
MOZ_CRASH("Bad prediction kind");
|
||||
}
|
||||
|
||||
static TypeDescr &
|
||||
DescrArrayElementType(const TypeDescr &descr) {
|
||||
return (descr.is<SizedArrayTypeDescr>()
|
||||
? descr.as<SizedArrayTypeDescr>().elementType()
|
||||
: descr.as<UnsizedArrayTypeDescr>().elementType());
|
||||
}
|
||||
|
||||
TypedObjectPrediction
|
||||
TypedObjectPrediction::arrayElementType() const
|
||||
{
|
||||
|
@ -245,7 +262,7 @@ TypedObjectPrediction::arrayElementType() const
|
|||
break;
|
||||
|
||||
case TypedObjectPrediction::Descr:
|
||||
return TypedObjectPrediction(descr().as<ArrayTypeDescr>().elementType());
|
||||
return TypedObjectPrediction(DescrArrayElementType(descr()));
|
||||
|
||||
case TypedObjectPrediction::Prefix:
|
||||
break; // Prefixes are always structs, never arrays
|
||||
|
|
|
@ -1014,9 +1014,9 @@ JSObject *
|
|||
CreateDerivedTypedObj(JSContext *cx, HandleObject descr,
|
||||
HandleObject owner, int32_t offset)
|
||||
{
|
||||
MOZ_ASSERT(descr->is<TypeDescr>());
|
||||
MOZ_ASSERT(descr->is<SizedTypeDescr>());
|
||||
MOZ_ASSERT(owner->is<TypedObject>());
|
||||
Rooted<TypeDescr*> descr1(cx, &descr->as<TypeDescr>());
|
||||
Rooted<SizedTypeDescr*> descr1(cx, &descr->as<SizedTypeDescr>());
|
||||
Rooted<TypedObject*> owner1(cx, &owner->as<TypedObject>());
|
||||
return OutlineTypedObject::createDerived(cx, descr1, owner1, offset);
|
||||
}
|
||||
|
|
|
@ -996,6 +996,8 @@ bool intrinsic_ObjectIsOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp
|
|||
bool intrinsic_ObjectIsTypeDescr(JSContext *cx, unsigned argc, Value *vp);
|
||||
bool intrinsic_TypeDescrIsSimpleType(JSContext *cx, unsigned argc, Value *vp);
|
||||
bool intrinsic_TypeDescrIsArrayType(JSContext *cx, unsigned argc, Value *vp);
|
||||
bool intrinsic_TypeDescrIsUnsizedArrayType(JSContext *cx, unsigned argc, Value *vp);
|
||||
bool intrinsic_TypeDescrIsSizedArrayType(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
class AutoLockForExclusiveAccess
|
||||
{
|
||||
|
|
|
@ -7,9 +7,9 @@ var StructType = TypedObject.StructType;
|
|||
var float32 = TypedObject.float32;
|
||||
|
||||
function runTests() {
|
||||
var Point = new ArrayType(float32, 3);
|
||||
var Point = new ArrayType(float32).dimension(3);
|
||||
var Line = new StructType({from: Point, to: Point});
|
||||
var Lines = new ArrayType(Line, 3);
|
||||
var Lines = new ArrayType(Line).dimension(3);
|
||||
|
||||
var lines = new Lines([
|
||||
{from: [1, 2, 3], to: [4, 5, 6]},
|
||||
|
|
|
@ -28,14 +28,14 @@ function runTests() {
|
|||
assertThrows(function() new ArrayType(""));
|
||||
assertThrows(function() new ArrayType(5));
|
||||
assertThrows(function() new ArrayType(uint8).dimension(-1));
|
||||
var A = new ArrayType(uint8, 10);
|
||||
//assertEq(A.__proto__.__proto__, ArrayType.prototype);
|
||||
var A = new ArrayType(uint8).dimension(10);
|
||||
assertEq(A.__proto__.__proto__, ArrayType.prototype);
|
||||
assertEq(A.length, 10);
|
||||
assertEq(A.elementType, uint8);
|
||||
assertEq(A.byteLength, 10);
|
||||
assertEq(A.toSource(), "new ArrayType(uint8, 10)");
|
||||
assertEq(A.toSource(), "new ArrayType(uint8).dimension(10)");
|
||||
|
||||
//assertEq(A.prototype.__proto__.__proto__, ArrayType.prototype.prototype);
|
||||
assertEq(A.prototype.__proto__.__proto__, ArrayType.prototype.prototype);
|
||||
|
||||
var a = new A();
|
||||
assertEq(a.__proto__, A.prototype);
|
||||
|
@ -74,8 +74,8 @@ function runTests() {
|
|||
// Length different
|
||||
assertThrows(function() new A([0, 1, 0, 1, 0, 1, 0, 1, 0]));
|
||||
|
||||
var Vec3 = new ArrayType(float32, 3);
|
||||
var Sprite = new ArrayType(Vec3, 3); // say for position, velocity, and direction
|
||||
var Vec3 = new ArrayType(float32).dimension(3);
|
||||
var Sprite = new ArrayType(Vec3).dimension(3); // say for position, velocity, and direction
|
||||
assertEq(Sprite.elementType, Vec3);
|
||||
assertEq(Sprite.elementType.elementType, float32);
|
||||
|
||||
|
@ -96,7 +96,7 @@ function runTests() {
|
|||
assertEq(Number.isNaN(mario[1][1]), true);
|
||||
|
||||
// ok this is just for kicks
|
||||
var AllSprites = new ArrayType(Sprite, 65536);
|
||||
var AllSprites = new ArrayType(Sprite).dimension(65536);
|
||||
var as = new AllSprites();
|
||||
assertEq(as.length, 65536);
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var BUGNUMBER = 922115;
|
||||
var summary = 'check we cannot create handles to unsized arrays';
|
||||
|
||||
var T = TypedObject;
|
||||
|
||||
function runTests() {
|
||||
var Line = new T.StructType({from: T.uint8, to: T.uint8});
|
||||
var Lines = Line.array();
|
||||
assertThrowsInstanceOf(function() Lines.handle(), TypeError,
|
||||
"was able to create handle to unsized array");
|
||||
|
||||
reportCompare(true, true);
|
||||
print("Tests complete");
|
||||
}
|
||||
|
||||
runTests();
|
||||
|
||||
|
|
@ -21,14 +21,31 @@ var float64 = TypedObject.float64;
|
|||
|
||||
var objectType = TypedObject.objectType;
|
||||
|
||||
function filterOdds() {
|
||||
function filterOddsFromVariable() {
|
||||
var length = 100;
|
||||
var Uint32s = new ArrayType(uint32, 100);
|
||||
var Uint32s = uint32.array();
|
||||
var uint32s = new Uint32s(100);
|
||||
for (var i = 0; i < length; i++)
|
||||
uint32s[i] = i;
|
||||
|
||||
var odds = uint32s.filter(i => (i % 2) != 0);
|
||||
assertEq(true, objectType(odds) == Uint32s);
|
||||
assertEq(true, Uint32s.variable);
|
||||
assertEq(50, odds.length);
|
||||
for (var i = 0, j = 1; j < length; i++, j += 2)
|
||||
assertEq(odds[i], j);
|
||||
}
|
||||
|
||||
function filterOddsFromSized() {
|
||||
var length = 100;
|
||||
var Uint32s = uint32.array(100);
|
||||
var uint32s = new Uint32s();
|
||||
for (var i = 0; i < length; i++)
|
||||
uint32s[i] = i;
|
||||
|
||||
var odds = uint32s.filter(i => (i % 2) != 0);
|
||||
assertEq(true, objectType(odds) == Uint32s.unsized);
|
||||
assertEq(true, objectType(odds).variable);
|
||||
assertEq(50, odds.length);
|
||||
for (var i = 0, j = 1; j < length; i++, j += 2)
|
||||
assertEq(odds[i], j);
|
||||
|
@ -37,7 +54,8 @@ function filterOdds() {
|
|||
function runTests() {
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
filterOdds();
|
||||
filterOddsFromVariable();
|
||||
filterOddsFromSized();
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
|
|
@ -27,7 +27,7 @@ function TestValues(type, values) {
|
|||
compare(struct.f, values[i]);
|
||||
}
|
||||
|
||||
var Array = new ArrayType(type, 1);
|
||||
var Array = new ArrayType(type).dimension(1);
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var array = new Array();
|
||||
array[0] = values[i].input;
|
||||
|
|
|
@ -39,7 +39,16 @@ function TestStructFields(RefType) {
|
|||
|
||||
function TestArrayElements(RefType) {
|
||||
var rabbit = {};
|
||||
var S1 = new ArrayType(RefType, 1);
|
||||
var S1 = new ArrayType(RefType).dimension(1);
|
||||
var s1 = new S1([rabbit]);
|
||||
assertCanReach(s1, rabbit);
|
||||
s1[0] = null;
|
||||
assertCannotReach(s1, rabbit);
|
||||
}
|
||||
|
||||
function TestUnsizedArrayElements(RefType) {
|
||||
var rabbit = {};
|
||||
var S1 = new ArrayType(RefType);
|
||||
var s1 = new S1([rabbit]);
|
||||
assertCanReach(s1, rabbit);
|
||||
s1[0] = null;
|
||||
|
@ -49,7 +58,7 @@ function TestArrayElements(RefType) {
|
|||
function TestStructInArray(RefType) {
|
||||
var rabbit = {};
|
||||
var S2 = new StructType({f: RefType, g: RefType});
|
||||
var S1 = new ArrayType(S2, 1);
|
||||
var S1 = new ArrayType(S2).dimension(1);
|
||||
var s1 = new S1([{f: rabbit, g: {}}]);
|
||||
assertCanReach(s1, rabbit);
|
||||
s1[0].f = null;
|
||||
|
@ -82,6 +91,9 @@ function runTests()
|
|||
TestArrayElements(Object);
|
||||
TestArrayElements(Any);
|
||||
|
||||
TestUnsizedArrayElements(Object);
|
||||
TestUnsizedArrayElements(Any);
|
||||
|
||||
TestStructInArray(Object);
|
||||
TestStructInArray(Any);
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ function runTests() {
|
|||
|
||||
{type: new StructType({a: uint8, b: uint8, c: uint16}), size: 4, alignment: 2},
|
||||
|
||||
{type: new ArrayType(uint8, 32), size: 32, alignment: 1},
|
||||
{type: new ArrayType(uint16, 16), size: 32, alignment: 2},
|
||||
{type: new ArrayType(uint32, 8), size: 32, alignment: 4},
|
||||
{type: new ArrayType(uint8).dimension(32), size: 32, alignment: 1},
|
||||
{type: new ArrayType(uint16).dimension(16), size: 32, alignment: 2},
|
||||
{type: new ArrayType(uint32).dimension(8), size: 32, alignment: 4},
|
||||
];
|
||||
|
||||
for (var i = 0; i < typesAndAlignments.length; i++) {
|
||||
|
|
|
@ -21,6 +21,7 @@ function runTests() {
|
|||
assertEq(S.__proto__, StructType.prototype);
|
||||
assertEq(S.prototype.__proto__, StructType.prototype.prototype);
|
||||
assertEq(S.toSource(), "new StructType({x: int32, y: uint8, z: float64})");
|
||||
assertEq(S.variable, false);
|
||||
assertEq(S.byteLength, 16);
|
||||
assertEq(S.byteAlignment, 8);
|
||||
var fieldNames = Object.getOwnPropertyNames(S.fieldTypes);
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
|
||||
var BUGNUMBER = 922115;
|
||||
var summary = 'TypedObjects ArrayType implementation';
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var { ArrayType, StructType, uint8, float32, uint32 } = TypedObject;
|
||||
var ObjectType = TypedObject.Object;
|
||||
|
||||
function runTests() {
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
(function SimpleArrayOfTwoObjects() {
|
||||
print("SimpleArrayOfTwoObjects");
|
||||
var Objects = new ArrayType(ObjectType);
|
||||
var objects2 = new Objects([{f: "Hello"},
|
||||
{f: "World"}]);
|
||||
assertEq(objects2[0].f, "Hello");
|
||||
assertEq(objects2[1].f, "World");
|
||||
assertEq(objects2.length, 2);
|
||||
})();
|
||||
|
||||
(function EmbedUnsizedArraysBad() {
|
||||
print("EmbedUnsizedArraysBad");
|
||||
var Objects = new ArrayType(ObjectType);
|
||||
assertThrows(() => new ArrayType(Objects));
|
||||
assertThrows(() => new StructType({f: Objects}));
|
||||
})();
|
||||
|
||||
(function MultipleSizes() {
|
||||
print("MultipleSizes");
|
||||
var Uints = new ArrayType(uint32);
|
||||
var Point = new StructType({values: new ArrayType(uint32).dimension(3)});
|
||||
|
||||
var uints = new Uints([0, 1, 2]);
|
||||
var point = new Point({values: uints});
|
||||
|
||||
assertEq(uints.length, point.values.length);
|
||||
for (var i = 0; i < uints.length; i++) {
|
||||
assertEq(uints[i], i);
|
||||
assertEq(uints[i], point.values[i]);
|
||||
}
|
||||
})();
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
print("Tests complete");
|
||||
}
|
||||
|
||||
runTests();
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
|
||||
var BUGNUMBER = 922115;
|
||||
var summary = 'TypedObjects ArrayType implementation';
|
||||
|
||||
var ArrayType = TypedObject.ArrayType;
|
||||
var StructType = TypedObject.StructType;
|
||||
var uint8 = TypedObject.uint8;
|
||||
var float32 = TypedObject.float32;
|
||||
var uint32 = TypedObject.uint32;
|
||||
var ObjectType = TypedObject.Object;
|
||||
|
||||
function runTests() {
|
||||
(function DimensionLinkedToUndimension() {
|
||||
var UintsA = uint32.array();
|
||||
var FiveUintsA = UintsA.dimension(5);
|
||||
var FiveUintsB = uint32.array(5);
|
||||
|
||||
assertEq(true, FiveUintsA.equivalent(FiveUintsB));
|
||||
assertEq(true, FiveUintsA.unsized === UintsA);
|
||||
assertEq(true, FiveUintsB.unsized !== UintsA);
|
||||
})();
|
||||
|
||||
(function PrototypeHierarchy() {
|
||||
var Uint8s = uint8.array();
|
||||
assertEq(Uint8s.prototype.__proto__, ArrayType.prototype.prototype);
|
||||
Uint8s.prototype.sum = function() {
|
||||
var r = 0;
|
||||
for (var i = 0; i < this.length; i++)
|
||||
r = uint8(r + this[i]);
|
||||
return r;
|
||||
};
|
||||
|
||||
var FiveUint8s = Uint8s.dimension(5);
|
||||
assertEq(FiveUint8s.__proto__, Uint8s);
|
||||
|
||||
var fiveUint8s = new FiveUint8s([128, 128, 128, 128, 128]);
|
||||
assertEq(128, fiveUint8s.sum());
|
||||
})();
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete");
|
||||
}
|
||||
|
||||
runTests();
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
|
||||
var BUGNUMBER = 922115;
|
||||
var summary = 'cannot embed unsized array in a struct';
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var T = TypedObject;
|
||||
|
||||
function runTests() {
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
var Uints = T.uint32.array();
|
||||
assertThrowsInstanceOf(() => { new T.StructType({f: Uints}) }, TypeError);
|
||||
assertThrowsInstanceOf(() => { Uints.array() }, TypeError);
|
||||
|
||||
reportCompare(true, true);
|
||||
print("Tests complete");
|
||||
}
|
||||
|
||||
runTests();
|
|
@ -914,6 +914,18 @@ js::intrinsic_TypeDescrIsArrayType(JSContext *cx, unsigned argc, Value *vp)
|
|||
return js::TypeDescrIsArrayType(cx, argc, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::intrinsic_TypeDescrIsUnsizedArrayType(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
return js::TypeDescrIsUnsizedArrayType(cx, argc, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::intrinsic_TypeDescrIsSizedArrayType(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
return js::TypeDescrIsSizedArrayType(cx, argc, vp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default locale as a well-formed, but not necessarily canonicalized,
|
||||
* BCP-47 language tag.
|
||||
|
@ -1119,6 +1131,12 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
JS_FNINFO("TypeDescrIsArrayType",
|
||||
intrinsic_TypeDescrIsArrayType,
|
||||
&js::TypeDescrIsArrayTypeJitInfo, 1, 0),
|
||||
JS_FNINFO("TypeDescrIsUnsizedArrayType",
|
||||
intrinsic_TypeDescrIsUnsizedArrayType,
|
||||
&js::TypeDescrIsUnsizedArrayTypeJitInfo, 1, 0),
|
||||
JS_FNINFO("TypeDescrIsSizedArrayType",
|
||||
intrinsic_TypeDescrIsSizedArrayType,
|
||||
&js::TypeDescrIsSizedArrayTypeJitInfo, 1, 0),
|
||||
JS_FNINFO("TypeDescrIsSimpleType",
|
||||
intrinsic_TypeDescrIsSimpleType,
|
||||
&js::TypeDescrIsSimpleTypeJitInfo, 1, 0),
|
||||
|
|
Загрузка…
Ссылка в новой задаче