mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
Bug 1478982 - Allow TypedObject fields to be flagged immutable. r=till
This allows internal clients (notably Wasm) to flag TO fields as immutable; we need this both to provide immutability for fields that are declared immutable in wasm structs, and to temporarily avoid the need for type constraints on assignments to Ref-typed pointer fields. --HG-- extra : rebase_source : 19d1b1bf81396ca305b699cda0277fd8e41f5fe9 extra : intermediate-source : d219c9587f920a0f5924dbdab3e8cf5dfecf3f75 extra : source : f1161dd31ac1cf6f050315d04b978b9d6c0c824a
This commit is contained in:
parent
39bda38c95
commit
27be8bc412
@ -547,6 +547,7 @@ ArrayMetaTypeDescr::create(JSContext* cx,
|
|||||||
obj->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(elementType->opaque()));
|
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_ELEM_TYPE, ObjectValue(*elementType));
|
||||||
obj->initReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH, Int32Value(length));
|
obj->initReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH, Int32Value(length));
|
||||||
|
obj->initReservedSlot(JS_DESCR_SLOT_FLAGS, Int32Value(0));
|
||||||
|
|
||||||
RootedValue elementTypeVal(cx, ObjectValue(*elementType));
|
RootedValue elementTypeVal(cx, ObjectValue(*elementType));
|
||||||
if (!DefineDataProperty(cx, obj, cx->names().elementType, elementTypeVal,
|
if (!DefineDataProperty(cx, obj, cx->names().elementType, elementTypeVal,
|
||||||
@ -767,6 +768,8 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||||||
AutoValueVector fieldTypeObjs(cx); // Type descriptor of each field.
|
AutoValueVector fieldTypeObjs(cx); // Type descriptor of each field.
|
||||||
bool opaque = false; // Opacity of struct.
|
bool opaque = false; // Opacity of struct.
|
||||||
|
|
||||||
|
Vector<bool> fieldMutabilities(cx);
|
||||||
|
|
||||||
RootedValue fieldTypeVal(cx);
|
RootedValue fieldTypeVal(cx);
|
||||||
RootedId id(cx);
|
RootedId id(cx);
|
||||||
Rooted<TypeDescr*> fieldType(cx);
|
Rooted<TypeDescr*> fieldType(cx);
|
||||||
@ -796,6 +799,10 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||||||
if (!fieldTypeObjs.append(ObjectValue(*fieldType)))
|
if (!fieldTypeObjs.append(ObjectValue(*fieldType)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
// Along this path everything is mutable
|
||||||
|
if (!fieldMutabilities.append(true))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
// Struct is opaque if any field is opaque
|
// Struct is opaque if any field is opaque
|
||||||
if (fieldType->opaque())
|
if (fieldType->opaque())
|
||||||
opaque = true;
|
opaque = true;
|
||||||
@ -805,7 +812,7 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||||||
if (!structTypePrototype)
|
if (!structTypePrototype)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return createFromArrays(cx, structTypePrototype, opaque, ids, fieldTypeObjs);
|
return createFromArrays(cx, structTypePrototype, opaque, ids, fieldTypeObjs, fieldMutabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ StructTypeDescr*
|
/* static */ StructTypeDescr*
|
||||||
@ -813,11 +820,13 @@ StructMetaTypeDescr::createFromArrays(JSContext* cx,
|
|||||||
HandleObject structTypePrototype,
|
HandleObject structTypePrototype,
|
||||||
bool opaque,
|
bool opaque,
|
||||||
AutoIdVector& ids,
|
AutoIdVector& ids,
|
||||||
AutoValueVector& fieldTypeObjs)
|
AutoValueVector& fieldTypeObjs,
|
||||||
|
Vector<bool>& fieldMutabilities)
|
||||||
{
|
{
|
||||||
StringBuffer stringBuffer(cx); // Canonical string repr
|
StringBuffer stringBuffer(cx); // Canonical string repr
|
||||||
AutoValueVector fieldNames(cx); // Name of each field.
|
AutoValueVector fieldNames(cx); // Name of each field.
|
||||||
AutoValueVector fieldOffsets(cx); // Offset of each field field.
|
AutoValueVector fieldOffsets(cx); // Offset of each field field.
|
||||||
|
AutoValueVector fieldMuts(cx); // Mutability of each field.
|
||||||
RootedObject userFieldOffsets(cx); // User-exposed {f:offset} object
|
RootedObject userFieldOffsets(cx); // User-exposed {f:offset} object
|
||||||
RootedObject userFieldTypes(cx); // User-exposed {f:descr} object.
|
RootedObject userFieldTypes(cx); // User-exposed {f:descr} object.
|
||||||
Layout layout; // Field offsetter
|
Layout layout; // Field offsetter
|
||||||
@ -872,6 +881,9 @@ StructMetaTypeDescr::createFromArrays(JSContext* cx,
|
|||||||
if (!fieldOffsets.append(Int32Value(offset.value())))
|
if (!fieldOffsets.append(Int32Value(offset.value())))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
if (!fieldMuts.append(BooleanValue(fieldMutabilities[i])))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
// userFieldOffsets[id] = offset
|
// userFieldOffsets[id] = offset
|
||||||
RootedValue offsetValue(cx, Int32Value(offset.value()));
|
RootedValue offsetValue(cx, Int32Value(offset.value()));
|
||||||
if (!DefineDataProperty(cx, userFieldOffsets, id, offsetValue,
|
if (!DefineDataProperty(cx, userFieldOffsets, id, offsetValue,
|
||||||
@ -908,6 +920,7 @@ StructMetaTypeDescr::createFromArrays(JSContext* cx,
|
|||||||
descr->initReservedSlot(JS_DESCR_SLOT_ALIGNMENT, Int32Value(AssertedCast<int32_t>(alignment)));
|
descr->initReservedSlot(JS_DESCR_SLOT_ALIGNMENT, Int32Value(AssertedCast<int32_t>(alignment)));
|
||||||
descr->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(totalSize.value()));
|
descr->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(totalSize.value()));
|
||||||
descr->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(opaque));
|
descr->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(opaque));
|
||||||
|
descr->initReservedSlot(JS_DESCR_SLOT_FLAGS, Int32Value(0));
|
||||||
|
|
||||||
// Construct for internal use an array with the name for each field.
|
// Construct for internal use an array with the name for each field.
|
||||||
{
|
{
|
||||||
@ -940,7 +953,19 @@ StructMetaTypeDescr::createFromArrays(JSContext* cx,
|
|||||||
descr->initReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS, ObjectValue(*fieldOffsetsVec));
|
descr->initReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS, ObjectValue(*fieldOffsetsVec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct for internal use an array with the mutability for each field.
|
||||||
|
{
|
||||||
|
RootedObject fieldMutsVec(cx);
|
||||||
|
fieldMutsVec = NewDenseCopiedArray(cx, fieldMuts.length(),
|
||||||
|
fieldMuts.begin(), nullptr,
|
||||||
|
TenuredObject);
|
||||||
|
if (!fieldMutsVec)
|
||||||
|
return nullptr;
|
||||||
|
descr->initReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_MUTS, ObjectValue(*fieldMutsVec));
|
||||||
|
}
|
||||||
|
|
||||||
// Create data properties fieldOffsets and fieldTypes
|
// Create data properties fieldOffsets and fieldTypes
|
||||||
|
// TODO: Probably also want to track mutability here, but not important yet.
|
||||||
if (!FreezeObject(cx, userFieldOffsets))
|
if (!FreezeObject(cx, userFieldOffsets))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (!FreezeObject(cx, userFieldTypes))
|
if (!FreezeObject(cx, userFieldTypes))
|
||||||
@ -1041,6 +1066,14 @@ StructTypeDescr::fieldOffset(size_t index) const
|
|||||||
return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32());
|
return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
StructTypeDescr::fieldIsMutable(size_t index) const
|
||||||
|
{
|
||||||
|
ArrayObject& fieldMuts = fieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_MUTS);
|
||||||
|
MOZ_ASSERT(index < fieldMuts.getDenseInitializedLength());
|
||||||
|
return fieldMuts.getDenseElement(index).toBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
TypeDescr&
|
TypeDescr&
|
||||||
StructTypeDescr::fieldDescr(size_t index) const
|
StructTypeDescr::fieldDescr(size_t index) const
|
||||||
{
|
{
|
||||||
@ -1133,6 +1166,7 @@ DefineSimpleTypeDescr(JSContext* cx,
|
|||||||
descr->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(AssertedCast<int32_t>(T::size(type))));
|
descr->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(AssertedCast<int32_t>(T::size(type))));
|
||||||
descr->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(T::Opaque));
|
descr->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(T::Opaque));
|
||||||
descr->initReservedSlot(JS_DESCR_SLOT_TYPE, Int32Value(int32_t(type)));
|
descr->initReservedSlot(JS_DESCR_SLOT_TYPE, Int32Value(int32_t(type)));
|
||||||
|
descr->initReservedSlot(JS_DESCR_SLOT_FLAGS, Int32Value(0));
|
||||||
|
|
||||||
if (!CreateUserSizeAndAlignmentProperties(cx, descr))
|
if (!CreateUserSizeAndAlignmentProperties(cx, descr))
|
||||||
return false;
|
return false;
|
||||||
@ -1874,6 +1908,12 @@ TypedObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, Handl
|
|||||||
if (!descr->fieldIndex(id, &fieldIndex))
|
if (!descr->fieldIndex(id, &fieldIndex))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (!descr->fieldIsMutable(fieldIndex)) {
|
||||||
|
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||||
|
JSMSG_TYPEDOBJECT_SETTING_IMMUTABLE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!receiver.isObject() || obj != &receiver.toObject())
|
if (!receiver.isObject() || obj != &receiver.toObject())
|
||||||
return SetPropertyByDefining(cx, id, v, receiver, result);
|
return SetPropertyByDefining(cx, id, v, receiver, result);
|
||||||
|
|
||||||
|
@ -417,7 +417,8 @@ class StructMetaTypeDescr : public NativeObject
|
|||||||
HandleObject structTypePrototype,
|
HandleObject structTypePrototype,
|
||||||
bool opaque,
|
bool opaque,
|
||||||
AutoIdVector& ids,
|
AutoIdVector& ids,
|
||||||
AutoValueVector& fieldTypeObjs);
|
AutoValueVector& fieldTypeObjs,
|
||||||
|
Vector<bool>& fieldMutabilities);
|
||||||
|
|
||||||
// Properties and methods to be installed on StructType.prototype,
|
// Properties and methods to be installed on StructType.prototype,
|
||||||
// and hence inherited by all struct type objects:
|
// and hence inherited by all struct type objects:
|
||||||
@ -476,6 +477,9 @@ class StructTypeDescr : public ComplexTypeDescr
|
|||||||
// Return the offset of the field at index `index`.
|
// Return the offset of the field at index `index`.
|
||||||
size_t fieldOffset(size_t index) const;
|
size_t fieldOffset(size_t index) const;
|
||||||
|
|
||||||
|
// Return the mutability of the field at index `index`.
|
||||||
|
bool fieldIsMutable(size_t index) const;
|
||||||
|
|
||||||
static bool call(JSContext* cx, unsigned argc, Value* vp);
|
static bool call(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -52,21 +52,23 @@
|
|||||||
#define JS_DESCR_SLOT_TYPROTO 5 // Prototype for instances, if any
|
#define JS_DESCR_SLOT_TYPROTO 5 // Prototype for instances, if any
|
||||||
#define JS_DESCR_SLOT_ARRAYPROTO 6 // Lazily created prototype for arrays
|
#define JS_DESCR_SLOT_ARRAYPROTO 6 // Lazily created prototype for arrays
|
||||||
#define JS_DESCR_SLOT_TRACE_LIST 7 // List of references for use in tracing
|
#define JS_DESCR_SLOT_TRACE_LIST 7 // List of references for use in tracing
|
||||||
|
#define JS_DESCR_SLOT_FLAGS 8 // int32 bitvector of JS_DESCR_FLAG_*
|
||||||
|
|
||||||
// Slots on scalars, references
|
// Slots on scalars, references
|
||||||
#define JS_DESCR_SLOT_TYPE 8 // Type code
|
#define JS_DESCR_SLOT_TYPE 9 // Type code
|
||||||
|
|
||||||
// Slots on array descriptors
|
// Slots on array descriptors
|
||||||
#define JS_DESCR_SLOT_ARRAY_ELEM_TYPE 8
|
#define JS_DESCR_SLOT_ARRAY_ELEM_TYPE 9
|
||||||
#define JS_DESCR_SLOT_ARRAY_LENGTH 9
|
#define JS_DESCR_SLOT_ARRAY_LENGTH 10
|
||||||
|
|
||||||
// Slots on struct type objects
|
// Slots on struct type objects
|
||||||
#define JS_DESCR_SLOT_STRUCT_FIELD_NAMES 8
|
#define JS_DESCR_SLOT_STRUCT_FIELD_NAMES 9
|
||||||
#define JS_DESCR_SLOT_STRUCT_FIELD_TYPES 9
|
#define JS_DESCR_SLOT_STRUCT_FIELD_TYPES 10
|
||||||
#define JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS 10
|
#define JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS 11
|
||||||
|
#define JS_DESCR_SLOT_STRUCT_FIELD_MUTS 12
|
||||||
|
|
||||||
// Maximum number of slots for any descriptor
|
// Maximum number of slots for any descriptor
|
||||||
#define JS_DESCR_SLOTS 11
|
#define JS_DESCR_SLOTS 13
|
||||||
|
|
||||||
// These constants are for use exclusively in JS code. In C++ code,
|
// These constants are for use exclusively in JS code. In C++ code,
|
||||||
// prefer TypeRepresentation::Scalar etc, which allows you to
|
// prefer TypeRepresentation::Scalar etc, which allows you to
|
||||||
|
@ -10574,7 +10574,8 @@ IonBuilder::getPropTryTypedObject(bool* emitted,
|
|||||||
TypedObjectPrediction fieldPrediction;
|
TypedObjectPrediction fieldPrediction;
|
||||||
size_t fieldOffset;
|
size_t fieldOffset;
|
||||||
size_t fieldIndex;
|
size_t fieldIndex;
|
||||||
if (!typedObjectHasField(obj, name, &fieldOffset, &fieldPrediction, &fieldIndex))
|
bool fieldMutable;
|
||||||
|
if (!typedObjectHasField(obj, name, &fieldOffset, &fieldPrediction, &fieldIndex, &fieldMutable))
|
||||||
return Ok();
|
return Ok();
|
||||||
|
|
||||||
switch (fieldPrediction.kind()) {
|
switch (fieldPrediction.kind()) {
|
||||||
@ -11716,7 +11717,11 @@ IonBuilder::setPropTryTypedObject(bool* emitted, MDefinition* obj,
|
|||||||
TypedObjectPrediction fieldPrediction;
|
TypedObjectPrediction fieldPrediction;
|
||||||
size_t fieldOffset;
|
size_t fieldOffset;
|
||||||
size_t fieldIndex;
|
size_t fieldIndex;
|
||||||
if (!typedObjectHasField(obj, name, &fieldOffset, &fieldPrediction, &fieldIndex))
|
bool fieldMutable;
|
||||||
|
if (!typedObjectHasField(obj, name, &fieldOffset, &fieldPrediction, &fieldIndex, &fieldMutable))
|
||||||
|
return Ok();
|
||||||
|
|
||||||
|
if (!fieldMutable)
|
||||||
return Ok();
|
return Ok();
|
||||||
|
|
||||||
switch (fieldPrediction.kind()) {
|
switch (fieldPrediction.kind()) {
|
||||||
@ -13486,7 +13491,8 @@ IonBuilder::typedObjectHasField(MDefinition* typedObj,
|
|||||||
PropertyName* name,
|
PropertyName* name,
|
||||||
size_t* fieldOffset,
|
size_t* fieldOffset,
|
||||||
TypedObjectPrediction* fieldPrediction,
|
TypedObjectPrediction* fieldPrediction,
|
||||||
size_t* fieldIndex)
|
size_t* fieldIndex,
|
||||||
|
bool* fieldMutable)
|
||||||
{
|
{
|
||||||
TypedObjectPrediction objPrediction = typedObjectPrediction(typedObj);
|
TypedObjectPrediction objPrediction = typedObjectPrediction(typedObj);
|
||||||
if (objPrediction.isUseless()) {
|
if (objPrediction.isUseless()) {
|
||||||
@ -13502,7 +13508,7 @@ IonBuilder::typedObjectHasField(MDefinition* typedObj,
|
|||||||
|
|
||||||
// Determine the type/offset of the field `name`, if any.
|
// Determine the type/offset of the field `name`, if any.
|
||||||
if (!objPrediction.hasFieldNamed(NameToId(name), fieldOffset,
|
if (!objPrediction.hasFieldNamed(NameToId(name), fieldOffset,
|
||||||
fieldPrediction, fieldIndex))
|
fieldPrediction, fieldIndex, fieldMutable))
|
||||||
{
|
{
|
||||||
trackOptimizationOutcome(TrackedOutcome::StructNoField);
|
trackOptimizationOutcome(TrackedOutcome::StructNoField);
|
||||||
return false;
|
return false;
|
||||||
|
@ -357,7 +357,8 @@ class IonBuilder
|
|||||||
PropertyName* name,
|
PropertyName* name,
|
||||||
size_t* fieldOffset,
|
size_t* fieldOffset,
|
||||||
TypedObjectPrediction* fieldTypeReprs,
|
TypedObjectPrediction* fieldTypeReprs,
|
||||||
size_t* fieldIndex);
|
size_t* fieldIndex,
|
||||||
|
bool* fieldMutable);
|
||||||
MDefinition* loadTypedObjectType(MDefinition* value);
|
MDefinition* loadTypedObjectType(MDefinition* value);
|
||||||
AbortReasonOr<Ok> loadTypedObjectData(MDefinition* typedObj,
|
AbortReasonOr<Ok> loadTypedObjectData(MDefinition* typedObj,
|
||||||
MDefinition** owner,
|
MDefinition** owner,
|
||||||
|
@ -256,7 +256,8 @@ TypedObjectPrediction::hasFieldNamedPrefix(const StructTypeDescr& descr,
|
|||||||
jsid id,
|
jsid id,
|
||||||
size_t* fieldOffset,
|
size_t* fieldOffset,
|
||||||
TypedObjectPrediction* out,
|
TypedObjectPrediction* out,
|
||||||
size_t* index) const
|
size_t* index,
|
||||||
|
bool* isMutable) const
|
||||||
{
|
{
|
||||||
// Find the index of the field |id| if any.
|
// Find the index of the field |id| if any.
|
||||||
if (!descr.fieldIndex(id, index))
|
if (!descr.fieldIndex(id, index))
|
||||||
@ -269,6 +270,7 @@ TypedObjectPrediction::hasFieldNamedPrefix(const StructTypeDescr& descr,
|
|||||||
// Load the offset and type.
|
// Load the offset and type.
|
||||||
*fieldOffset = descr.fieldOffset(*index);
|
*fieldOffset = descr.fieldOffset(*index);
|
||||||
*out = TypedObjectPrediction(descr.fieldDescr(*index));
|
*out = TypedObjectPrediction(descr.fieldDescr(*index));
|
||||||
|
*isMutable = descr.fieldIsMutable(*index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +278,8 @@ bool
|
|||||||
TypedObjectPrediction::hasFieldNamed(jsid id,
|
TypedObjectPrediction::hasFieldNamed(jsid id,
|
||||||
size_t* fieldOffset,
|
size_t* fieldOffset,
|
||||||
TypedObjectPrediction* fieldType,
|
TypedObjectPrediction* fieldType,
|
||||||
size_t* fieldIndex) const
|
size_t* fieldIndex,
|
||||||
|
bool* fieldMutable) const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(kind() == type::Struct);
|
MOZ_ASSERT(kind() == type::Struct);
|
||||||
|
|
||||||
@ -288,12 +291,12 @@ TypedObjectPrediction::hasFieldNamed(jsid id,
|
|||||||
case TypedObjectPrediction::Descr:
|
case TypedObjectPrediction::Descr:
|
||||||
return hasFieldNamedPrefix(
|
return hasFieldNamedPrefix(
|
||||||
descr().as<StructTypeDescr>(), ALL_FIELDS,
|
descr().as<StructTypeDescr>(), ALL_FIELDS,
|
||||||
id, fieldOffset, fieldType, fieldIndex);
|
id, fieldOffset, fieldType, fieldIndex, fieldMutable);
|
||||||
|
|
||||||
case TypedObjectPrediction::Prefix:
|
case TypedObjectPrediction::Prefix:
|
||||||
return hasFieldNamedPrefix(
|
return hasFieldNamedPrefix(
|
||||||
*prefix().descr, prefix().fields,
|
*prefix().descr, prefix().fields,
|
||||||
id, fieldOffset, fieldType, fieldIndex);
|
id, fieldOffset, fieldType, fieldIndex, fieldMutable);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH("Bad prediction kind");
|
MOZ_CRASH("Bad prediction kind");
|
||||||
|
@ -110,7 +110,8 @@ class TypedObjectPrediction {
|
|||||||
jsid id,
|
jsid id,
|
||||||
size_t* fieldOffset,
|
size_t* fieldOffset,
|
||||||
TypedObjectPrediction* out,
|
TypedObjectPrediction* out,
|
||||||
size_t* index) const;
|
size_t* index,
|
||||||
|
bool* isMutable) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -192,7 +193,8 @@ class TypedObjectPrediction {
|
|||||||
bool hasFieldNamed(jsid id,
|
bool hasFieldNamed(jsid id,
|
||||||
size_t* fieldOffset,
|
size_t* fieldOffset,
|
||||||
TypedObjectPrediction* fieldType,
|
TypedObjectPrediction* fieldType,
|
||||||
size_t* fieldIndex) const;
|
size_t* fieldIndex,
|
||||||
|
bool* fieldMutable) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace jit
|
} // namespace jit
|
||||||
|
@ -543,6 +543,7 @@ MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED, 0, JSEXN_TYPEERR, "handle unattache
|
|||||||
MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_ARGS, 0, JSEXN_RANGEERR, "invalid field descriptor")
|
MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_ARGS, 0, JSEXN_RANGEERR, "invalid field descriptor")
|
||||||
MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_NOT_CALLABLE, 0, JSEXN_TYPEERR, "not callable")
|
MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_NOT_CALLABLE, 0, JSEXN_TYPEERR, "not callable")
|
||||||
MSG_DEF(JSMSG_TYPEDOBJECT_TOO_BIG, 0, JSEXN_ERR, "Type is too large to allocate")
|
MSG_DEF(JSMSG_TYPEDOBJECT_TOO_BIG, 0, JSEXN_ERR, "Type is too large to allocate")
|
||||||
|
MSG_DEF(JSMSG_TYPEDOBJECT_SETTING_IMMUTABLE, 0, JSEXN_ERR, "setting immutable field")
|
||||||
|
|
||||||
// Array
|
// Array
|
||||||
MSG_DEF(JSMSG_TOO_LONG_ARRAY, 0, JSEXN_TYPEERR, "Too long array")
|
MSG_DEF(JSMSG_TOO_LONG_ARRAY, 0, JSEXN_TYPEERR, "Too long array")
|
||||||
|
Loading…
Reference in New Issue
Block a user