mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset c2659bf5793d (bug 1107145) for bustage.
DONTBUILD CLOSED TREE
This commit is contained in:
parent
ed48b245f1
commit
34b779d2f4
@ -278,6 +278,7 @@ CreateSimdClass(JSContext *cx,
|
||||
proto = NewObjectWithProto<TypedProto>(cx, objProto, nullptr, TenuredObject);
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
proto->initTypeDescrSlot(*typeDescr);
|
||||
typeDescr->initReservedSlot(JS_DESCR_SLOT_TYPROTO, ObjectValue(*proto));
|
||||
|
||||
// Link constructor to prototype and install properties.
|
||||
|
@ -478,10 +478,16 @@ CreatePrototypeObjectForComplexTypeInstance(JSContext *cx,
|
||||
if (!ctorPrototypePrototype)
|
||||
return nullptr;
|
||||
|
||||
return NewObjectWithProto<TypedProto>(cx,
|
||||
Rooted<TypedProto*> result(cx);
|
||||
result = NewObjectWithProto<TypedProto>(cx,
|
||||
&*ctorPrototypePrototype,
|
||||
nullptr,
|
||||
TenuredObject);
|
||||
if (!result)
|
||||
return nullptr;
|
||||
|
||||
result->initTypeDescrSlot(*descr);
|
||||
return result;
|
||||
}
|
||||
|
||||
const Class ArrayTypeDescr::class_ = {
|
||||
@ -1166,6 +1172,7 @@ DefineSimpleTypeDescr(JSContext *cx,
|
||||
proto = NewObjectWithProto<TypedProto>(cx, objProto, nullptr, TenuredObject);
|
||||
if (!proto)
|
||||
return false;
|
||||
proto->initTypeDescrSlot(*descr);
|
||||
descr->initReservedSlot(JS_DESCR_SLOT_TYPROTO, ObjectValue(*proto));
|
||||
|
||||
RootedValue descrValue(cx, ObjectValue(*descr));
|
||||
@ -1461,6 +1468,24 @@ OutlineTypedObject::createUnattached(JSContext *cx,
|
||||
return createUnattachedWithClass(cx, &OutlineTransparentTypedObject::class_, descr, length, heap);
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
PrototypeForTypeDescr(JSContext *cx, HandleTypeDescr descr)
|
||||
{
|
||||
if (descr->is<SimpleTypeDescr>()) {
|
||||
// FIXME Bug 929651 -- What prototype to use?
|
||||
return cx->global()->getOrCreateObjectPrototype(cx);
|
||||
}
|
||||
|
||||
RootedValue protoVal(cx);
|
||||
if (!JSObject::getProperty(cx, descr, descr,
|
||||
cx->names().prototype, &protoVal))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &protoVal.toObject();
|
||||
}
|
||||
|
||||
void
|
||||
OutlineTypedObject::setOwnerAndData(JSObject *owner, uint8_t *data)
|
||||
{
|
||||
@ -1483,25 +1508,26 @@ OutlineTypedObject::setOwnerAndData(JSObject *owner, uint8_t *data)
|
||||
/*static*/ OutlineTypedObject *
|
||||
OutlineTypedObject::createUnattachedWithClass(JSContext *cx,
|
||||
const Class *clasp,
|
||||
HandleTypeDescr descr,
|
||||
HandleTypeDescr type,
|
||||
int32_t length,
|
||||
gc::InitialHeap heap)
|
||||
{
|
||||
MOZ_ASSERT(clasp == &OutlineTransparentTypedObject::class_ ||
|
||||
clasp == &OutlineOpaqueTypedObject::class_);
|
||||
|
||||
RootedTypeObject type(cx, cx->getNewType(clasp, TaggedProto(&descr->typedProto()), descr));
|
||||
if (!type)
|
||||
RootedObject proto(cx, PrototypeForTypeDescr(cx, type));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
NewObjectKind newKind = (heap == gc::TenuredHeap) ? MaybeSingletonObject : GenericObject;
|
||||
OutlineTypedObject *obj = NewObjectWithType<OutlineTypedObject>(cx, type, cx->global(),
|
||||
gc::FINALIZE_OBJECT0, newKind);
|
||||
JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, nullptr, gc::FINALIZE_OBJECT0, newKind);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
obj->setOwnerAndData(nullptr, nullptr);
|
||||
return obj;
|
||||
OutlineTypedObject *typedObj = &obj->as<OutlineTypedObject>();
|
||||
|
||||
typedObj->setOwnerAndData(nullptr, nullptr);
|
||||
return typedObj;
|
||||
}
|
||||
|
||||
void
|
||||
@ -2191,16 +2217,20 @@ InlineTypedObject::create(JSContext *cx, HandleTypeDescr descr, gc::InitialHeap
|
||||
{
|
||||
gc::AllocKind allocKind = allocKindForTypeDescriptor(descr);
|
||||
|
||||
RootedObject proto(cx, PrototypeForTypeDescr(cx, descr));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
const Class *clasp = descr->opaque()
|
||||
? &InlineOpaqueTypedObject::class_
|
||||
: &InlineTransparentTypedObject::class_;
|
||||
|
||||
RootedTypeObject type(cx, cx->getNewType(clasp, TaggedProto(&descr->typedProto()), descr));
|
||||
if (!type)
|
||||
NewObjectKind newKind = (heap == gc::TenuredHeap) ? MaybeSingletonObject : GenericObject;
|
||||
RootedObject obj(cx, NewObjectWithClassProto(cx, clasp, proto, nullptr, allocKind, newKind));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
NewObjectKind newKind = (heap == gc::TenuredHeap) ? MaybeSingletonObject : GenericObject;
|
||||
return NewObjectWithType<InlineTypedObject>(cx, type, cx->global(), allocKind, newKind);
|
||||
return &obj->as<InlineTypedObject>();
|
||||
}
|
||||
|
||||
/* static */ InlineTypedObject *
|
||||
@ -2748,19 +2778,6 @@ JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypedObjectIsAttachedJitInfo,
|
||||
TypedObjectIsAttachedJitInfo,
|
||||
js::TypedObjectIsAttached);
|
||||
|
||||
bool
|
||||
js::TypedObjectTypeDescr(ThreadSafeContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
TypedObject &typedObj = args[0].toObject().as<TypedObject>();
|
||||
args.rval().setObject(typedObj.typeDescr());
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypedObjectTypeDescrJitInfo,
|
||||
TypedObjectTypeDescrJitInfo,
|
||||
js::TypedObjectTypeDescr);
|
||||
|
||||
bool
|
||||
js::ClampToUint8(ThreadSafeContext *, unsigned argc, Value *vp)
|
||||
{
|
||||
|
@ -134,12 +134,30 @@ class StructTypeDescr;
|
||||
class TypedProto;
|
||||
|
||||
/*
|
||||
* The prototype for a typed object.
|
||||
* The prototype for a typed object. Currently, carries a link to the
|
||||
* type descriptor. Eventually will carry most of the type information
|
||||
* we want.
|
||||
*/
|
||||
class TypedProto : public NativeObject
|
||||
{
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
inline void initTypeDescrSlot(TypeDescr &descr);
|
||||
|
||||
TypeDescr &typeDescr() const {
|
||||
return getReservedSlot(JS_TYPROTO_SLOT_DESCR).toObject().as<TypeDescr>();
|
||||
}
|
||||
|
||||
TypeDescr &maybeForwardedTypeDescr() const {
|
||||
return MaybeForwarded(&getReservedSlot(JS_TYPROTO_SLOT_DESCR).toObject())->as<TypeDescr>();
|
||||
}
|
||||
|
||||
inline type::Kind kind() const;
|
||||
|
||||
static int32_t offsetOfTypeDescr() {
|
||||
return getFixedSlotOffset(JS_TYPROTO_SLOT_DESCR);
|
||||
}
|
||||
};
|
||||
|
||||
class TypeDescr : public NativeObject
|
||||
@ -576,11 +594,11 @@ class TypedObject : public JSObject
|
||||
}
|
||||
|
||||
TypeDescr &typeDescr() const {
|
||||
return type()->typeDescr();
|
||||
return typedProto().typeDescr();
|
||||
}
|
||||
|
||||
TypeDescr &maybeForwardedTypeDescr() const {
|
||||
return MaybeForwarded(&typeDescr())->as<TypeDescr>();
|
||||
return maybeForwardedTypedProto().maybeForwardedTypeDescr();
|
||||
}
|
||||
|
||||
int32_t offset() const;
|
||||
@ -853,14 +871,6 @@ extern const JSJitInfo TypeDescrIsArrayTypeJitInfo;
|
||||
bool TypedObjectIsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp);
|
||||
extern const JSJitInfo TypedObjectIsAttachedJitInfo;
|
||||
|
||||
/*
|
||||
* Usage: TypedObjectTypeDescr(obj)
|
||||
*
|
||||
* Given a TypedObject `obj`, returns the object's type descriptor.
|
||||
*/
|
||||
bool TypedObjectTypeDescr(ThreadSafeContext *cx, unsigned argc, Value *vp);
|
||||
extern const JSJitInfo TypedObjectTypeDescrJitInfo;
|
||||
|
||||
/*
|
||||
* Usage: ClampToUint8(v)
|
||||
*
|
||||
@ -1120,4 +1130,17 @@ JSObject::is<js::InlineTypedObject>() const
|
||||
getClass() == &js::InlineOpaqueTypedObject::class_;
|
||||
}
|
||||
|
||||
inline void
|
||||
js::TypedProto::initTypeDescrSlot(TypeDescr &descr)
|
||||
{
|
||||
initReservedSlot(JS_TYPROTO_SLOT_DESCR, ObjectValue(descr));
|
||||
}
|
||||
|
||||
inline js::type::Kind
|
||||
js::TypedProto::kind() const {
|
||||
// Defined out of line because it depends on def'n of both
|
||||
// TypedProto and TypeDescr
|
||||
return typeDescr().kind();
|
||||
}
|
||||
|
||||
#endif /* builtin_TypedObject_h */
|
||||
|
@ -28,11 +28,20 @@
|
||||
#define DESCR_STRUCT_FIELD_OFFSETS(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS)
|
||||
|
||||
// Typed prototype slots
|
||||
|
||||
#define TYPROTO_DESCR(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_TYPROTO_SLOT_DESCR)
|
||||
|
||||
// Other
|
||||
|
||||
#define HAS_PROPERTY(obj, prop) \
|
||||
callFunction(std_Object_hasOwnProperty, obj, prop)
|
||||
|
||||
function TypedObjectTypeDescr(typedObj) {
|
||||
return TYPROTO_DESCR(std_Object_getPrototypeOf(typedObj));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Getting values
|
||||
//
|
||||
|
@ -12,7 +12,8 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Slots for typed prototypes
|
||||
|
||||
#define JS_TYPROTO_SLOTS 0
|
||||
#define JS_TYPROTO_SLOT_DESCR 0
|
||||
#define JS_TYPROTO_SLOTS 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Slots for type objects
|
||||
|
@ -778,6 +778,10 @@ class UnownedBaseShape;
|
||||
namespace jit {
|
||||
class JitCode;
|
||||
}
|
||||
namespace types {
|
||||
struct TypeObject;
|
||||
class TypeNewScript;
|
||||
}
|
||||
|
||||
typedef PreBarriered<JSObject*> PreBarrieredObject;
|
||||
typedef PreBarriered<JSScript*> PreBarrieredScript;
|
||||
@ -807,6 +811,7 @@ typedef HeapPtr<Shape*> HeapPtrShape;
|
||||
typedef HeapPtr<UnownedBaseShape*> HeapPtrUnownedBaseShape;
|
||||
typedef HeapPtr<jit::JitCode*> HeapPtrJitCode;
|
||||
typedef HeapPtr<types::TypeObject*> HeapPtrTypeObject;
|
||||
typedef HeapPtr<types::TypeNewScript*> HeapPtrTypeNewScript;
|
||||
|
||||
typedef PreBarriered<Value> PreBarrieredValue;
|
||||
typedef RelocatablePtr<Value> RelocatableValue;
|
||||
|
@ -4677,8 +4677,8 @@ LoadTypedThingLength(MacroAssembler &masm, TypedThingLayout layout, Register obj
|
||||
break;
|
||||
case Layout_OutlineTypedObject:
|
||||
case Layout_InlineTypedObject:
|
||||
masm.loadPtr(Address(obj, JSObject::offsetOfType()), result);
|
||||
masm.loadPtr(Address(result, types::TypeObject::offsetOfAddendum()), result);
|
||||
masm.loadObjProto(obj, result);
|
||||
masm.unboxObject(Address(result, TypedProto::offsetOfTypeDescr()), result);
|
||||
masm.unboxInt32(Address(result, ArrayTypeDescr::offsetOfLength()), result);
|
||||
break;
|
||||
default:
|
||||
@ -8516,7 +8516,7 @@ ICSetPropNativeAddCompiler::generateStubCode(MacroAssembler &masm)
|
||||
// Check if the old type still has a newScript.
|
||||
masm.loadPtr(Address(objReg, JSObject::offsetOfType()), scratch);
|
||||
masm.branchPtr(Assembler::Equal,
|
||||
Address(scratch, types::TypeObject::offsetOfAddendum()),
|
||||
Address(scratch, types::TypeObject::offsetOfNewScript()),
|
||||
ImmWord(0),
|
||||
&noTypeChange);
|
||||
|
||||
|
@ -4884,13 +4884,19 @@ CodeGenerator::visitTypedArrayElements(LTypedArrayElements *lir)
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitTypedObjectDescr(LTypedObjectDescr *lir)
|
||||
CodeGenerator::visitTypedObjectProto(LTypedObjectProto *lir)
|
||||
{
|
||||
Register obj = ToRegister(lir->object());
|
||||
Register out = ToRegister(lir->output());
|
||||
MOZ_ASSERT(ToRegister(lir->output()) == ReturnReg);
|
||||
|
||||
masm.loadPtr(Address(obj, JSObject::offsetOfType()), out);
|
||||
masm.loadPtr(Address(out, types::TypeObject::offsetOfAddendum()), out);
|
||||
// Eventually we ought to inline this helper function for
|
||||
// efficiency, but it's mildly non-trivial since we must reach
|
||||
// into the type object and so on.
|
||||
|
||||
const Register tempReg = ToRegister(lir->temp());
|
||||
masm.setupUnalignedABICall(1, tempReg);
|
||||
masm.passABIArg(obj);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, TypedObjectProto));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -186,7 +186,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
void visitTypedArrayElements(LTypedArrayElements *lir);
|
||||
void visitTypedObjectElements(LTypedObjectElements *lir);
|
||||
void visitSetTypedObjectOffset(LSetTypedObjectOffset *lir);
|
||||
void visitTypedObjectDescr(LTypedObjectDescr *ins);
|
||||
void visitTypedObjectProto(LTypedObjectProto *ins);
|
||||
void visitStringLength(LStringLength *lir);
|
||||
void visitSubstr(LSubstr *lir);
|
||||
void visitInitializedLength(LInitializedLength *lir);
|
||||
|
@ -11271,7 +11271,14 @@ IonBuilder::typedObjectPrediction(types::TemporaryTypeSet *types)
|
||||
if (!IsTypedObjectClass(type->clasp()))
|
||||
return TypedObjectPrediction();
|
||||
|
||||
out.addDescr(type->typeDescr());
|
||||
TaggedProto proto = type->proto();
|
||||
|
||||
// typed objects have immutable prototypes, and they are
|
||||
// always instances of TypedProto
|
||||
MOZ_ASSERT(proto.isObject() && proto.toObject()->is<TypedProto>());
|
||||
|
||||
TypedProto &typedProto = proto.toObject()->as<TypedProto>();
|
||||
out.addDescr(typedProto.typeDescr());
|
||||
}
|
||||
|
||||
return out;
|
||||
@ -11287,10 +11294,16 @@ IonBuilder::loadTypedObjectType(MDefinition *typedObj)
|
||||
if (typedObj->isNewDerivedTypedObject())
|
||||
return typedObj->toNewDerivedTypedObject()->type();
|
||||
|
||||
MInstruction *descr = MTypedObjectDescr::New(alloc(), typedObj);
|
||||
current->add(descr);
|
||||
MInstruction *proto = MTypedObjectProto::New(alloc(), typedObj);
|
||||
current->add(proto);
|
||||
|
||||
return descr;
|
||||
MInstruction *load = MLoadFixedSlot::New(alloc(), proto, JS_TYPROTO_SLOT_DESCR);
|
||||
current->add(load);
|
||||
|
||||
MInstruction *unbox = MUnbox::New(alloc(), load, MIRType_Object, MUnbox::Infallible);
|
||||
current->add(unbox);
|
||||
|
||||
return unbox;
|
||||
}
|
||||
|
||||
// Given a typed object `typedObj` and an offset `offset` into that
|
||||
|
@ -2596,7 +2596,7 @@ GenerateAddSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
|
||||
masm.push(object);
|
||||
masm.loadPtr(Address(object, JSObject::offsetOfType()), object);
|
||||
masm.branchPtr(Assembler::Equal,
|
||||
Address(object, types::TypeObject::offsetOfAddendum()),
|
||||
Address(object, types::TypeObject::offsetOfNewScript()),
|
||||
ImmWord(0),
|
||||
&noTypeChange);
|
||||
masm.pop(object);
|
||||
|
@ -4295,18 +4295,23 @@ class LTypedArrayElements : public LInstructionHelper<1, 1, 0>
|
||||
}
|
||||
};
|
||||
|
||||
// Load a typed object's descriptor.
|
||||
class LTypedObjectDescr : public LInstructionHelper<1, 1, 0>
|
||||
// Load a typed object's prototype, which is guaranteed to be a
|
||||
// TypedProto object.
|
||||
class LTypedObjectProto : public LCallInstructionHelper<1, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(TypedObjectDescr)
|
||||
LIR_HEADER(TypedObjectProto)
|
||||
|
||||
LTypedObjectDescr(const LAllocation &object) {
|
||||
LTypedObjectProto(const LAllocation &object, const LDefinition &temp1) {
|
||||
setOperand(0, object);
|
||||
setTemp(0, temp1);
|
||||
}
|
||||
const LAllocation *object() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
};
|
||||
|
||||
// Load a typed object's elements vector.
|
||||
|
@ -285,7 +285,7 @@
|
||||
_(SetArrayLength) \
|
||||
_(TypedArrayLength) \
|
||||
_(TypedArrayElements) \
|
||||
_(TypedObjectDescr) \
|
||||
_(TypedObjectProto) \
|
||||
_(TypedObjectElements) \
|
||||
_(SetTypedObjectOffset) \
|
||||
_(StringLength) \
|
||||
|
@ -2496,10 +2496,12 @@ LIRGenerator::visitTypedArrayElements(MTypedArrayElements *ins)
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitTypedObjectDescr(MTypedObjectDescr *ins)
|
||||
LIRGenerator::visitTypedObjectProto(MTypedObjectProto *ins)
|
||||
{
|
||||
MOZ_ASSERT(ins->type() == MIRType_Object);
|
||||
define(new(alloc()) LTypedObjectDescr(useRegisterAtStart(ins->object())), ins);
|
||||
defineReturn(new(alloc()) LTypedObjectProto(useFixed(ins->object(), CallTempReg0),
|
||||
tempFixed(CallTempReg1)),
|
||||
ins);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -192,7 +192,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
void visitTypedArrayElements(MTypedArrayElements *ins);
|
||||
void visitTypedObjectElements(MTypedObjectElements *ins);
|
||||
void visitSetTypedObjectOffset(MSetTypedObjectOffset *ins);
|
||||
void visitTypedObjectDescr(MTypedObjectDescr *ins);
|
||||
void visitTypedObjectProto(MTypedObjectProto *ins);
|
||||
void visitInitializedLength(MInitializedLength *ins);
|
||||
void visitSetInitializedLength(MSetInitializedLength *ins);
|
||||
void visitNot(MNot *ins);
|
||||
|
@ -2829,12 +2829,12 @@ class MNewTypedObject : public MNullaryInstruction
|
||||
}
|
||||
};
|
||||
|
||||
class MTypedObjectDescr
|
||||
class MTypedObjectProto
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy::Data
|
||||
{
|
||||
private:
|
||||
explicit MTypedObjectDescr(MDefinition *object)
|
||||
explicit MTypedObjectProto(MDefinition *object)
|
||||
: MUnaryInstruction(object)
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
@ -2842,10 +2842,10 @@ class MTypedObjectDescr
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(TypedObjectDescr)
|
||||
INSTRUCTION_HEADER(TypedObjectProto)
|
||||
|
||||
static MTypedObjectDescr *New(TempAllocator &alloc, MDefinition *object) {
|
||||
return new(alloc) MTypedObjectDescr(object);
|
||||
static MTypedObjectProto *New(TempAllocator &alloc, MDefinition *object) {
|
||||
return new(alloc) MTypedObjectProto(object);
|
||||
}
|
||||
|
||||
MDefinition *object() const {
|
||||
|
@ -164,7 +164,7 @@ namespace jit {
|
||||
_(SetArrayLength) \
|
||||
_(TypedArrayLength) \
|
||||
_(TypedArrayElements) \
|
||||
_(TypedObjectDescr) \
|
||||
_(TypedObjectProto) \
|
||||
_(TypedObjectElements) \
|
||||
_(SetTypedObjectOffset) \
|
||||
_(InitializedLength) \
|
||||
|
@ -244,7 +244,7 @@ class ParallelSafetyVisitor : public MDefinitionVisitor
|
||||
WRITE_GUARDED_OP(SetArrayLength, elements)
|
||||
SAFE_OP(TypedArrayLength)
|
||||
SAFE_OP(TypedArrayElements)
|
||||
SAFE_OP(TypedObjectDescr)
|
||||
SAFE_OP(TypedObjectProto)
|
||||
SAFE_OP(TypedObjectElements)
|
||||
SAFE_OP(SetTypedObjectOffset)
|
||||
SAFE_OP(InitializedLength)
|
||||
|
@ -1291,6 +1291,15 @@ AssertValidValue(JSContext *cx, Value *v)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Definition of the MTypedObjectProto MIR.
|
||||
JSObject *
|
||||
TypedObjectProto(JSObject *obj)
|
||||
{
|
||||
MOZ_ASSERT(obj->is<TypedObject>());
|
||||
TypedObject &typedObj = obj->as<TypedObject>();
|
||||
return &typedObj.typedProto();
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectIsCallable(JSObject *obj)
|
||||
{
|
||||
|
@ -791,6 +791,8 @@ void AssertValidSymbolPtr(JSContext *cx, JS::Symbol *sym);
|
||||
void AssertValidValue(JSContext *cx, Value *v);
|
||||
#endif
|
||||
|
||||
JSObject *TypedObjectProto(JSObject *obj);
|
||||
|
||||
void MarkValueFromIon(JSRuntime *rt, Value *vp);
|
||||
void MarkStringFromIon(JSRuntime *rt, JSString **stringp);
|
||||
void MarkObjectFromIon(JSRuntime *rt, JSObject **objp);
|
||||
|
@ -375,8 +375,7 @@ class ExclusiveContext : public ThreadSafeContext
|
||||
}
|
||||
|
||||
// Zone local methods that can be used freely from an ExclusiveContext.
|
||||
types::TypeObject *getNewType(const Class *clasp, TaggedProto proto,
|
||||
JSObject *associated = nullptr);
|
||||
types::TypeObject *getNewType(const Class *clasp, TaggedProto proto, JSFunction *fun = nullptr);
|
||||
types::TypeObject *getSingletonType(const Class *clasp, TaggedProto proto);
|
||||
inline js::LifoAlloc &typeLifoAlloc();
|
||||
|
||||
|
@ -271,13 +271,13 @@ struct JSCompartment
|
||||
void sweepInitialShapeTable();
|
||||
|
||||
/* Set of default 'new' or lazy types in the compartment. */
|
||||
js::types::NewTypeObjectTable newTypeObjects;
|
||||
js::types::NewTypeObjectTable lazyTypeObjects;
|
||||
void sweepNewTypeObjectTable(js::types::NewTypeObjectTable &table);
|
||||
js::types::TypeObjectWithNewScriptSet newTypeObjects;
|
||||
js::types::TypeObjectWithNewScriptSet lazyTypeObjects;
|
||||
void sweepNewTypeObjectTable(js::types::TypeObjectWithNewScriptSet &table);
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
void checkTypeObjectTablesAfterMovingGC();
|
||||
void checkTypeObjectTableAfterMovingGC(js::types::NewTypeObjectTable &table);
|
||||
void checkTypeObjectTableAfterMovingGC(js::types::TypeObjectWithNewScriptSet &table);
|
||||
void checkInitialShapesTableAfterMovingGC();
|
||||
void checkWrapperMapAfterMovingGC();
|
||||
#endif
|
||||
@ -394,7 +394,7 @@ struct JSCompartment
|
||||
|
||||
#ifdef JSGC_COMPACTING
|
||||
void fixupInitialShapeTable();
|
||||
void fixupNewTypeObjectTable(js::types::NewTypeObjectTable &table);
|
||||
void fixupNewTypeObjectTable(js::types::TypeObjectWithNewScriptSet &table);
|
||||
void fixupAfterMovingGC();
|
||||
void fixupGlobal();
|
||||
#endif
|
||||
|
@ -3264,7 +3264,7 @@ TypeObject::maybeClearNewScriptOnOOM()
|
||||
if (!isMarked())
|
||||
return;
|
||||
|
||||
if (!newScript())
|
||||
if (!newScript_)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < getPropertyCount(); i++) {
|
||||
@ -3278,7 +3278,7 @@ TypeObject::maybeClearNewScriptOnOOM()
|
||||
// This method is called during GC sweeping, so there is no write barrier
|
||||
// that needs to be triggered.
|
||||
js_delete(newScript());
|
||||
addendum_ = nullptr;
|
||||
newScript_.unsafeSet(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
@ -4083,12 +4083,12 @@ TypeNewScript::maybeAnalyze(JSContext *cx, TypeObject *type, bool *regenerate, b
|
||||
if (!type->addDefiniteProperties(cx, prefixShape))
|
||||
return false;
|
||||
|
||||
NewTypeObjectTable &table = cx->compartment()->newTypeObjects;
|
||||
NewTypeObjectTable::Lookup lookup(type->clasp(), type->proto(), fun);
|
||||
TypeObjectWithNewScriptSet &table = cx->compartment()->newTypeObjects;
|
||||
TypeObjectWithNewScriptSet::Lookup lookup(type->clasp(), type->proto(), fun);
|
||||
|
||||
MOZ_ASSERT(table.lookup(lookup)->object == type);
|
||||
table.remove(lookup);
|
||||
table.putNew(lookup, NewTypeObjectEntry(initialType, fun));
|
||||
table.putNew(lookup, TypeObjectWithNewScriptEntry(initialType, fun));
|
||||
|
||||
templateObject()->setType(initialType);
|
||||
|
||||
@ -4322,32 +4322,31 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj)
|
||||
}
|
||||
|
||||
/* static */ inline HashNumber
|
||||
NewTypeObjectEntry::hash(const Lookup &lookup)
|
||||
TypeObjectWithNewScriptEntry::hash(const Lookup &lookup)
|
||||
{
|
||||
return PointerHasher<JSObject *, 3>::hash(lookup.hashProto.raw()) ^
|
||||
PointerHasher<const Class *, 3>::hash(lookup.clasp) ^
|
||||
PointerHasher<JSObject *, 3>::hash(lookup.associated);
|
||||
PointerHasher<JSFunction *, 3>::hash(lookup.newFunction);
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
NewTypeObjectEntry::match(const NewTypeObjectEntry &key, const Lookup &lookup)
|
||||
TypeObjectWithNewScriptEntry::match(const TypeObjectWithNewScriptEntry &key, const Lookup &lookup)
|
||||
{
|
||||
return key.object->proto() == lookup.matchProto &&
|
||||
key.object->clasp() == lookup.clasp &&
|
||||
key.associated == lookup.associated;
|
||||
key.newFunction == lookup.newFunction;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
JSObject::hasNewType(const Class *clasp, TypeObject *type)
|
||||
{
|
||||
NewTypeObjectTable &table = compartment()->newTypeObjects;
|
||||
TypeObjectWithNewScriptSet &table = compartment()->newTypeObjects;
|
||||
|
||||
if (!table.initialized())
|
||||
return false;
|
||||
|
||||
NewTypeObjectTable::Ptr p =
|
||||
table.lookup(NewTypeObjectTable::Lookup(clasp, TaggedProto(this), nullptr));
|
||||
TypeObjectWithNewScriptSet::Ptr p = table.lookup(TypeObjectWithNewScriptSet::Lookup(clasp, TaggedProto(this), nullptr));
|
||||
return p && p->object == type;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
@ -4363,12 +4362,10 @@ JSObject::setNewTypeUnknown(JSContext *cx, const Class *clasp, HandleObject obj)
|
||||
* not have the SETS_MARKED_UNKNOWN bit set, so may require a type set
|
||||
* crawl if prototypes of the object change dynamically in the future.
|
||||
*/
|
||||
NewTypeObjectTable &table = cx->compartment()->newTypeObjects;
|
||||
TypeObjectWithNewScriptSet &table = cx->compartment()->newTypeObjects;
|
||||
if (table.initialized()) {
|
||||
Rooted<TaggedProto> taggedProto(cx, TaggedProto(obj));
|
||||
NewTypeObjectTable::Ptr p =
|
||||
table.lookup(NewTypeObjectTable::Lookup(clasp, taggedProto, nullptr));
|
||||
if (p)
|
||||
if (TypeObjectWithNewScriptSet::Ptr p = table.lookup(TypeObjectWithNewScriptSet::Lookup(clasp, taggedProto, nullptr)))
|
||||
MarkTypeObjectUnknownProperties(cx, p->object);
|
||||
}
|
||||
|
||||
@ -4382,14 +4379,14 @@ JSObject::setNewTypeUnknown(JSContext *cx, const Class *clasp, HandleObject obj)
|
||||
*/
|
||||
class NewTypeObjectsSetRef : public BufferableRef
|
||||
{
|
||||
NewTypeObjectTable *set;
|
||||
TypeObjectWithNewScriptSet *set;
|
||||
const Class *clasp;
|
||||
JSObject *proto;
|
||||
JSObject *associated;
|
||||
JSFunction *newFunction;
|
||||
|
||||
public:
|
||||
NewTypeObjectsSetRef(NewTypeObjectTable *s, const Class *clasp, JSObject *proto, JSObject *associated)
|
||||
: set(s), clasp(clasp), proto(proto), associated(associated)
|
||||
NewTypeObjectsSetRef(TypeObjectWithNewScriptSet *s, const Class *clasp, JSObject *proto, JSFunction *newFunction)
|
||||
: set(s), clasp(clasp), proto(proto), newFunction(newFunction)
|
||||
{}
|
||||
|
||||
void mark(JSTracer *trc) {
|
||||
@ -4399,21 +4396,19 @@ class NewTypeObjectsSetRef : public BufferableRef
|
||||
if (prior == proto)
|
||||
return;
|
||||
|
||||
NewTypeObjectTable::Ptr p =
|
||||
set->lookup(NewTypeObjectTable::Lookup(clasp, TaggedProto(prior), TaggedProto(proto),
|
||||
associated));
|
||||
TypeObjectWithNewScriptSet::Ptr p = set->lookup(TypeObjectWithNewScriptSet::Lookup(clasp, TaggedProto(prior), TaggedProto(proto), newFunction));
|
||||
MOZ_ASSERT(p); // newTypeObjects set must still contain original entry.
|
||||
|
||||
set->rekeyAs(NewTypeObjectTable::Lookup(clasp, TaggedProto(prior), TaggedProto(proto), associated),
|
||||
NewTypeObjectTable::Lookup(clasp, TaggedProto(proto), associated), *p);
|
||||
set->rekeyAs(TypeObjectWithNewScriptSet::Lookup(clasp, TaggedProto(prior), TaggedProto(proto), newFunction),
|
||||
TypeObjectWithNewScriptSet::Lookup(clasp, TaggedProto(proto), newFunction), *p);
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
TypeObjectTablePostBarrier(ExclusiveContext *cx, NewTypeObjectTable *table,
|
||||
const Class *clasp, TaggedProto proto, JSObject *associated)
|
||||
TypeObjectTablePostBarrier(ExclusiveContext *cx, TypeObjectWithNewScriptSet *table,
|
||||
const Class *clasp, TaggedProto proto, JSFunction *fun)
|
||||
{
|
||||
MOZ_ASSERT_IF(associated, !IsInsideNursery(associated));
|
||||
MOZ_ASSERT_IF(fun, !IsInsideNursery(fun));
|
||||
|
||||
if (!proto.isObject())
|
||||
return;
|
||||
@ -4425,35 +4420,33 @@ TypeObjectTablePostBarrier(ExclusiveContext *cx, NewTypeObjectTable *table,
|
||||
|
||||
if (IsInsideNursery(proto.toObject())) {
|
||||
StoreBuffer &sb = cx->asJSContext()->runtime()->gc.storeBuffer;
|
||||
sb.putGeneric(NewTypeObjectsSetRef(table, clasp, proto.toObject(), associated));
|
||||
sb.putGeneric(NewTypeObjectsSetRef(table, clasp, proto.toObject(), fun));
|
||||
}
|
||||
}
|
||||
|
||||
TypeObject *
|
||||
ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto, JSObject *associated)
|
||||
ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto, JSFunction *fun)
|
||||
{
|
||||
MOZ_ASSERT_IF(associated, proto.isObject());
|
||||
MOZ_ASSERT_IF(associated, associated->is<JSFunction>() || associated->is<TypeDescr>());
|
||||
MOZ_ASSERT_IF(fun, proto.isObject());
|
||||
MOZ_ASSERT_IF(proto.isObject(), isInsideCurrentCompartment(proto.toObject()));
|
||||
|
||||
NewTypeObjectTable &newTypeObjects = compartment()->newTypeObjects;
|
||||
TypeObjectWithNewScriptSet &newTypeObjects = compartment()->newTypeObjects;
|
||||
|
||||
if (!newTypeObjects.initialized() && !newTypeObjects.init())
|
||||
return nullptr;
|
||||
|
||||
// Canonicalize new functions to use the original one associated with its script.
|
||||
if (associated && associated->is<JSFunction>()) {
|
||||
JSFunction *fun = &associated->as<JSFunction>();
|
||||
if (fun) {
|
||||
if (fun->hasScript())
|
||||
associated = fun->nonLazyScript()->functionNonDelazifying();
|
||||
fun = fun->nonLazyScript()->functionNonDelazifying();
|
||||
else if (fun->isInterpretedLazy() && !fun->isSelfHostedBuiltin())
|
||||
associated = fun->lazyScript()->functionNonDelazifying();
|
||||
fun = fun->lazyScript()->functionNonDelazifying();
|
||||
else
|
||||
associated = nullptr;
|
||||
fun = nullptr;
|
||||
}
|
||||
|
||||
NewTypeObjectTable::AddPtr p =
|
||||
newTypeObjects.lookupForAdd(NewTypeObjectTable::Lookup(clasp, proto, associated));
|
||||
TypeObjectWithNewScriptSet::AddPtr p =
|
||||
newTypeObjects.lookupForAdd(TypeObjectWithNewScriptSet::Lookup(clasp, proto, fun));
|
||||
if (p) {
|
||||
TypeObject *type = p->object;
|
||||
MOZ_ASSERT(type->clasp() == clasp);
|
||||
@ -4482,20 +4475,16 @@ ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto, JSObject *as
|
||||
if (!type)
|
||||
return nullptr;
|
||||
|
||||
if (!newTypeObjects.add(p, NewTypeObjectEntry(type, associated)))
|
||||
if (!newTypeObjects.add(p, TypeObjectWithNewScriptEntry(type, fun)))
|
||||
return nullptr;
|
||||
|
||||
TypeObjectTablePostBarrier(this, &newTypeObjects, clasp, proto, associated);
|
||||
TypeObjectTablePostBarrier(this, &newTypeObjects, clasp, proto, fun);
|
||||
|
||||
if (proto.isObject()) {
|
||||
RootedObject obj(this, proto.toObject());
|
||||
|
||||
if (associated) {
|
||||
if (associated->is<JSFunction>())
|
||||
TypeNewScript::make(asJSContext(), type, &associated->as<JSFunction>());
|
||||
else
|
||||
type->setTypeDescr(&associated->as<TypeDescr>());
|
||||
}
|
||||
if (fun)
|
||||
TypeNewScript::make(asJSContext(), type, fun);
|
||||
|
||||
/*
|
||||
* Some builtin objects have slotful native properties baked in at
|
||||
@ -4534,12 +4523,12 @@ ExclusiveContext::getSingletonType(const Class *clasp, TaggedProto proto)
|
||||
|
||||
AutoEnterAnalysis enter(this);
|
||||
|
||||
NewTypeObjectTable &table = compartment()->lazyTypeObjects;
|
||||
TypeObjectWithNewScriptSet &table = compartment()->lazyTypeObjects;
|
||||
|
||||
if (!table.initialized() && !table.init())
|
||||
return nullptr;
|
||||
|
||||
NewTypeObjectTable::AddPtr p = table.lookupForAdd(NewTypeObjectTable::Lookup(clasp, proto, nullptr));
|
||||
TypeObjectWithNewScriptSet::AddPtr p = table.lookupForAdd(TypeObjectWithNewScriptSet::Lookup(clasp, proto, nullptr));
|
||||
if (p) {
|
||||
TypeObject *type = p->object;
|
||||
MOZ_ASSERT(type->lazy());
|
||||
@ -4552,7 +4541,7 @@ ExclusiveContext::getSingletonType(const Class *clasp, TaggedProto proto)
|
||||
if (!type)
|
||||
return nullptr;
|
||||
|
||||
if (!table.add(p, NewTypeObjectEntry(type, nullptr)))
|
||||
if (!table.add(p, TypeObjectWithNewScriptEntry(type, nullptr)))
|
||||
return nullptr;
|
||||
|
||||
TypeObjectTablePostBarrier(this, &table, clasp, proto, nullptr);
|
||||
@ -4860,20 +4849,20 @@ TypeCompartment::sweep(FreeOp *fop)
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::sweepNewTypeObjectTable(NewTypeObjectTable &table)
|
||||
JSCompartment::sweepNewTypeObjectTable(TypeObjectWithNewScriptSet &table)
|
||||
{
|
||||
MOZ_ASSERT(zone()->runtimeFromAnyThread()->isHeapCollecting());
|
||||
if (table.initialized()) {
|
||||
for (NewTypeObjectTable::Enum e(table); !e.empty(); e.popFront()) {
|
||||
NewTypeObjectEntry entry = e.front();
|
||||
for (TypeObjectWithNewScriptSet::Enum e(table); !e.empty(); e.popFront()) {
|
||||
TypeObjectWithNewScriptEntry entry = e.front();
|
||||
if (IsTypeObjectAboutToBeFinalizedFromAnyThread(entry.object.unsafeGet()) ||
|
||||
(entry.associated && IsObjectAboutToBeFinalizedFromAnyThread(&entry.associated)))
|
||||
(entry.newFunction && IsObjectAboutToBeFinalizedFromAnyThread(&entry.newFunction)))
|
||||
{
|
||||
e.removeFront();
|
||||
} else {
|
||||
/* Any rekeying necessary is handled by fixupNewTypeObjectTable() below. */
|
||||
MOZ_ASSERT(entry.object.unbarrieredGet() == e.front().object.unbarrieredGet());
|
||||
MOZ_ASSERT(entry.associated == e.front().associated);
|
||||
MOZ_ASSERT(entry.newFunction == e.front().newFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4882,7 +4871,7 @@ JSCompartment::sweepNewTypeObjectTable(NewTypeObjectTable &table)
|
||||
#ifdef JSGC_COMPACTING
|
||||
|
||||
void
|
||||
JSCompartment::fixupNewTypeObjectTable(NewTypeObjectTable &table)
|
||||
JSCompartment::fixupNewTypeObjectTable(TypeObjectWithNewScriptSet &table)
|
||||
{
|
||||
/*
|
||||
* Each entry's hash depends on the object's prototype and we can't tell
|
||||
@ -4890,8 +4879,8 @@ JSCompartment::fixupNewTypeObjectTable(NewTypeObjectTable &table)
|
||||
*/
|
||||
MOZ_ASSERT(zone()->isCollecting());
|
||||
if (table.initialized()) {
|
||||
for (NewTypeObjectTable::Enum e(table); !e.empty(); e.popFront()) {
|
||||
NewTypeObjectEntry entry = e.front();
|
||||
for (TypeObjectWithNewScriptSet::Enum e(table); !e.empty(); e.popFront()) {
|
||||
TypeObjectWithNewScriptEntry entry = e.front();
|
||||
bool needRekey = false;
|
||||
if (IsForwarded(entry.object.get())) {
|
||||
entry.object.set(Forwarded(entry.object.get()));
|
||||
@ -4907,7 +4896,7 @@ JSCompartment::fixupNewTypeObjectTable(NewTypeObjectTable &table)
|
||||
needRekey = true;
|
||||
}
|
||||
if (needRekey) {
|
||||
NewTypeObjectTable::Lookup lookup(entry.object->clasp(),
|
||||
TypeObjectWithNewScriptSet::Lookup lookup(entry.object->clasp(),
|
||||
proto,
|
||||
entry.newFunction);
|
||||
e.rekeyFront(lookup, entry);
|
||||
@ -4953,7 +4942,7 @@ JSCompartment::checkTypeObjectTablesAfterMovingGC()
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::checkTypeObjectTableAfterMovingGC(NewTypeObjectTable &table)
|
||||
JSCompartment::checkTypeObjectTableAfterMovingGC(TypeObjectWithNewScriptSet &table)
|
||||
{
|
||||
/*
|
||||
* Assert that nothing points into the nursery or needs to be relocated, and
|
||||
@ -4962,17 +4951,17 @@ JSCompartment::checkTypeObjectTableAfterMovingGC(NewTypeObjectTable &table)
|
||||
if (!table.initialized())
|
||||
return;
|
||||
|
||||
for (NewTypeObjectTable::Enum e(table); !e.empty(); e.popFront()) {
|
||||
NewTypeObjectEntry entry = e.front();
|
||||
for (TypeObjectWithNewScriptSet::Enum e(table); !e.empty(); e.popFront()) {
|
||||
TypeObjectWithNewScriptEntry entry = e.front();
|
||||
CheckGCThingAfterMovingGC(entry.object.get());
|
||||
TaggedProto proto = entry.object->proto();
|
||||
if (proto.isObject())
|
||||
CheckGCThingAfterMovingGC(proto.toObject());
|
||||
CheckGCThingAfterMovingGC(entry.associated);
|
||||
CheckGCThingAfterMovingGC(entry.newFunction);
|
||||
|
||||
NewTypeObjectTable::Lookup
|
||||
lookup(entry.object->clasp(), proto, entry.associated);
|
||||
NewTypeObjectTable::Ptr ptr = table.lookup(lookup);
|
||||
TypeObjectWithNewScriptEntry::Lookup
|
||||
lookup(entry.object->clasp(), proto, entry.newFunction);
|
||||
TypeObjectWithNewScriptSet::Ptr ptr = table.lookup(lookup);
|
||||
MOZ_ASSERT(ptr.found() && &*ptr == &e.front());
|
||||
}
|
||||
}
|
||||
@ -5083,7 +5072,7 @@ TypeCompartment::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||
size_t
|
||||
TypeObject::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return mallocSizeOf(newScriptDontCheckGeneration());
|
||||
return mallocSizeOf(newScript_);
|
||||
}
|
||||
|
||||
TypeZone::TypeZone(Zone *zone)
|
||||
@ -5248,14 +5237,8 @@ TypeScript::printTypes(JSContext *cx, HandleScript script) const
|
||||
#endif /* DEBUG */
|
||||
|
||||
void
|
||||
TypeObject::setAddendum(AddendumKind kind, void *addendum)
|
||||
TypeObject::setNewScript(TypeNewScript *newScript)
|
||||
{
|
||||
MOZ_ASSERT(!needsSweep());
|
||||
MOZ_ASSERT(kind <= (OBJECT_FLAG_ADDENDUM_MASK >> OBJECT_FLAG_ADDENDUM_SHIFT));
|
||||
MOZ_ASSERT(!(flags_ & OBJECT_FLAG_ADDENDUM_MASK));
|
||||
|
||||
writeBarrierPre(this);
|
||||
|
||||
flags_ |= kind << OBJECT_FLAG_ADDENDUM_SHIFT;
|
||||
addendum_ = addendum;
|
||||
newScript_ = newScript;
|
||||
}
|
||||
|
@ -512,14 +512,10 @@ enum MOZ_ENUM_TYPE(uint32_t) {
|
||||
OBJECT_FLAG_DYNAMIC_MASK
|
||||
| OBJECT_FLAG_SETS_MARKED_UNKNOWN,
|
||||
|
||||
// Mask/shift for the kind of addendum attached to this type object.
|
||||
OBJECT_FLAG_ADDENDUM_MASK = 0x04000000,
|
||||
OBJECT_FLAG_ADDENDUM_SHIFT = 26,
|
||||
|
||||
// Mask/shift for this type object's generation. If out of sync with the
|
||||
// TypeZone's generation, this TypeObject hasn't been swept yet.
|
||||
OBJECT_FLAG_GENERATION_MASK = 0x08000000,
|
||||
OBJECT_FLAG_GENERATION_SHIFT = 27,
|
||||
OBJECT_FLAG_GENERATION_MASK = 0x04000000,
|
||||
OBJECT_FLAG_GENERATION_SHIFT = 26,
|
||||
};
|
||||
typedef uint32_t TypeObjectFlags;
|
||||
|
||||
@ -980,6 +976,9 @@ class TypeNewScript
|
||||
js_free(initializerList);
|
||||
}
|
||||
|
||||
static inline void writeBarrierPre(TypeNewScript *newScript);
|
||||
static void writeBarrierPost(TypeNewScript *newScript, void *addr) {}
|
||||
|
||||
bool analyzed() const {
|
||||
if (preliminaryObjects) {
|
||||
MOZ_ASSERT(!templateObject());
|
||||
@ -1100,27 +1099,12 @@ struct TypeObject : public gc::TenuredCell
|
||||
/* Flags for this object. */
|
||||
TypeObjectFlags flags_;
|
||||
|
||||
enum AddendumKind {
|
||||
Addendum_NewScript,
|
||||
Addendum_TypeDescr
|
||||
};
|
||||
|
||||
// If non-null, holds additional information about this object, whose
|
||||
// format is indicated by the object's addendum kind.
|
||||
void *addendum_;
|
||||
|
||||
void setAddendum(AddendumKind kind, void *addendum);
|
||||
|
||||
AddendumKind addendumKind() const {
|
||||
return (AddendumKind)
|
||||
((flags_ & OBJECT_FLAG_ADDENDUM_MASK) >> OBJECT_FLAG_ADDENDUM_SHIFT);
|
||||
}
|
||||
|
||||
TypeNewScript *newScriptDontCheckGeneration() const {
|
||||
return addendumKind() == Addendum_NewScript
|
||||
? reinterpret_cast<TypeNewScript *>(addendum_)
|
||||
: nullptr;
|
||||
}
|
||||
/*
|
||||
* If specified, holds information about properties which are definitely
|
||||
* added to objects of this type after being constructed by a particular
|
||||
* script.
|
||||
*/
|
||||
HeapPtrTypeNewScript newScript_;
|
||||
|
||||
public:
|
||||
|
||||
@ -1141,23 +1125,10 @@ struct TypeObject : public gc::TenuredCell
|
||||
|
||||
TypeNewScript *newScript() {
|
||||
maybeSweep(nullptr);
|
||||
return newScriptDontCheckGeneration();
|
||||
return newScript_;
|
||||
}
|
||||
|
||||
void setNewScript(TypeNewScript *newScript) {
|
||||
setAddendum(Addendum_NewScript, newScript);
|
||||
}
|
||||
|
||||
TypeDescr &typeDescr() {
|
||||
// Note: there is no need to sweep when accessing the type descriptor
|
||||
// of an object, as it is strongly held and immutable.
|
||||
MOZ_ASSERT(addendumKind() == Addendum_TypeDescr);
|
||||
return *reinterpret_cast<TypeDescr *>(addendum_);
|
||||
}
|
||||
|
||||
void setTypeDescr(TypeDescr *descr) {
|
||||
setAddendum(Addendum_TypeDescr, descr);
|
||||
}
|
||||
void setNewScript(TypeNewScript *newScript);
|
||||
|
||||
private:
|
||||
/*
|
||||
@ -1318,8 +1289,8 @@ struct TypeObject : public gc::TenuredCell
|
||||
return offsetof(TypeObject, proto_);
|
||||
}
|
||||
|
||||
static inline uint32_t offsetOfAddendum() {
|
||||
return offsetof(TypeObject, addendum_);
|
||||
static inline uint32_t offsetOfNewScript() {
|
||||
return offsetof(TypeObject, newScript_);
|
||||
}
|
||||
|
||||
static inline uint32_t offsetOfFlags() {
|
||||
@ -1336,50 +1307,49 @@ struct TypeObject : public gc::TenuredCell
|
||||
};
|
||||
|
||||
/*
|
||||
* Entries for the per-compartment set of type objects which are the default
|
||||
* types to use for some prototype. An optional associated object is used which
|
||||
* allows multiple type objects to be created with the same prototype. The
|
||||
* associated object may be a function (for types constructed with 'new') or a
|
||||
* type descriptor (for typed objects). These entries are also used for the set
|
||||
* of lazy type objects in the compartment, which use a null associated object
|
||||
* (though there are only a few of these per compartment).
|
||||
* Entries for the per-compartment set of type objects which are 'new' types to
|
||||
* use for some prototype and constructed with an optional script. This also
|
||||
* includes entries for the set of lazy type objects in the compartment, which
|
||||
* use a null script (though there are only a few of these per compartment).
|
||||
*/
|
||||
struct NewTypeObjectEntry
|
||||
struct TypeObjectWithNewScriptEntry
|
||||
{
|
||||
ReadBarrieredTypeObject object;
|
||||
|
||||
// Note: This pointer is only used for equality and does not need a read barrier.
|
||||
JSObject *associated;
|
||||
JSFunction *newFunction;
|
||||
|
||||
NewTypeObjectEntry(TypeObject *object, JSObject *associated)
|
||||
: object(object), associated(associated)
|
||||
TypeObjectWithNewScriptEntry(TypeObject *object, JSFunction *newFunction)
|
||||
: object(object), newFunction(newFunction)
|
||||
{}
|
||||
|
||||
struct Lookup {
|
||||
const Class *clasp;
|
||||
TaggedProto hashProto;
|
||||
TaggedProto matchProto;
|
||||
JSObject *associated;
|
||||
JSFunction *newFunction;
|
||||
|
||||
Lookup(const Class *clasp, TaggedProto proto, JSObject *associated)
|
||||
: clasp(clasp), hashProto(proto), matchProto(proto), associated(associated)
|
||||
Lookup(const Class *clasp, TaggedProto proto, JSFunction *newFunction)
|
||||
: clasp(clasp), hashProto(proto), matchProto(proto), newFunction(newFunction)
|
||||
{}
|
||||
|
||||
/*
|
||||
* For use by generational post barriers only. Look up an entry whose
|
||||
* proto has been moved, but was hashed with the original value.
|
||||
*/
|
||||
Lookup(const Class *clasp, TaggedProto hashProto, TaggedProto matchProto, JSObject *associated)
|
||||
: clasp(clasp), hashProto(hashProto), matchProto(matchProto), associated(associated)
|
||||
Lookup(const Class *clasp, TaggedProto hashProto, TaggedProto matchProto, JSFunction *newFunction)
|
||||
: clasp(clasp), hashProto(hashProto), matchProto(matchProto), newFunction(newFunction)
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
static inline HashNumber hash(const Lookup &lookup);
|
||||
static inline bool match(const NewTypeObjectEntry &key, const Lookup &lookup);
|
||||
static void rekey(NewTypeObjectEntry &k, const NewTypeObjectEntry& newKey) { k = newKey; }
|
||||
static inline bool match(const TypeObjectWithNewScriptEntry &key, const Lookup &lookup);
|
||||
static void rekey(TypeObjectWithNewScriptEntry &k, const TypeObjectWithNewScriptEntry& newKey) { k = newKey; }
|
||||
};
|
||||
typedef HashSet<NewTypeObjectEntry, NewTypeObjectEntry, SystemAllocPolicy> NewTypeObjectTable;
|
||||
typedef HashSet<TypeObjectWithNewScriptEntry,
|
||||
TypeObjectWithNewScriptEntry,
|
||||
SystemAllocPolicy> TypeObjectWithNewScriptSet;
|
||||
|
||||
/* Whether to use a new type object when calling 'new' at script/pc. */
|
||||
bool
|
||||
|
@ -1208,7 +1208,7 @@ inline TypeObject::TypeObject(const Class *clasp, TaggedProto proto, TypeObjectF
|
||||
inline void
|
||||
TypeObject::finalize(FreeOp *fop)
|
||||
{
|
||||
fop->delete_(newScriptDontCheckGeneration());
|
||||
fop->delete_(newScript_.get());
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
@ -1300,6 +1300,17 @@ TypeObject::getProperty(unsigned i)
|
||||
return propertySet[i];
|
||||
}
|
||||
|
||||
inline void
|
||||
TypeNewScript::writeBarrierPre(TypeNewScript *newScript)
|
||||
{
|
||||
if (!newScript || !newScript->fun->runtimeFromAnyThread()->needsIncrementalBarrier())
|
||||
return;
|
||||
|
||||
JS::Zone *zone = newScript->fun->zoneFromAnyThread();
|
||||
if (zone->needsIncrementalBarrier())
|
||||
newScript->trace(zone->barrierTracer());
|
||||
}
|
||||
|
||||
} } /* namespace js::types */
|
||||
|
||||
inline js::types::TypeScript *
|
||||
|
@ -1166,9 +1166,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||
JS_FNINFO("TypedObjectIsAttached",
|
||||
JSNativeThreadSafeWrapper<js::TypedObjectIsAttached>,
|
||||
&js::TypedObjectIsAttachedJitInfo, 1, 0),
|
||||
JS_FNINFO("TypedObjectTypeDescr",
|
||||
JSNativeThreadSafeWrapper<js::TypedObjectTypeDescr>,
|
||||
&js::TypedObjectTypeDescrJitInfo, 1, 0),
|
||||
JS_FNINFO("ObjectIsOpaqueTypedObject",
|
||||
intrinsic_ObjectIsOpaqueTypedObject,
|
||||
&js::ObjectIsOpaqueTypedObjectJitInfo, 1, 0),
|
||||
|
Loading…
Reference in New Issue
Block a user