Bug 906060 - Allow ExclusiveContext zones to have TI enabled, r=billm.

This commit is contained in:
Brian Hackett 2013-08-22 07:13:18 -06:00
parent 36d43a2d51
commit 3ea6fd69a7
16 changed files with 229 additions and 217 deletions

View File

@ -4497,8 +4497,7 @@ EmitFunc(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
*/ */
if (fun->isInterpreted()) { if (fun->isInterpreted()) {
bool singleton = bool singleton =
cx->isJSContext() && cx->typeInferenceEnabled() &&
cx->asJSContext()->typeInferenceEnabled() &&
bce->script->compileAndGo && bce->script->compileAndGo &&
fun->isInterpreted() && fun->isInterpreted() &&
(bce->checkSingletonContext() || (bce->checkSingletonContext() ||

View File

@ -820,7 +820,7 @@ IonBuilder::initParameters()
types::StackTypeSet *thisTypes = types::TypeScript::ThisTypes(script()); types::StackTypeSet *thisTypes = types::TypeScript::ThisTypes(script());
if (thisTypes->empty() && baselineFrame_) if (thisTypes->empty() && baselineFrame_)
thisTypes->addType(cx, types::GetValueType(cx, baselineFrame_->thisValue())); thisTypes->addType(cx, types::GetValueType(baselineFrame_->thisValue()));
MParameter *param = MParameter::New(MParameter::THIS_SLOT, cloneTypeSet(thisTypes)); MParameter *param = MParameter::New(MParameter::THIS_SLOT, cloneTypeSet(thisTypes));
current->add(param); current->add(param);
@ -831,7 +831,7 @@ IonBuilder::initParameters()
if (argTypes->empty() && baselineFrame_ && if (argTypes->empty() && baselineFrame_ &&
!script_->baselineScript()->modifiesArguments()) !script_->baselineScript()->modifiesArguments())
{ {
argTypes->addType(cx, types::GetValueType(cx, baselineFrame_->argv()[i])); argTypes->addType(cx, types::GetValueType(baselineFrame_->argv()[i]));
} }
param = MParameter::New(i, cloneTypeSet(argTypes)); param = MParameter::New(i, cloneTypeSet(argTypes));
@ -5773,7 +5773,7 @@ IonBuilder::newPendingLoopHeader(MBasicBlock *predecessor, jsbytecode *pc, bool
MIRType type = existingValue.isDouble() MIRType type = existingValue.isDouble()
? MIRType_Double ? MIRType_Double
: MIRTypeFromValueType(existingValue.extractNonDoubleType()); : MIRTypeFromValueType(existingValue.extractNonDoubleType());
types::Type ntype = types::GetValueType(cx, existingValue); types::Type ntype = types::GetValueType(existingValue);
types::StackTypeSet *typeSet = types::StackTypeSet *typeSet =
GetIonContext()->temp->lifoAlloc()->new_<types::StackTypeSet>(ntype); GetIonContext()->temp->lifoAlloc()->new_<types::StackTypeSet>(ntype);
phi->addBackedgeType(type, typeSet); phi->addBackedgeType(type, typeSet);
@ -6363,7 +6363,7 @@ IonBuilder::jsop_intrinsic(HandlePropertyName name)
if (!cx->global()->getIntrinsicValue(cx, name, &vp)) if (!cx->global()->getIntrinsicValue(cx, name, &vp))
return false; return false;
JS_ASSERT(types->hasType(types::GetValueType(cx, vp))); JS_ASSERT(types->hasType(types::GetValueType(vp)));
MConstant *ins = MConstant::New(vp); MConstant *ins = MConstant::New(vp);
current->add(ins); current->add(ins);

View File

@ -2546,7 +2546,7 @@ ion::PropertyReadNeedsTypeBarrier(JSContext *cx, types::TypeObject *object, Prop
if (HasDataProperty(cx, obj, id, &v)) { if (HasDataProperty(cx, obj, id, &v)) {
if (v.isUndefined()) if (v.isUndefined())
break; break;
observed->addType(cx, types::GetValueType(cx, v)); observed->addType(cx, types::GetValueType(v));
} }
obj = obj->getProto(); obj = obj->getProto();

View File

@ -1075,7 +1075,7 @@ InitArrayTypes(JSContext *cx, TypeObject *type, const Value *vector, unsigned co
for (unsigned i = 0; i < count; i++) { for (unsigned i = 0; i < count; i++) {
if (vector[i].isMagic(JS_ELEMENTS_HOLE)) if (vector[i].isMagic(JS_ELEMENTS_HOLE))
continue; continue;
Type valtype = GetValueType(cx, vector[i]); Type valtype = GetValueType(vector[i]);
types->addType(cx, valtype); types->addType(cx, valtype);
} }
} }

View File

@ -259,10 +259,11 @@ struct ThreadSafeContext : ContextFriendFields,
js_ReportAllocationOverflow(this); js_ReportAllocationOverflow(this);
} }
// Builtin atoms are immutable and may be accessed freely from any thread. // Accessors for immutable runtime data.
JSAtomState &names() { return runtime_->atomState; } JSAtomState &names() { return runtime_->atomState; }
StaticStrings &staticStrings() { return runtime_->staticStrings; } StaticStrings &staticStrings() { return runtime_->staticStrings; }
PropertyName *emptyString() { return runtime_->emptyString; } PropertyName *emptyString() { return runtime_->emptyString; }
FreeOp *defaultFreeOp() { return runtime_->defaultFreeOp(); }
// GCs cannot happen while non-main threads are running. // GCs cannot happen while non-main threads are running.
uint64_t gcNumber() { return runtime_->gcNumber; } uint64_t gcNumber() { return runtime_->gcNumber; }
@ -351,6 +352,7 @@ class ExclusiveContext : public ThreadSafeContext
// Zone local methods that can be used freely from an ExclusiveContext. // Zone local methods that can be used freely from an ExclusiveContext.
inline bool typeInferenceEnabled() const; inline bool typeInferenceEnabled() const;
types::TypeObject *getNewType(Class *clasp, TaggedProto proto, JSFunction *fun = NULL); types::TypeObject *getNewType(Class *clasp, TaggedProto proto, JSFunction *fun = NULL);
inline js::LifoAlloc &typeLifoAlloc();
// Current global. This is only safe to use within the scope of the // Current global. This is only safe to use within the scope of the
// AutoCompartment from which it's called. // AutoCompartment from which it's called.
@ -483,7 +485,6 @@ struct JSContext : public js::ExclusiveContext,
js::LifoAlloc &tempLifoAlloc() { return runtime()->tempLifoAlloc; } js::LifoAlloc &tempLifoAlloc() { return runtime()->tempLifoAlloc; }
inline js::LifoAlloc &analysisLifoAlloc(); inline js::LifoAlloc &analysisLifoAlloc();
inline js::LifoAlloc &typeLifoAlloc();
#ifdef JS_THREADSAFE #ifdef JS_THREADSAFE
unsigned outstandingRequests;/* number of JS_BeginRequest calls unsigned outstandingRequests;/* number of JS_BeginRequest calls

View File

@ -406,6 +406,12 @@ class AutoLockForExclusiveAccess
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
}; };
inline LifoAlloc &
ExclusiveContext::typeLifoAlloc()
{
return zone()->types.typeLifoAlloc;
}
} /* namespace js */ } /* namespace js */
inline js::LifoAlloc & inline js::LifoAlloc &
@ -414,12 +420,6 @@ JSContext::analysisLifoAlloc()
return compartment()->analysisLifoAlloc; return compartment()->analysisLifoAlloc;
} }
inline js::LifoAlloc &
JSContext::typeLifoAlloc()
{
return zone()->types.typeLifoAlloc;
}
inline void inline void
JSContext::setPendingException(js::Value v) { JSContext::setPendingException(js::Value v) {
JS_ASSERT(!IsPoisonedValue(v)); JS_ASSERT(!IsPoisonedValue(v));

View File

@ -433,10 +433,6 @@ namespace js {
inline bool inline bool
ExclusiveContext::typeInferenceEnabled() const ExclusiveContext::typeInferenceEnabled() const
{ {
// Type inference cannot be enabled in compartments which are accessed off
// the main thread by an ExclusiveContext. TI data is stored in per-zone
// allocators which could otherwise race with main thread operations.
JS_ASSERT_IF(!isJSContext(), !compartment_->zone()->types.inferenceEnabled);
return compartment_->zone()->types.inferenceEnabled; return compartment_->zone()->types.inferenceEnabled;
} }

View File

@ -4055,6 +4055,13 @@ AutoGCSession::AutoGCSession(JSRuntime *rt)
runtime->gcInterFrameGC = true; runtime->gcInterFrameGC = true;
runtime->gcNumber++; runtime->gcNumber++;
#ifdef DEBUG
// Threads with an exclusive context should never pause while they are in
// the middle of a suppressGC.
for (ThreadDataIter iter(rt); !iter.done(); iter.next())
JS_ASSERT(!iter->suppressGC);
#endif
} }
AutoGCSession::~AutoGCSession() AutoGCSession::~AutoGCSession()
@ -4816,6 +4823,9 @@ gc::MergeCompartments(JSCompartment *source, JSCompartment *target)
target->zone()->allocator.arenas.adoptArenas(rt, &source->zone()->allocator.arenas); target->zone()->allocator.arenas.adoptArenas(rt, &source->zone()->allocator.arenas);
target->zone()->gcBytes += source->zone()->gcBytes; target->zone()->gcBytes += source->zone()->gcBytes;
source->zone()->gcBytes = 0; source->zone()->gcBytes = 0;
// Merge other info in source's zone into target's zone.
target->zone()->types.typeLifoAlloc.transferFrom(&source->zone()->types.typeLifoAlloc);
} }
void void
@ -5140,8 +5150,8 @@ AutoMaybeTouchDeadZones::~AutoMaybeTouchDeadZones()
runtime->gcManipulatingDeadZones = manipulatingDeadZones; runtime->gcManipulatingDeadZones = manipulatingDeadZones;
} }
AutoSuppressGC::AutoSuppressGC(JSContext *cx) AutoSuppressGC::AutoSuppressGC(ExclusiveContext *cx)
: suppressGC_(cx->runtime()->mainThread.suppressGC) : suppressGC_(cx->perThreadData->suppressGC)
{ {
suppressGC_++; suppressGC_++;
} }

