зеркало из https://github.com/mozilla/gecko-dev.git
Bug 966575 part06 -- Move field info into reserved slots, remove non-standard fieldName r=sfink
This commit is contained in:
Родитель
4716472758
Коммит
c71ebdb102
|
@ -130,7 +130,6 @@ ConvertAndCopyTo(JSContext *cx, HandleTypedDatum datum, HandleValue val)
|
|||
*/
|
||||
static bool
|
||||
Reify(JSContext *cx,
|
||||
TypeRepresentation *typeRepr,
|
||||
HandleTypeDescr type,
|
||||
HandleTypedDatum datum,
|
||||
size_t offset,
|
||||
|
@ -782,36 +781,52 @@ StructMetaTypeDescr::layout(JSContext *cx,
|
|||
structType->initReservedSlot(JS_DESCR_SLOT_TYPE_REPR,
|
||||
ObjectValue(*typeReprObj));
|
||||
|
||||
// Construct for internal use an array with the type object for each field.
|
||||
RootedObject fieldTypeVec(
|
||||
cx, NewDenseCopiedArray(cx, fieldTypeObjs.length(),
|
||||
fieldTypeObjs.begin()));
|
||||
if (!fieldTypeVec)
|
||||
return false;
|
||||
|
||||
structType->initReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_TYPES,
|
||||
ObjectValue(*fieldTypeVec));
|
||||
|
||||
// Construct the fieldNames vector
|
||||
AutoValueVector fieldNameValues(cx);
|
||||
for (unsigned int i = 0; i < ids.length(); i++) {
|
||||
RootedValue value(cx, IdToValue(ids[i]));
|
||||
if (!fieldNameValues.append(value))
|
||||
// Construct for internal use an array with names of each field
|
||||
{
|
||||
AutoValueVector fieldNameValues(cx);
|
||||
for (unsigned int i = 0; i < ids.length(); i++) {
|
||||
RootedValue value(cx, IdToValue(ids[i]));
|
||||
if (!fieldNameValues.append(value))
|
||||
return false;
|
||||
}
|
||||
RootedObject fieldNamesVec(
|
||||
cx, NewDenseCopiedArray(cx, fieldNameValues.length(),
|
||||
fieldNameValues.begin()));
|
||||
if (!fieldNamesVec)
|
||||
return false;
|
||||
structType->initReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_NAMES,
|
||||
ObjectValue(*fieldNamesVec));
|
||||
}
|
||||
RootedObject fieldNamesVec(
|
||||
cx, NewDenseCopiedArray(cx, fieldNameValues.length(),
|
||||
fieldNameValues.begin()));
|
||||
if (!fieldNamesVec)
|
||||
return false;
|
||||
RootedValue fieldNamesVecValue(cx, ObjectValue(*fieldNamesVec));
|
||||
if (!JSObject::defineProperty(cx, structType, cx->names().fieldNames,
|
||||
fieldNamesVecValue, nullptr, nullptr,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT))
|
||||
return false;
|
||||
|
||||
// Construct the fieldNames, fieldOffsets and fieldTypes objects:
|
||||
// fieldNames : [ string ]
|
||||
// Construct for internal use an array with the type object for each field.
|
||||
{
|
||||
RootedObject fieldTypeVec(cx);
|
||||
fieldTypeVec = NewDenseCopiedArray(cx, fieldTypeObjs.length(),
|
||||
fieldTypeObjs.begin());
|
||||
if (!fieldTypeVec)
|
||||
return false;
|
||||
structType->initReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_TYPES,
|
||||
ObjectValue(*fieldTypeVec));
|
||||
}
|
||||
|
||||
// Construct for internal use an array with the offset for each field.
|
||||
{
|
||||
AutoValueVector fieldOffsets(cx);
|
||||
for (size_t i = 0; i < typeRepr->fieldCount(); i++) {
|
||||
const StructField &field = typeRepr->field(i);
|
||||
if (!fieldOffsets.append(Int32Value(field.offset)))
|
||||
return false;
|
||||
}
|
||||
RootedObject fieldOffsetsVec(cx);
|
||||
fieldOffsetsVec = NewDenseCopiedArray(cx, fieldOffsets.length(),
|
||||
fieldOffsets.begin());
|
||||
if (!fieldOffsetsVec)
|
||||
return false;
|
||||
structType->initReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS,
|
||||
ObjectValue(*fieldOffsetsVec));
|
||||
}
|
||||
|
||||
// Construct the fieldOffsets and fieldTypes objects:
|
||||
// fieldOffsets : { string: integer, ... }
|
||||
// fieldTypes : { string: Type, ... }
|
||||
RootedObject fieldOffsets(cx);
|
||||
|
@ -914,6 +929,40 @@ StructMetaTypeDescr::construct(JSContext *cx, unsigned int argc, Value *vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
StructTypeDescr::fieldIndex(jsid id, size_t *out)
|
||||
{
|
||||
JSObject &fieldNames =
|
||||
getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).toObject();
|
||||
size_t l = fieldNames.getDenseInitializedLength();
|
||||
for (size_t i = 0; i < l; i++) {
|
||||
JSAtom &a = fieldNames.getDenseElement(i).toString()->asAtom();
|
||||
if (JSID_IS_ATOM(id, &a)) {
|
||||
*out = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t
|
||||
StructTypeDescr::fieldOffset(size_t index)
|
||||
{
|
||||
JSObject &fieldOffsets =
|
||||
getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS).toObject();
|
||||
JS_ASSERT(index < fieldOffsets.getDenseInitializedLength());
|
||||
return fieldOffsets.getDenseElement(index).toInt32();
|
||||
}
|
||||
|
||||
SizedTypeDescr&
|
||||
StructTypeDescr::fieldDescr(size_t index)
|
||||
{
|
||||
JSObject &fieldDescrs =
|
||||
getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_TYPES).toObject();
|
||||
JS_ASSERT(index < fieldDescrs.getDenseInitializedLength());
|
||||
return fieldDescrs.getDenseElement(index).toObject().as<SizedTypeDescr>();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Creating the TypedObject "module"
|
||||
*
|
||||
|
@ -1597,34 +1646,6 @@ TypedDatum::obj_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId s
|
|||
return obj_defineGeneric(cx, obj, id, v, getter, setter, attrs);
|
||||
}
|
||||
|
||||
static SizedTypeDescr *
|
||||
StructFieldType(JSContext *cx,
|
||||
HandleStructTypeDescr type,
|
||||
int32_t fieldIndex)
|
||||
{
|
||||
// Recover the original type object here (`field` contains
|
||||
// only its canonical form). The difference is observable,
|
||||
// e.g. in a program like:
|
||||
//
|
||||
// var Point1 = new StructType({x:uint8, y:uint8});
|
||||
// var Point2 = new StructType({x:uint8, y:uint8});
|
||||
// var Line1 = new StructType({start:Point1, end: Point1});
|
||||
// var Line2 = new StructType({start:Point2, end: Point2});
|
||||
// var line1 = new Line1(...);
|
||||
// var line2 = new Line2(...);
|
||||
//
|
||||
// In this scenario, line1.start.type() === Point1 and
|
||||
// line2.start.type() === Point2.
|
||||
RootedObject fieldTypes(
|
||||
cx, &type->getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_TYPES).toObject());
|
||||
RootedValue fieldTypeVal(cx);
|
||||
if (!JSObject::getElement(cx, fieldTypes, fieldTypes,
|
||||
fieldIndex, &fieldTypeVal))
|
||||
return nullptr;
|
||||
|
||||
return &fieldTypeVal.toObject().as<SizedTypeDescr>();
|
||||
}
|
||||
|
||||
bool
|
||||
TypedDatum::obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp)
|
||||
|
@ -1664,20 +1685,15 @@ TypedDatum::obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receive
|
|||
break;
|
||||
|
||||
case TypeRepresentation::Struct: {
|
||||
Rooted<StructTypeDescr*> type(cx);
|
||||
type = &datum->typeDescr().as<StructTypeDescr>();
|
||||
Rooted<StructTypeDescr*> descr(cx, &datum->typeDescr().as<StructTypeDescr>());
|
||||
|
||||
StructTypeRepresentation *structTypeRepr = typeRepr->asStruct();
|
||||
const StructField *field = structTypeRepr->fieldNamed(id);
|
||||
if (!field)
|
||||
size_t fieldIndex;
|
||||
if (!descr->fieldIndex(id, &fieldIndex))
|
||||
break;
|
||||
|
||||
Rooted<SizedTypeDescr*> fieldType(cx);
|
||||
fieldType = StructFieldType(cx, type, field->index);
|
||||
if (!fieldType)
|
||||
return false;
|
||||
|
||||
return Reify(cx, field->typeRepr, fieldType, datum, field->offset, vp);
|
||||
size_t offset = descr->fieldOffset(fieldIndex);
|
||||
Rooted<SizedTypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
|
||||
return Reify(cx, fieldType, datum, offset, vp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1751,7 +1767,7 @@ TypedDatum::obj_getArrayElement(JSContext *cx,
|
|||
elementType = &typeDescr->as<T>().elementType();
|
||||
SizedTypeRepresentation *elementTypeRepr = elementType->typeRepresentation();
|
||||
size_t offset = elementTypeRepr->size() * index;
|
||||
return Reify(cx, elementTypeRepr, elementType, datum, offset, vp);
|
||||
return Reify(cx, elementType, datum, offset, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1793,17 +1809,15 @@ TypedDatum::obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
|||
break;
|
||||
|
||||
case ScalarTypeRepresentation::Struct: {
|
||||
const StructField *field = typeRepr->asStruct()->fieldNamed(id);
|
||||
if (!field)
|
||||
Rooted<StructTypeDescr*> descr(cx, &datum->typeDescr().as<StructTypeDescr>());
|
||||
|
||||
size_t fieldIndex;
|
||||
if (!descr->fieldIndex(id, &fieldIndex))
|
||||
break;
|
||||
|
||||
Rooted<StructTypeDescr *> descr(cx, &datum->typeDescr().as<StructTypeDescr>());
|
||||
Rooted<SizedTypeDescr*> fieldType(cx);
|
||||
fieldType = StructFieldType(cx, descr, field->index);
|
||||
if (!fieldType)
|
||||
return false;
|
||||
|
||||
return ConvertAndCopyTo(cx, fieldType, datum, field->offset, vp);
|
||||
size_t offset = descr->fieldOffset(fieldIndex);
|
||||
Rooted<SizedTypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
|
||||
return ConvertAndCopyTo(cx, fieldType, datum, offset, vp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -337,6 +337,16 @@ class StructMetaTypeDescr : public JSObject
|
|||
class StructTypeDescr : public SizedTypeDescr {
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
// Set `*out` to the index of the field named `id` and returns true,
|
||||
// or return false if no such field exists.
|
||||
bool fieldIndex(jsid id, size_t *out);
|
||||
|
||||
// Return the type descr of the field at index `index`.
|
||||
SizedTypeDescr &fieldDescr(size_t index);
|
||||
|
||||
// Return the offset of the field at index `index`.
|
||||
size_t fieldOffset(size_t index);
|
||||
};
|
||||
|
||||
typedef Handle<StructTypeDescr*> HandleStructTypeDescr;
|
||||
|
|
|
@ -26,6 +26,12 @@
|
|||
TO_INT32(UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_SIZED_ARRAY_LENGTH))
|
||||
#define DESCR_TYPE(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_TYPE)
|
||||
#define DESCR_STRUCT_FIELD_NAMES(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_NAMES)
|
||||
#define DESCR_STRUCT_FIELD_TYPES(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_TYPES)
|
||||
#define DESCR_STRUCT_FIELD_OFFSETS(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS)
|
||||
|
||||
// Typed object slots
|
||||
|
||||
|
@ -98,15 +104,15 @@ function DescrToSource(descr) {
|
|||
|
||||
case JS_TYPEREPR_STRUCT_KIND:
|
||||
var result = "new StructType({";
|
||||
for (var i = 0; i < descr.fieldNames.length; i++) {
|
||||
var fieldNames = DESCR_STRUCT_FIELD_NAMES(descr);
|
||||
var fieldTypes = DESCR_STRUCT_FIELD_TYPES(descr);
|
||||
for (var i = 0; i < fieldNames.length; i++) {
|
||||
if (i != 0)
|
||||
result += ", ";
|
||||
|
||||
var fieldName = descr.fieldNames[i];
|
||||
var fieldDescr = descr.fieldTypes[fieldName];
|
||||
result += fieldName;
|
||||
result += fieldNames[i];
|
||||
result += ": ";
|
||||
result += DescrToSource(fieldDescr);
|
||||
result += DescrToSource(fieldTypes[i]);
|
||||
}
|
||||
result += "})";
|
||||
return result;
|
||||
|
@ -267,21 +273,27 @@ TypedObjectPointer.prototype.moveToElem = function(index) {
|
|||
return this;
|
||||
};
|
||||
|
||||
TypedObjectPointer.prototype.moveToField = function(propName) {
|
||||
var fieldNames = DESCR_STRUCT_FIELD_NAMES(this.descr);
|
||||
var index = fieldNames.indexOf(propName);
|
||||
if (index != -1)
|
||||
return this.moveToFieldIndex(index);
|
||||
|
||||
ThrowError(JSMSG_TYPEDOBJECT_NO_SUCH_PROP, propName);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Adjust `this` to point at the field `propName`. `this` must be a
|
||||
// struct type and `propName` must be a valid field name. Returns
|
||||
// `this`.
|
||||
TypedObjectPointer.prototype.moveToField = function(propName) {
|
||||
TypedObjectPointer.prototype.moveToFieldIndex = function(index) {
|
||||
assert(this.kind() == JS_TYPEREPR_STRUCT_KIND,
|
||||
"moveToField invoked on non-struct");
|
||||
assert(HAS_PROPERTY(this.descr.fieldTypes, propName),
|
||||
"moveToField invoked with undefined field");
|
||||
"moveToFieldIndex invoked on non-struct");
|
||||
assert(index >= 0 && index < DESCR_STRUCT_FIELD_NAMES(this.descr).length,
|
||||
"moveToFieldIndex invoked with invalid field index " + index);
|
||||
|
||||
// FIXME(Bug 966575) -- the fieldOffsets array that we are using
|
||||
// below is only available on transparent types. This is fixed
|
||||
// in part 6 of this patch series.
|
||||
|
||||
var fieldDescr = this.descr.fieldTypes[propName];
|
||||
var fieldOffset = TO_INT32(this.descr.fieldOffsets[propName]);
|
||||
var fieldDescr = DESCR_STRUCT_FIELD_TYPES(this.descr)[index];
|
||||
var fieldOffset = TO_INT32(DESCR_STRUCT_FIELD_OFFSETS(this.descr)[index]);
|
||||
|
||||
assert(IsObject(fieldDescr) && ObjectIsTypeDescr(fieldDescr),
|
||||
"bad field descr");
|
||||
|
@ -462,10 +474,10 @@ TypedObjectPointer.prototype.set = function(fromValue) {
|
|||
|
||||
// Adapt each field.
|
||||
var tempPtr = this.copy();
|
||||
var fieldNames = this.descr.fieldNames;
|
||||
var fieldNames = DESCR_STRUCT_FIELD_NAMES(this.descr);
|
||||
for (var i = 0; i < fieldNames.length; i++) {
|
||||
var fieldName = fieldNames[i];
|
||||
tempPtr.reset(this).moveToField(fieldName).set(fromValue[fieldName]);
|
||||
tempPtr.reset(this).moveToFieldIndex(i).set(fromValue[fieldName]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -32,10 +32,12 @@
|
|||
#define JS_DESCR_SLOT_SIZED_ARRAY_LENGTH 4
|
||||
|
||||
// Slots on struct type objects
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_TYPES 3
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_NAMES 3
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_TYPES 4
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS 5
|
||||
|
||||
// Maximum number of slots for any descriptor
|
||||
#define JS_DESCR_SLOTS 5
|
||||
#define JS_DESCR_SLOTS 6
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Slots for type representation objects
|
||||
|
|
|
@ -17,14 +17,10 @@ function assertTypedEqual(type, a_orig, b_orig) {
|
|||
for (var i = 0; i < type.length; i++)
|
||||
recur(type.elementType, a[i], b[i]);
|
||||
} else if (type instanceof StructType) {
|
||||
for (var idx in type.fieldNames) {
|
||||
var fieldName = type.fieldNames[idx];
|
||||
if (type.fieldTypes[fieldName] !== undefined) {
|
||||
recur(type.fieldTypes[fieldName], a[fieldName], b[fieldName]);
|
||||
} else {
|
||||
throw new Error("assertTypedEqual no type for "+
|
||||
"fieldName: "+fieldName+" in type: "+type.toSource());
|
||||
}
|
||||
var fieldNames = Object.getOwnPropertyNames(type.fieldTypes);
|
||||
for (var i = 0; i < fieldNames.length; i++) {
|
||||
var fieldName = fieldNames[i];
|
||||
recur(type.fieldTypes[fieldName], a[fieldName], b[fieldName]);
|
||||
}
|
||||
} else {
|
||||
assertEq(a, b);
|
||||
|
|
|
@ -24,10 +24,11 @@ function runTests() {
|
|||
assertEq(S.variable, false);
|
||||
assertEq(S.byteLength, 16);
|
||||
assertEq(S.byteAlignment, 8);
|
||||
assertEq(S.fieldNames[0], "x");
|
||||
assertEq(S.fieldNames[1], "y");
|
||||
assertEq(S.fieldNames[2], "z");
|
||||
assertEq(S.fieldNames.length, 3);
|
||||
var fieldNames = Object.getOwnPropertyNames(S.fieldTypes);
|
||||
assertEq(fieldNames[0], "x");
|
||||
assertEq(fieldNames[1], "y");
|
||||
assertEq(fieldNames[2], "z");
|
||||
assertEq(fieldNames.length, 3);
|
||||
assertEq(S.fieldTypes.x, int32);
|
||||
assertEq(S.fieldTypes.y, uint8);
|
||||
assertEq(S.fieldTypes.z, float64);
|
||||
|
|
|
@ -65,7 +65,6 @@
|
|||
macro(escape, escape, "escape") \
|
||||
macro(eval, eval, "eval") \
|
||||
macro(false, false_, "false") \
|
||||
macro(fieldNames, fieldNames, "fieldNames") \
|
||||
macro(fieldOffsets, fieldOffsets, "fieldOffsets") \
|
||||
macro(fieldTypes, fieldTypes, "fieldTypes") \
|
||||
macro(fileName, fileName, "fileName") \
|
||||
|
|
Загрузка…
Ссылка в новой задаче