View File

@ -1400,7 +1400,7 @@ class AutoSuppressGC
int32_t &suppressGC_; int32_t &suppressGC_;
public: public:
AutoSuppressGC(JSContext *cx); AutoSuppressGC(ExclusiveContext *cx);
AutoSuppressGC(JSCompartment *comp); AutoSuppressGC(JSCompartment *comp);
~AutoSuppressGC() ~AutoSuppressGC()

View File

@ -47,6 +47,7 @@ using namespace js::types;
using namespace js::analyze; using namespace js::analyze;
using mozilla::DebugOnly; using mozilla::DebugOnly;
using mozilla::Maybe;
using mozilla::PodArrayZero; using mozilla::PodArrayZero;
using mozilla::PodCopy; using mozilla::PodCopy;
using mozilla::PodZero; using mozilla::PodZero;
@ -259,7 +260,7 @@ types::TypeHasProperty(JSContext *cx, TypeObject *obj, jsid id, const Value &val
if (cx->compartment()->types.pendingCount) if (cx->compartment()->types.pendingCount)
return true; return true;
Type type = GetValueType(cx, value); Type type = GetValueType(value);
AutoEnterAnalysis enter(cx); AutoEnterAnalysis enter(cx);
@ -268,7 +269,7 @@ types::TypeHasProperty(JSContext *cx, TypeObject *obj, jsid id, const Value &val
* haven't yet been accessed during analysis of the inheriting object. * haven't yet been accessed during analysis of the inheriting object.
* Don't do the property instantiation now. * Don't do the property instantiation now.
*/ */
TypeSet *types = obj->maybeGetProperty(id, cx); TypeSet *types = obj->maybeGetProperty(cx, id);
if (!types) if (!types)
return true; return true;
@ -1127,7 +1128,7 @@ GetSingletonPropertyType(JSContext *cx, JSObject *rawObjArg, HandleId id)
if (HasDataProperty(cx, obj, id, v.address())) { if (HasDataProperty(cx, obj, id, v.address())) {
if (v.isUndefined()) if (v.isUndefined())
return Type::UnknownType(); return Type::UnknownType();
return GetValueType(cx, v); return GetValueType(v);
} }
obj = obj->getProto(); obj = obj->getProto();
@ -1838,23 +1839,27 @@ HeapTypeSet::HasObjectFlags(JSContext *cx, TypeObject *object, TypeObjectFlags f
} }
static inline void static inline void
ObjectStateChange(JSContext *cx, TypeObject *object, bool markingUnknown, bool force) ObjectStateChange(ExclusiveContext *cxArg, TypeObject *object, bool markingUnknown, bool force)
{ {
if (object->unknownProperties()) if (object->unknownProperties())
return; return;
/* All constraints listening to state changes are on the empty id. */ /* All constraints listening to state changes are on the empty id. */
TypeSet *types = object->maybeGetProperty(JSID_EMPTY, cx); TypeSet *types = object->maybeGetProperty(cxArg, JSID_EMPTY);
/* Mark as unknown after getting the types, to avoid assertion. */ /* Mark as unknown after getting the types, to avoid assertion. */
if (markingUnknown) if (markingUnknown)
object->flags |= OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES; object->flags |= OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES;
if (types) { if (types) {
TypeConstraint *constraint = types->constraintList; if (JSContext *cx = cxArg->maybeJSContext()) {
while (constraint) { TypeConstraint *constraint = types->constraintList;
constraint->newObjectState(cx, object, force); while (constraint) {
constraint = constraint->next; constraint->newObjectState(cx, object, force);
constraint = constraint->next;
}
} else {
JS_ASSERT(!types->constraintList);
} }
} }
} }
@ -2192,7 +2197,7 @@ StackTypeSet::propertyNeedsBarrier(JSContext *cx, jsid id)
if (otype->unknownProperties()) if (otype->unknownProperties())
return true; return true;
if (types::HeapTypeSet *propTypes = otype->maybeGetProperty(typeId, cx)) { if (types::HeapTypeSet *propTypes = otype->maybeGetProperty(cx, typeId)) {
if (propTypes->needsBarrier(cx)) if (propTypes->needsBarrier(cx))
return true; return true;
} }
@ -2612,7 +2617,7 @@ TypeCompartment::processPendingRecompiles(FreeOp *fop)
} }
void void
TypeCompartment::setPendingNukeTypes(JSContext *cx) TypeCompartment::setPendingNukeTypes(ExclusiveContext *cx)
{ {
TypeZone *zone = &compartment()->zone()->types; TypeZone *zone = &compartment()->zone()->types;
if (!zone->pendingNukeTypes) { if (!zone->pendingNukeTypes) {
@ -3030,9 +3035,9 @@ NumberTypes(Type a, Type b)
* arrays and objects whose type can be fixed. * arrays and objects whose type can be fixed.
*/ */
static inline Type static inline Type
GetValueTypeForTable(JSContext *cx, const Value &v) GetValueTypeForTable(const Value &v)
{ {
Type type = GetValueType(cx, v); Type type = GetValueType(v);
JS_ASSERT(!type.isSingleObject()); JS_ASSERT(!type.isSingleObject());
return type; return type;
} }
@ -3058,7 +3063,8 @@ struct types::ArrayTableKey
}; };
void void
TypeCompartment::setTypeToHomogenousArray(JSContext *cx, JSObject *obj, Type elementType) TypeCompartment::setTypeToHomogenousArray(ExclusiveContext *cx,
JSObject *obj, Type elementType)
{ {
if (!arrayTypeTable) { if (!arrayTypeTable) {
arrayTypeTable = cx->new_<ArrayTypeTable>(); arrayTypeTable = cx->new_<ArrayTypeTable>();
@ -3097,7 +3103,7 @@ TypeCompartment::setTypeToHomogenousArray(JSContext *cx, JSObject *obj, Type ele
} }
void void
TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj) TypeCompartment::fixArrayType(ExclusiveContext *cx, JSObject *obj)
{ {
AutoEnterAnalysis enter(cx); AutoEnterAnalysis enter(cx);
@ -3113,10 +3119,10 @@ TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj)
if (len == 0) if (len == 0)
return; return;
Type type = GetValueTypeForTable(cx, obj->getDenseElement(0)); Type type = GetValueTypeForTable(obj->getDenseElement(0));
for (unsigned i = 1; i < len; i++) { for (unsigned i = 1; i < len; i++) {
Type ntype = GetValueTypeForTable(cx, obj->getDenseElement(i)); Type ntype = GetValueTypeForTable(obj->getDenseElement(i));
if (ntype != type) { if (ntype != type) {
if (NumberTypes(type, ntype)) if (NumberTypes(type, ntype))
type = Type::DoubleType(); type = Type::DoubleType();
@ -3129,17 +3135,14 @@ TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj)
} }
void void
types::FixRestArgumentsType(ExclusiveContext *cxArg, JSObject *obj) types::FixRestArgumentsType(ExclusiveContext *cx, JSObject *obj)
{ {
if (cxArg->isJSContext()) { if (cx->typeInferenceEnabled())
JSContext *cx = cxArg->asJSContext(); cx->compartment()->types.fixRestArgumentsType(cx, obj);
if (cx->typeInferenceEnabled())
cx->compartment()->types.fixRestArgumentsType(cx, obj);
}
} }
void void
TypeCompartment::fixRestArgumentsType(JSContext *cx, JSObject *obj) TypeCompartment::fixRestArgumentsType(ExclusiveContext *cx, JSObject *obj)
{ {
AutoEnterAnalysis enter(cx); AutoEnterAnalysis enter(cx);
@ -3199,14 +3202,14 @@ struct types::ObjectTableEntry
}; };
static inline void static inline void
UpdateObjectTableEntryTypes(JSContext *cx, ObjectTableEntry &entry, UpdateObjectTableEntryTypes(ExclusiveContext *cx, ObjectTableEntry &entry,
IdValuePair *properties, size_t nproperties) IdValuePair *properties, size_t nproperties)
{ {
if (entry.object->unknownProperties()) if (entry.object->unknownProperties())
return; return;
for (size_t i = 0; i < nproperties; i++) { for (size_t i = 0; i < nproperties; i++) {
Type type = entry.types[i]; Type type = entry.types[i];
Type ntype = GetValueTypeForTable(cx, properties[i].value); Type ntype = GetValueTypeForTable(properties[i].value);
if (ntype == type) if (ntype == type)
continue; continue;
if (ntype.isPrimitive(JSVAL_TYPE_INT32) && if (ntype.isPrimitive(JSVAL_TYPE_INT32) &&
@ -3226,7 +3229,7 @@ UpdateObjectTableEntryTypes(JSContext *cx, ObjectTableEntry &entry,
} }
void void
TypeCompartment::fixObjectType(JSContext *cx, JSObject *obj) TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj)
{ {
AutoEnterAnalysis enter(cx); AutoEnterAnalysis enter(cx);
@ -3299,7 +3302,7 @@ TypeCompartment::fixObjectType(JSContext *cx, JSObject *obj)
for (size_t i = 0; i < properties.length(); i++) { for (size_t i = 0; i < properties.length(); i++) {
ids[i] = properties[i].id; ids[i] = properties[i].id;
types[i] = GetValueTypeForTable(cx, obj->getSlot(i)); types[i] = GetValueTypeForTable(obj->getSlot(i));
if (!objType->unknownProperties()) if (!objType->unknownProperties())
objType->addPropertyType(cx, IdToTypeId(ids[i]), types[i]); objType->addPropertyType(cx, IdToTypeId(ids[i]), types[i]);
} }
@ -3427,7 +3430,7 @@ TypeObject::getFromPrototypes(JSContext *cx, jsid id, TypeSet *types, bool force
} }
static inline void static inline void
UpdatePropertyType(JSContext *cx, TypeSet *types, JSObject *obj, Shape *shape, UpdatePropertyType(ExclusiveContext *cx, TypeSet *types, JSObject *obj, Shape *shape,
bool force) bool force)
{ {
types->setOwnProperty(cx, false); types->setOwnProperty(cx, false);
@ -3445,14 +3448,14 @@ UpdatePropertyType(JSContext *cx, TypeSet *types, JSObject *obj, Shape *shape,
* not collated into the JSID_VOID property (see propertySet comment). * not collated into the JSID_VOID property (see propertySet comment).
*/ */
if (force || !value.isUndefined()) { if (force || !value.isUndefined()) {
Type type = GetValueType(cx, value); Type type = GetValueType(value);
types->addType(cx, type); types->addType(cx, type);
} }
} }
} }
bool bool
TypeObject::addProperty(JSContext *cx, jsid id, Property **pprop) TypeObject::addProperty(ExclusiveContext *cx, jsid id, Property **pprop)
{ {
JS_ASSERT(!*pprop); JS_ASSERT(!*pprop);
Property *base = cx->typeLifoAlloc().new_<Property>(id); Property *base = cx->typeLifoAlloc().new_<Property>(id);
@ -3483,7 +3486,7 @@ TypeObject::addProperty(JSContext *cx, jsid id, Property **pprop)
for (size_t i = 0; i < singleton->getDenseInitializedLength(); i++) { for (size_t i = 0; i < singleton->getDenseInitializedLength(); i++) {
const Value &value = singleton->getDenseElement(i); const Value &value = singleton->getDenseElement(i);
if (!value.isMagic(JS_ELEMENTS_HOLE)) { if (!value.isMagic(JS_ELEMENTS_HOLE)) {
Type type = GetValueType(cx, value); Type type = GetValueType(value);
base->types.setOwnProperty(cx, false); base->types.setOwnProperty(cx, false);
base->types.addType(cx, type); base->types.addType(cx, type);
} }
@ -3514,7 +3517,7 @@ TypeObject::addProperty(JSContext *cx, jsid id, Property **pprop)
} }
bool bool
TypeObject::addDefiniteProperties(JSContext *cx, JSObject *obj) TypeObject::addDefiniteProperties(ExclusiveContext *cx, JSObject *obj)
{ {
if (unknownProperties()) if (unknownProperties())
return true; return true;
@ -3567,7 +3570,7 @@ TypeObject::matchDefiniteProperties(HandleObject obj)
} }
inline void inline void
InlineAddTypeProperty(JSContext *cx, TypeObject *obj, jsid id, Type type) InlineAddTypeProperty(ExclusiveContext *cx, TypeObject *obj, jsid id, Type type)
{ {
JS_ASSERT(id == IdToTypeId(id)); JS_ASSERT(id == IdToTypeId(id));
@ -3583,19 +3586,19 @@ InlineAddTypeProperty(JSContext *cx, TypeObject *obj, jsid id, Type type)
} }
void void
TypeObject::addPropertyType(JSContext *cx, jsid id, Type type) TypeObject::addPropertyType(ExclusiveContext *cx, jsid id, Type type)
{ {
InlineAddTypeProperty(cx, this, id, type); InlineAddTypeProperty(cx, this, id, type);
} }
void void
TypeObject::addPropertyType(JSContext *cx, jsid id, const Value &value) TypeObject::addPropertyType(ExclusiveContext *cx, jsid id, const Value &value)
{ {
InlineAddTypeProperty(cx, this, id, GetValueType(cx, value)); InlineAddTypeProperty(cx, this, id, GetValueType(value));
} }
void void
TypeObject::addPropertyType(JSContext *cx, const char *name, Type type) TypeObject::addPropertyType(ExclusiveContext *cx, const char *name, Type type)
{ {
jsid id = JSID_VOID; jsid id = JSID_VOID;
if (name) { if (name) {
@ -3611,13 +3614,13 @@ TypeObject::addPropertyType(JSContext *cx, const char *name, Type type)
} }
void void
TypeObject::addPropertyType(JSContext *cx, const char *name, const Value &value) TypeObject::addPropertyType(ExclusiveContext *cx, const char *name, const Value &value)
{ {
addPropertyType(cx, name, GetValueType(cx, value)); addPropertyType(cx, name, GetValueType(value));
} }
void void
TypeObject::markPropertyConfigured(JSContext *cx, jsid id) TypeObject::markPropertyConfigured(ExclusiveContext *cx, jsid id)
{ {
AutoEnterAnalysis enter(cx); AutoEnterAnalysis enter(cx);
@ -3629,24 +3632,28 @@ TypeObject::markPropertyConfigured(JSContext *cx, jsid id)
} }
void void
TypeObject::markStateChange(JSContext *cx) TypeObject::markStateChange(ExclusiveContext *cxArg)
{ {
if (unknownProperties()) if (unknownProperties())
return; return;
AutoEnterAnalysis enter(cx); AutoEnterAnalysis enter(cxArg);
TypeSet *types = maybeGetProperty(JSID_EMPTY, cx); TypeSet *types = maybeGetProperty(cxArg, JSID_EMPTY);
if (types) { if (types) {
TypeConstraint *constraint = types->constraintList; if (JSContext *cx = cxArg->maybeJSContext()) {
while (constraint) { TypeConstraint *constraint = types->constraintList;
constraint->newObjectState(cx, this, true); while (constraint) {
constraint = constraint->next; constraint->newObjectState(cx, this, true);
constraint = constraint->next;
}
} else {
JS_ASSERT(!types->constraintList);
} }
} }
} }
void void
TypeObject::setFlags(JSContext *cx, TypeObjectFlags flags) TypeObject::setFlags(ExclusiveContext *cx, TypeObjectFlags flags)
{ {
if ((this->flags & flags) == flags) if ((this->flags & flags) == flags)
return; return;
@ -3667,7 +3674,7 @@ TypeObject::setFlags(JSContext *cx, TypeObjectFlags flags)
} }
void void
TypeObject::markUnknown(JSContext *cx) TypeObject::markUnknown(ExclusiveContext *cx)
{ {
AutoEnterAnalysis enter(cx); AutoEnterAnalysis enter(cx);
@ -3701,7 +3708,7 @@ TypeObject::markUnknown(JSContext *cx)
} }
void void
TypeObject::clearNewScript(JSContext *cx) TypeObject::clearNewScript(ExclusiveContext *cx)
{ {
JS_ASSERT(!(flags & OBJECT_FLAG_NEW_SCRIPT_CLEARED)); JS_ASSERT(!(flags & OBJECT_FLAG_NEW_SCRIPT_CLEARED));
flags |= OBJECT_FLAG_NEW_SCRIPT_CLEARED; flags |= OBJECT_FLAG_NEW_SCRIPT_CLEARED;
@ -3744,69 +3751,74 @@ TypeObject::clearNewScript(JSContext *cx)
* script keeps track of where each property is initialized so we can walk * script keeps track of where each property is initialized so we can walk
* the stack and fix up any such objects. * the stack and fix up any such objects.
*/ */
Vector<uint32_t, 32> pcOffsets(cx); if (cx->isJSContext()) {
for (ScriptFrameIter iter(cx); !iter.done(); ++iter) { Vector<uint32_t, 32> pcOffsets(cx);
pcOffsets.append(uint32_t(iter.pc() - iter.script()->code)); for (ScriptFrameIter iter(cx->asJSContext()); !iter.done(); ++iter) {
if (iter.isConstructing() && pcOffsets.append(uint32_t(iter.pc() - iter.script()->code));
iter.callee() == newScript->fun && if (iter.isConstructing() &&
iter.thisv().isObject() && iter.callee() == newScript->fun &&
!iter.thisv().toObject().hasLazyType() && iter.thisv().isObject() &&
iter.thisv().toObject().type() == this) !iter.thisv().toObject().hasLazyType() &&
{ iter.thisv().toObject().type() == this)
RootedObject obj(cx, &iter.thisv().toObject()); {
RootedObject obj(cx, &iter.thisv().toObject());
/* Whether all identified 'new' properties have been initialized. */ /* Whether all identified 'new' properties have been initialized. */
bool finished = false; bool finished = false;
/* If not finished, number of properties that have been added. */ /* If not finished, number of properties that have been added. */
uint32_t numProperties = 0; uint32_t numProperties = 0;
/* /*
* If non-zero, we are scanning initializers in a call which has * If non-zero, we are scanning initializers in a call which has
* already finished. * already finished.
*/ */
size_t depth = 0; size_t depth = 0;
size_t callDepth = pcOffsets.length() - 1; size_t callDepth = pcOffsets.length() - 1;
uint32_t offset = pcOffsets[callDepth]; uint32_t offset = pcOffsets[callDepth];
for (TypeNewScript::Initializer *init = newScript->initializerList;; init++) { for (TypeNewScript::Initializer *init = newScript->initializerList;; init++) {
if (init->kind == TypeNewScript::Initializer::SETPROP) { if (init->kind == TypeNewScript::Initializer::SETPROP) {
if (!depth && init->offset > offset) { if (!depth && init->offset > offset) {
/* Advanced past all properties which have been initialized. */ /* Advanced past all properties which have been initialized. */
break;
}
numProperties++;
} else if (init->kind == TypeNewScript::Initializer::FRAME_PUSH) {
if (depth) {
depth++;
} else if (init->offset > offset) {
/* Advanced past all properties which have been initialized. */
break;
} else if (init->offset == offset) {
if (!callDepth)
break; break;
offset = pcOffsets[--callDepth]; }
numProperties++;
} else if (init->kind == TypeNewScript::Initializer::FRAME_PUSH) {
if (depth) {
depth++;
} else if (init->offset > offset) {
/* Advanced past all properties which have been initialized. */
break;
} else if (init->offset == offset) {
if (!callDepth)
break;
offset = pcOffsets[--callDepth];
} else {
/* This call has already finished. */
depth = 1;
}
} else if (init->kind == TypeNewScript::Initializer::FRAME_POP) {
if (depth) {
depth--;
} else {
/* This call has not finished yet. */
break;
}
} else { } else {
/* This call has already finished. */ JS_ASSERT(init->kind == TypeNewScript::Initializer::DONE);
depth = 1; finished = true;
}
} else if (init->kind == TypeNewScript::Initializer::FRAME_POP) {
if (depth) {
depth--;
} else {
/* This call has not finished yet. */
break; break;
} }
} else {
JS_ASSERT(init->kind == TypeNewScript::Initializer::DONE);
finished = true;
break;
} }
}
if (!finished) if (!finished)
obj->rollbackProperties(cx, numProperties); obj->rollbackProperties(cx, numProperties);
}
} }
} else {
// Threads with an ExclusiveContext are not allowed to run scripts.
JS_ASSERT(!cx->perThreadData->activation());
} }
/* We NULL out newScript *before* freeing it so the write barrier works. */ /* We NULL out newScript *before* freeing it so the write barrier works. */
@ -5029,7 +5041,7 @@ AnalyzePoppedThis(JSContext *cx, SSAUseChain *use,
if (shape && shape->hasSlot()) { if (shape && shape->hasSlot()) {
Value protov = type->proto->getSlot(shape->slot()); Value protov = type->proto->getSlot(shape->slot());
TypeSet *types = TypeScript::BytecodeTypes(script, pc); TypeSet *types = TypeScript::BytecodeTypes(script, pc);
types->addType(cx, GetValueType(cx, protov)); types->addType(cx, GetValueType(protov));
} }
return true; return true;
@ -5530,7 +5542,7 @@ types::TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const
return; return;
} }
Type type = GetValueType(cx, rval); Type type = GetValueType(rval);
TypeSet *types = TypeScript::BytecodeTypes(script, pc); TypeSet *types = TypeScript::BytecodeTypes(script, pc);
if (types->hasType(type)) if (types->hasType(type))
return; return;
@ -5804,14 +5816,12 @@ JSScript::makeAnalysis(JSContext *cx)
} }
/* static */ bool /* static */ bool
JSFunction::setTypeForScriptedFunction(ExclusiveContext *cxArg, HandleFunction fun, JSFunction::setTypeForScriptedFunction(ExclusiveContext *cx, HandleFunction fun,
bool singleton /* = false */) bool singleton /* = false */)
{ {
if (!cxArg->typeInferenceEnabled()) if (!cx->typeInferenceEnabled())
return true; return true;
JSContext *cx = cxArg->asJSContext();
if (singleton) { if (singleton) {
if (!setSingletonType(cx, fun)) if (!setSingletonType(cx, fun))
return false; return false;
@ -6051,7 +6061,7 @@ ExclusiveContext::getNewType(Class *clasp, TaggedProto proto_, JSFunction *fun_)
* 'prototype' property of some scripted function. * 'prototype' property of some scripted function.
*/ */
if (type->newScript && type->newScript->fun != fun_) if (type->newScript && type->newScript->fun != fun_)
type->clearNewScript(asJSContext()); type->clearNewScript(this);
return type; return type;
} }
@ -6077,8 +6087,7 @@ ExclusiveContext::getNewType(Class *clasp, TaggedProto proto_, JSFunction *fun_)
if (!typeInferenceEnabled()) if (!typeInferenceEnabled())
return type; return type;
JSContext *cx = asJSContext(); AutoEnterAnalysis enter(this);
AutoEnterAnalysis enter(cx);
/* /*
* Set the special equality flag for types whose prototype also has the * Set the special equality flag for types whose prototype also has the
@ -6086,22 +6095,22 @@ ExclusiveContext::getNewType(Class *clasp, TaggedProto proto_, JSFunction *fun_)
* types and the possible js::Class of objects with that type. * types and the possible js::Class of objects with that type.
*/ */
if (proto.isObject()) { if (proto.isObject()) {
RootedObject obj(cx, proto.toObject()); RootedObject obj(this, proto.toObject());
if (fun) if (fun)
CheckNewScriptProperties(cx, type, fun); CheckNewScriptProperties(asJSContext(), type, fun);
if (obj->is<RegExpObject>()) { if (obj->is<RegExpObject>()) {
AddTypeProperty(cx, type, "source", types::Type::StringType()); AddTypeProperty(this, type, "source", types::Type::StringType());
AddTypeProperty(cx, type, "global", types::Type::BooleanType()); AddTypeProperty(this, type, "global", types::Type::BooleanType());
AddTypeProperty(cx, type, "ignoreCase", types::Type::BooleanType()); AddTypeProperty(this, type, "ignoreCase", types::Type::BooleanType());
AddTypeProperty(cx, type, "multiline", types::Type::BooleanType()); AddTypeProperty(this, type, "multiline", types::Type::BooleanType());
AddTypeProperty(cx, type, "sticky", types::Type::BooleanType()); AddTypeProperty(this, type, "sticky", types::Type::BooleanType());
AddTypeProperty(cx, type, "lastIndex", types::Type::Int32Type()); AddTypeProperty(this, type, "lastIndex", types::Type::Int32Type());
} }
if (obj->is<StringObject>()) if (obj->is<StringObject>())
AddTypeProperty(cx, type, "length", Type::Int32Type()); AddTypeProperty(this, type, "length", Type::Int32Type());
} }
/* /*

View File

@ -204,7 +204,7 @@ class Type
}; };
/* Get the type of a jsval, or zero for an unknown special value. */ /* Get the type of a jsval, or zero for an unknown special value. */
inline Type GetValueType(JSContext *cx, const Value &val); inline Type GetValueType(const Value &val);
/* /*
* Type inference memory management overview. * Type inference memory management overview.
@ -489,10 +489,10 @@ class TypeSet
* Add a type to this set, calling any constraint handlers if this is a new * Add a type to this set, calling any constraint handlers if this is a new
* possible type. * possible type.
*/ */
inline void addType(JSContext *cx, Type type); inline void addType(ExclusiveContext *cx, Type type);
/* Mark this type set as representing an own property or configured property. */ /* Mark this type set as representing an own property or configured property. */
inline void setOwnProperty(JSContext *cx, bool configured); inline void setOwnProperty(ExclusiveContext *cx, bool configured);
/* /*
* Add an object to this set using the specified allocator, without * Add an object to this set using the specified allocator, without
@ -1040,10 +1040,10 @@ struct TypeObject : gc::Cell
* assignment, and the own types of the property will be used instead of * assignment, and the own types of the property will be used instead of
* aggregate types. * aggregate types.
*/ */
inline HeapTypeSet *getProperty(JSContext *cx, jsid id, bool own); inline HeapTypeSet *getProperty(ExclusiveContext *cx, jsid id, bool own);
/* Get a property only if it already exists. */ /* Get a property only if it already exists. */
inline HeapTypeSet *maybeGetProperty(jsid id, JSContext *cx); inline HeapTypeSet *maybeGetProperty(ExclusiveContext *cx, jsid id);
inline unsigned getPropertyCount(); inline unsigned getPropertyCount();
inline Property *getProperty(unsigned i); inline Property *getProperty(unsigned i);
@ -1056,19 +1056,19 @@ struct TypeObject : gc::Cell
/* Helpers */ /* Helpers */
bool addProperty(JSContext *cx, jsid id, Property **pprop); bool addProperty(ExclusiveContext *cx, jsid id, Property **pprop);
bool addDefiniteProperties(JSContext *cx, JSObject *obj); bool addDefiniteProperties(ExclusiveContext *cx, JSObject *obj);
bool matchDefiniteProperties(HandleObject obj); bool matchDefiniteProperties(HandleObject obj);
void addPrototype(JSContext *cx, TypeObject *proto); void addPrototype(JSContext *cx, TypeObject *proto);
void addPropertyType(JSContext *cx, jsid id, Type type); void addPropertyType(ExclusiveContext *cx, jsid id, Type type);
void addPropertyType(JSContext *cx, jsid id, const Value &value); void addPropertyType(ExclusiveContext *cx, jsid id, const Value &value);
void addPropertyType(JSContext *cx, const char *name, Type type); void addPropertyType(ExclusiveContext *cx, const char *name, Type type);
void addPropertyType(JSContext *cx, const char *name, const Value &value); void addPropertyType(ExclusiveContext *cx, const char *name, const Value &value);
void markPropertyConfigured(JSContext *cx, jsid id); void markPropertyConfigured(ExclusiveContext *cx, jsid id);
void markStateChange(JSContext *cx); void markStateChange(ExclusiveContext *cx);
void setFlags(JSContext *cx, TypeObjectFlags flags); void setFlags(ExclusiveContext *cx, TypeObjectFlags flags);
void markUnknown(JSContext *cx); void markUnknown(ExclusiveContext *cx);
void clearNewScript(JSContext *cx); void clearNewScript(ExclusiveContext *cx);
void getFromPrototypes(JSContext *cx, jsid id, TypeSet *types, bool force = false); void getFromPrototypes(JSContext *cx, jsid id, TypeSet *types, bool force = false);
void print(); void print();
@ -1368,12 +1368,12 @@ struct TypeCompartment
ObjectTypeTable *objectTypeTable; ObjectTypeTable *objectTypeTable;
private: private:
void setTypeToHomogenousArray(JSContext *cx, JSObject *obj, Type type); void setTypeToHomogenousArray(ExclusiveContext *cx, JSObject *obj, Type type);
public: public:
void fixArrayType(JSContext *cx, JSObject *obj); void fixArrayType(ExclusiveContext *cx, JSObject *obj);
void fixObjectType(JSContext *cx, JSObject *obj); void fixObjectType(ExclusiveContext *cx, JSObject *obj);
void fixRestArgumentsType(JSContext *cx, JSObject *obj); void fixRestArgumentsType(ExclusiveContext *cx, JSObject *obj);
JSObject *newTypedObject(JSContext *cx, IdValuePair *properties, size_t nproperties); JSObject *newTypedObject(JSContext *cx, IdValuePair *properties, size_t nproperties);
@ -1414,7 +1414,7 @@ struct TypeCompartment
void processPendingRecompiles(FreeOp *fop); void processPendingRecompiles(FreeOp *fop);
/* Mark all types as needing destruction once inference has 'finished'. */ /* Mark all types as needing destruction once inference has 'finished'. */
void setPendingNukeTypes(JSContext *cx); void setPendingNukeTypes(ExclusiveContext *cx);
/* Mark a script as needing recompilation once inference has finished. */ /* Mark a script as needing recompilation once inference has finished. */
void addPendingRecompile(JSContext *cx, const RecompileInfo &info); void addPendingRecompile(JSContext *cx, const RecompileInfo &info);

View File

@ -185,9 +185,8 @@ Type::ObjectType(TypeObjectKey *obj)
} }
inline Type inline Type
GetValueType(JSContext *cx, const Value &val) GetValueType(const Value &val)
{ {
JS_ASSERT(cx->typeInferenceEnabled());
if (val.isDouble()) if (val.isDouble())
return Type::DoubleType(); return Type::DoubleType();
if (val.isObject()) if (val.isObject())
@ -310,10 +309,10 @@ struct AutoEnterAnalysis
JSCompartment *compartment; JSCompartment *compartment;
bool oldActiveAnalysis; bool oldActiveAnalysis;
AutoEnterAnalysis(JSContext *cx) AutoEnterAnalysis(ExclusiveContext *cx)
: suppressGC(cx) : suppressGC(cx)
{ {
init(cx->runtime()->defaultFreeOp(), cx->compartment()); init(cx->defaultFreeOp(), cx->compartment());
} }
AutoEnterAnalysis(FreeOp *fop, JSCompartment *comp) AutoEnterAnalysis(FreeOp *fop, JSCompartment *comp)
@ -535,7 +534,7 @@ TrackPropertyTypes(ExclusiveContext *cx, JSObject *obj, jsid id)
if (!cx->typeInferenceEnabled() || obj->hasLazyType() || obj->type()->unknownProperties()) if (!cx->typeInferenceEnabled() || obj->hasLazyType() || obj->type()->unknownProperties())
return false; return false;
if (obj->hasSingletonType() && !obj->type()->maybeGetProperty(id, cx->asJSContext())) if (obj->hasSingletonType() && !obj->type()->maybeGetProperty(cx, id))
return false; return false;
return true; return true;
@ -566,7 +565,7 @@ AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, Type type)
if (cx->typeInferenceEnabled()) { if (cx->typeInferenceEnabled()) {
id = IdToTypeId(id); id = IdToTypeId(id);
if (TrackPropertyTypes(cx, obj, id)) if (TrackPropertyTypes(cx, obj, id))
obj->type()->addPropertyType(cx->asJSContext(), id, type); obj->type()->addPropertyType(cx, id, type);
} }
} }
@ -576,19 +575,19 @@ AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, const Value &val
if (cx->typeInferenceEnabled()) { if (cx->typeInferenceEnabled()) {
id = IdToTypeId(id); id = IdToTypeId(id);
if (TrackPropertyTypes(cx, obj, id)) if (TrackPropertyTypes(cx, obj, id))
obj->type()->addPropertyType(cx->asJSContext(), id, value); obj->type()->addPropertyType(cx, id, value);
} }
} }
inline void inline void
AddTypeProperty(JSContext *cx, TypeObject *obj, const char *name, Type type) AddTypeProperty(ExclusiveContext *cx, TypeObject *obj, const char *name, Type type)
{ {
if (cx->typeInferenceEnabled() && !obj->unknownProperties()) if (cx->typeInferenceEnabled() && !obj->unknownProperties())
obj->addPropertyType(cx, name, type); obj->addPropertyType(cx, name, type);
} }
inline void inline void
AddTypeProperty(JSContext *cx, TypeObject *obj, const char *name, const Value &value) AddTypeProperty(ExclusiveContext *cx, TypeObject *obj, const char *name, const Value &value)
{ {
if (cx->typeInferenceEnabled() && !obj->unknownProperties()) if (cx->typeInferenceEnabled() && !obj->unknownProperties())
obj->addPropertyType(cx, name, value); obj->addPropertyType(cx, name, value);
@ -599,7 +598,7 @@ inline void
MarkTypeObjectFlags(ExclusiveContext *cx, JSObject *obj, TypeObjectFlags flags) MarkTypeObjectFlags(ExclusiveContext *cx, JSObject *obj, TypeObjectFlags flags)
{ {
if (cx->typeInferenceEnabled() && !obj->hasLazyType() && !obj->type()->hasAllFlags(flags)) if (cx->typeInferenceEnabled() && !obj->hasLazyType() && !obj->type()->hasAllFlags(flags))
obj->type()->setFlags(cx->asJSContext(), flags); obj->type()->setFlags(cx, flags);
} }
/* /*
@ -630,7 +629,7 @@ MarkTypePropertyConfigured(ExclusiveContext *cx, HandleObject obj, jsid id)
if (cx->typeInferenceEnabled()) { if (cx->typeInferenceEnabled()) {
id = IdToTypeId(id); id = IdToTypeId(id);
if (TrackPropertyTypes(cx, obj, id)) if (TrackPropertyTypes(cx, obj, id))
obj->type()->markPropertyConfigured(cx->asJSContext(), id); obj->type()->markPropertyConfigured(cx, id);
} }
} }
@ -639,7 +638,7 @@ inline void
MarkObjectStateChange(ExclusiveContext *cx, JSObject *obj) MarkObjectStateChange(ExclusiveContext *cx, JSObject *obj)
{ {
if (cx->typeInferenceEnabled() && !obj->hasLazyType() && !obj->type()->unknownProperties()) if (cx->typeInferenceEnabled() && !obj->hasLazyType() && !obj->type()->unknownProperties())
obj->type()->markStateChange(cx->asJSContext()); obj->type()->markStateChange(cx);
} }
/* /*
@ -648,23 +647,17 @@ MarkObjectStateChange(ExclusiveContext *cx, JSObject *obj)
*/ */
inline void inline void
FixArrayType(ExclusiveContext *cxArg, HandleObject obj) FixArrayType(ExclusiveContext *cx, HandleObject obj)
{ {
if (cxArg->isJSContext()) { if (cx->typeInferenceEnabled())
JSContext *cx = cxArg->asJSContext(); cx->compartment()->types.fixArrayType(cx, obj);
if (cx->typeInferenceEnabled())
cx->compartment()->types.fixArrayType(cx, obj);
}
} }
inline void inline void
FixObjectType(ExclusiveContext *cxArg, HandleObject obj) FixObjectType(ExclusiveContext *cx, HandleObject obj)
{ {
if (cxArg->isJSContext()) { if (cx->typeInferenceEnabled())
JSContext *cx = cxArg->asJSContext(); cx->compartment()->types.fixObjectType(cx, obj);
if (cx->typeInferenceEnabled())
cx->compartment()->types.fixObjectType(cx, obj);
}
} }
/* Interface helpers for JSScript*. */ /* Interface helpers for JSScript*. */
@ -970,7 +963,7 @@ TypeScript::SetThis(JSContext *cx, JSScript *script, Type type)
TypeScript::SetThis(JSContext *cx, JSScript *script, const js::Value &value) TypeScript::SetThis(JSContext *cx, JSScript *script, const js::Value &value)
{ {
if (cx->typeInferenceEnabled()) if (cx->typeInferenceEnabled())
SetThis(cx, script, GetValueType(cx, value)); SetThis(cx, script, GetValueType(value));
} }
/* static */ inline void /* static */ inline void
@ -992,7 +985,7 @@ TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value) TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value)
{ {
if (cx->typeInferenceEnabled()) { if (cx->typeInferenceEnabled()) {
Type type = GetValueType(cx, value); Type type = GetValueType(value);
SetArgument(cx, script, arg, type); SetArgument(cx, script, arg, type);
} }
} }
@ -1280,9 +1273,9 @@ TypeSet::clearObjects()
} }
inline void inline void
TypeSet::addType(JSContext *cx, Type type) TypeSet::addType(ExclusiveContext *cxArg, Type type)
{ {
JS_ASSERT(cx->compartment()->activeAnalysis); JS_ASSERT(cxArg->compartment()->activeAnalysis);
if (unknown()) if (unknown())
return; return;
@ -1308,14 +1301,14 @@ TypeSet::addType(JSContext *cx, Type type)
goto unknownObject; goto unknownObject;
LifoAlloc &alloc = LifoAlloc &alloc =
purged() ? cx->compartment()->analysisLifoAlloc : cx->typeLifoAlloc(); purged() ? cxArg->compartment()->analysisLifoAlloc : cxArg->typeLifoAlloc();
uint32_t objectCount = baseObjectCount(); uint32_t objectCount = baseObjectCount();
TypeObjectKey *object = type.objectKey(); TypeObjectKey *object = type.objectKey();
TypeObjectKey **pentry = HashSetInsert<TypeObjectKey *,TypeObjectKey,TypeObjectKey> TypeObjectKey **pentry = HashSetInsert<TypeObjectKey *,TypeObjectKey,TypeObjectKey>
(alloc, objectSet, objectCount, object); (alloc, objectSet, objectCount, object);
if (!pentry) { if (!pentry) {
cx->compartment()->types.setPendingNukeTypes(cx); cxArg->compartment()->types.setPendingNukeTypes(cxArg);
return; return;
} }
if (*pentry) if (*pentry)
@ -1347,17 +1340,20 @@ TypeSet::addType(JSContext *cx, Type type)
TypeString(type)); TypeString(type));
/* Propagate the type to all constraints. */ /* Propagate the type to all constraints. */
TypeConstraint *constraint = constraintList; if (JSContext *cx = cxArg->maybeJSContext()) {
while (constraint) { TypeConstraint *constraint = constraintList;
cx->compartment()->types.addPending(cx, constraint, this, type); while (constraint) {
constraint = constraint->next; cx->compartment()->types.addPending(cx, constraint, this, type);
constraint = constraint->next;
}
cx->compartment()->types.resolvePending(cx);
} else {
JS_ASSERT(!constraintList);
} }
cx->compartment()->types.resolvePending(cx);
} }
inline void inline void
TypeSet::setOwnProperty(JSContext *cx, bool configured) TypeSet::setOwnProperty(ExclusiveContext *cxArg, bool configured)
{ {
TypeFlags nflags = TYPE_FLAG_OWN_PROPERTY | (configured ? TYPE_FLAG_CONFIGURED_PROPERTY : 0); TypeFlags nflags = TYPE_FLAG_OWN_PROPERTY | (configured ? TYPE_FLAG_CONFIGURED_PROPERTY : 0);
@ -1367,10 +1363,14 @@ TypeSet::setOwnProperty(JSContext *cx, bool configured)
flags |= nflags; flags |= nflags;
/* Propagate the change to all constraints. */ /* Propagate the change to all constraints. */
TypeConstraint *constraint = constraintList; if (JSContext *cx = cxArg->maybeJSContext()) {
while (constraint) { TypeConstraint *constraint = constraintList;
constraint->newPropertyState(cx, this); while (constraint) {
constraint = constraint->next; constraint->newPropertyState(cx, this);
constraint = constraint->next;
}
} else {
JS_ASSERT(!constraintList);
} }
} }
@ -1476,7 +1476,7 @@ TypeObject::setBasePropertyCount(uint32_t count)
} }
inline HeapTypeSet * inline HeapTypeSet *
TypeObject::getProperty(JSContext *cx, jsid id, bool own) TypeObject::getProperty(ExclusiveContext *cx, jsid id, bool own)
{ {
JS_ASSERT(cx->compartment()->activeAnalysis); JS_ASSERT(cx->compartment()->activeAnalysis);
@ -1524,7 +1524,7 @@ TypeObject::getProperty(JSContext *cx, jsid id, bool own)
} }
inline HeapTypeSet * inline HeapTypeSet *
TypeObject::maybeGetProperty(jsid id, JSContext *cx) TypeObject::maybeGetProperty(ExclusiveContext *cx, jsid id)
{ {
JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id)); JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id)); JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));

View File

@ -377,7 +377,7 @@ class JSObject : public js::ObjectImpl
inline void prepareSlotRangeForOverwrite(size_t start, size_t end); inline void prepareSlotRangeForOverwrite(size_t start, size_t end);
inline void prepareElementRangeForOverwrite(size_t start, size_t end); inline void prepareElementRangeForOverwrite(size_t start, size_t end);
void rollbackProperties(JSContext *cx, uint32_t slotSpan); void rollbackProperties(js::ExclusiveContext *cx, uint32_t slotSpan);
inline void nativeSetSlot(uint32_t slot, const js::Value &value); inline void nativeSetSlot(uint32_t slot, const js::Value &value);
static inline void nativeSetSlotWithType(js::ExclusiveContext *cx, static inline void nativeSetSlotWithType(js::ExclusiveContext *cx,

View File

@ -226,12 +226,7 @@ js::StartOffThreadParseScript(JSContext *cx, const CompileOptions &options,
if (!global) if (!global)
return false; return false;
// For now, type inference is always disabled in exclusive zones, as type global->zone()->types.inferenceEnabled = cx->typeInferenceEnabled();
// inference data is not merged between zones when finishing the off thread
// parse. This restriction would be fairly easy to lift.
JS_ASSERT(!cx->typeInferenceEnabled());
global->zone()->types.inferenceEnabled = false;
JS_SetCompartmentPrincipals(global->compartment(), cx->compartment()->principals); JS_SetCompartmentPrincipals(global->compartment(), cx->compartment()->principals);
RootedObject obj(cx); RootedObject obj(cx);

View File

@ -407,7 +407,9 @@ JSRuntime::~JSRuntime()
PR_DestroyLock(exclusiveAccessLock); PR_DestroyLock(exclusiveAccessLock);
JS_ASSERT(!numExclusiveThreads); JS_ASSERT(!numExclusiveThreads);
exclusiveThreadsPaused = true; // Avoid bogus asserts during teardown.
// Avoid bogus asserts during teardown.
exclusiveThreadsPaused = true;
#endif #endif
/* /*

View File

@ -938,7 +938,7 @@ JSObject::clear(JSContext *cx, HandleObject obj)
} }
void void
JSObject::rollbackProperties(JSContext *cx, uint32_t slotSpan) JSObject::rollbackProperties(ExclusiveContext *cx, uint32_t slotSpan)
{ {
/* /*
* Remove properties from this object until it has a matching slot span. * Remove properties from this object until it has a matching slot span.