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()) {
bool singleton =
cx->isJSContext() &&
cx->asJSContext()->typeInferenceEnabled() &&
cx->typeInferenceEnabled() &&
bce->script->compileAndGo &&
fun->isInterpreted() &&
(bce->checkSingletonContext() ||

View File

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

View File

@ -2546,7 +2546,7 @@ ion::PropertyReadNeedsTypeBarrier(JSContext *cx, types::TypeObject *object, Prop
if (HasDataProperty(cx, obj, id, &v)) {
if (v.isUndefined())
break;
observed->addType(cx, types::GetValueType(cx, v));
observed->addType(cx, types::GetValueType(v));
}
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++) {
if (vector[i].isMagic(JS_ELEMENTS_HOLE))
continue;
Type valtype = GetValueType(cx, vector[i]);
Type valtype = GetValueType(vector[i]);
types->addType(cx, valtype);
}
}

View File

@ -259,10 +259,11 @@ struct ThreadSafeContext : ContextFriendFields,
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; }
StaticStrings &staticStrings() { return runtime_->staticStrings; }
PropertyName *emptyString() { return runtime_->emptyString; }
FreeOp *defaultFreeOp() { return runtime_->defaultFreeOp(); }
// GCs cannot happen while non-main threads are running.
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.
inline bool typeInferenceEnabled() const;
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
// AutoCompartment from which it's called.
@ -483,7 +485,6 @@ struct JSContext : public js::ExclusiveContext,
js::LifoAlloc &tempLifoAlloc() { return runtime()->tempLifoAlloc; }
inline js::LifoAlloc &analysisLifoAlloc();
inline js::LifoAlloc &typeLifoAlloc();
#ifdef JS_THREADSAFE
unsigned outstandingRequests;/* number of JS_BeginRequest calls

View File

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

View File

@ -433,10 +433,6 @@ namespace js {
inline bool
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;
}

View File

@ -4055,6 +4055,13 @@ AutoGCSession::AutoGCSession(JSRuntime *rt)
runtime->gcInterFrameGC = true;
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()
@ -4816,6 +4823,9 @@ gc::MergeCompartments(JSCompartment *source, JSCompartment *target)
target->zone()->allocator.arenas.adoptArenas(rt, &source->zone()->allocator.arenas);
target->zone()->gcBytes += source->zone()->gcBytes;
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
@ -5140,8 +5150,8 @@ AutoMaybeTouchDeadZones::~AutoMaybeTouchDeadZones()
runtime->gcManipulatingDeadZones = manipulatingDeadZones;
}
AutoSuppressGC::AutoSuppressGC(JSContext *cx)
: suppressGC_(cx->runtime()->mainThread.suppressGC)
AutoSuppressGC::AutoSuppressGC(ExclusiveContext *cx)
: suppressGC_(cx->perThreadData->suppressGC)
{
suppressGC_++;
}

View File

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

View File

@ -47,6 +47,7 @@ using namespace js::types;
using namespace js::analyze;
using mozilla::DebugOnly;
using mozilla::Maybe;
using mozilla::PodArrayZero;
using mozilla::PodCopy;
using mozilla::PodZero;
@ -259,7 +260,7 @@ types::TypeHasProperty(JSContext *cx, TypeObject *obj, jsid id, const Value &val
if (cx->compartment()->types.pendingCount)
return true;
Type type = GetValueType(cx, value);
Type type = GetValueType(value);
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.
* Don't do the property instantiation now.
*/
TypeSet *types = obj->maybeGetProperty(id, cx);
TypeSet *types = obj->maybeGetProperty(cx, id);
if (!types)
return true;
@ -1127,7 +1128,7 @@ GetSingletonPropertyType(JSContext *cx, JSObject *rawObjArg, HandleId id)
if (HasDataProperty(cx, obj, id, v.address())) {
if (v.isUndefined())
return Type::UnknownType();
return GetValueType(cx, v);
return GetValueType(v);
}
obj = obj->getProto();
@ -1838,23 +1839,27 @@ HeapTypeSet::HasObjectFlags(JSContext *cx, TypeObject *object, TypeObjectFlags f
}
static inline void
ObjectStateChange(JSContext *cx, TypeObject *object, bool markingUnknown, bool force)
ObjectStateChange(ExclusiveContext *cxArg, TypeObject *object, bool markingUnknown, bool force)
{
if (object->unknownProperties())
return;
/* 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. */
if (markingUnknown)
object->flags |= OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES;
if (types) {
TypeConstraint *constraint = types->constraintList;
while (constraint) {
constraint->newObjectState(cx, object, force);
constraint = constraint->next;
if (JSContext *cx = cxArg->maybeJSContext()) {
TypeConstraint *constraint = types->constraintList;
while (constraint) {
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())
return true;
if (types::HeapTypeSet *propTypes = otype->maybeGetProperty(typeId, cx)) {
if (types::HeapTypeSet *propTypes = otype->maybeGetProperty(cx, typeId)) {
if (propTypes->needsBarrier(cx))
return true;
}
@ -2612,7 +2617,7 @@ TypeCompartment::processPendingRecompiles(FreeOp *fop)
}
void
TypeCompartment::setPendingNukeTypes(JSContext *cx)
TypeCompartment::setPendingNukeTypes(ExclusiveContext *cx)
{
TypeZone *zone = &compartment()->zone()->types;
if (!zone->pendingNukeTypes) {
@ -3030,9 +3035,9 @@ NumberTypes(Type a, Type b)
* arrays and objects whose type can be fixed.
*/
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());
return type;
}
@ -3058,7 +3063,8 @@ struct types::ArrayTableKey
};
void
TypeCompartment::setTypeToHomogenousArray(JSContext *cx, JSObject *obj, Type elementType)
TypeCompartment::setTypeToHomogenousArray(ExclusiveContext *cx,
JSObject *obj, Type elementType)
{
if (!arrayTypeTable) {
arrayTypeTable = cx->new_<ArrayTypeTable>();
@ -3097,7 +3103,7 @@ TypeCompartment::setTypeToHomogenousArray(JSContext *cx, JSObject *obj, Type ele
}
void
TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj)
TypeCompartment::fixArrayType(ExclusiveContext *cx, JSObject *obj)
{
AutoEnterAnalysis enter(cx);
@ -3113,10 +3119,10 @@ TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj)
if (len == 0)
return;
Type type = GetValueTypeForTable(cx, obj->getDenseElement(0));
Type type = GetValueTypeForTable(obj->getDenseElement(0));
for (unsigned i = 1; i < len; i++) {
Type ntype = GetValueTypeForTable(cx, obj->getDenseElement(i));
Type ntype = GetValueTypeForTable(obj->getDenseElement(i));
if (ntype != type) {
if (NumberTypes(type, ntype))
type = Type::DoubleType();
@ -3129,17 +3135,14 @@ TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj)
}
void
types::FixRestArgumentsType(ExclusiveContext *cxArg, JSObject *obj)
types::FixRestArgumentsType(ExclusiveContext *cx, JSObject *obj)
{
if (cxArg->isJSContext()) {
JSContext *cx = cxArg->asJSContext();
if (cx->typeInferenceEnabled())
cx->compartment()->types.fixRestArgumentsType(cx, obj);
}
if (cx->typeInferenceEnabled())
cx->compartment()->types.fixRestArgumentsType(cx, obj);
}
void
TypeCompartment::fixRestArgumentsType(JSContext *cx, JSObject *obj)
TypeCompartment::fixRestArgumentsType(ExclusiveContext *cx, JSObject *obj)
{
AutoEnterAnalysis enter(cx);
@ -3199,14 +3202,14 @@ struct types::ObjectTableEntry
};
static inline void
UpdateObjectTableEntryTypes(JSContext *cx, ObjectTableEntry &entry,
UpdateObjectTableEntryTypes(ExclusiveContext *cx, ObjectTableEntry &entry,
IdValuePair *properties, size_t nproperties)
{
if (entry.object->unknownProperties())
return;
for (size_t i = 0; i < nproperties; i++) {
Type type = entry.types[i];
Type ntype = GetValueTypeForTable(cx, properties[i].value);
Type ntype = GetValueTypeForTable(properties[i].value);
if (ntype == type)
continue;
if (ntype.isPrimitive(JSVAL_TYPE_INT32) &&
@ -3226,7 +3229,7 @@ UpdateObjectTableEntryTypes(JSContext *cx, ObjectTableEntry &entry,
}
void
TypeCompartment::fixObjectType(JSContext *cx, JSObject *obj)
TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj)
{
AutoEnterAnalysis enter(cx);
@ -3299,7 +3302,7 @@ TypeCompartment::fixObjectType(JSContext *cx, JSObject *obj)
for (size_t i = 0; i < properties.length(); i++) {
ids[i] = properties[i].id;
types[i] = GetValueTypeForTable(cx, obj->getSlot(i));
types[i] = GetValueTypeForTable(obj->getSlot(i));
if (!objType->unknownProperties())
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
UpdatePropertyType(JSContext *cx, TypeSet *types, JSObject *obj, Shape *shape,
UpdatePropertyType(ExclusiveContext *cx, TypeSet *types, JSObject *obj, Shape *shape,
bool force)
{
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).
*/
if (force || !value.isUndefined()) {
Type type = GetValueType(cx, value);
Type type = GetValueType(value);
types->addType(cx, type);
}
}
}
bool
TypeObject::addProperty(JSContext *cx, jsid id, Property **pprop)
TypeObject::addProperty(ExclusiveContext *cx, jsid id, Property **pprop)
{
JS_ASSERT(!*pprop);
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++) {
const Value &value = singleton->getDenseElement(i);
if (!value.isMagic(JS_ELEMENTS_HOLE)) {
Type type = GetValueType(cx, value);
Type type = GetValueType(value);
base->types.setOwnProperty(cx, false);
base->types.addType(cx, type);
}
@ -3514,7 +3517,7 @@ TypeObject::addProperty(JSContext *cx, jsid id, Property **pprop)
}
bool
TypeObject::addDefiniteProperties(JSContext *cx, JSObject *obj)
TypeObject::addDefiniteProperties(ExclusiveContext *cx, JSObject *obj)
{
if (unknownProperties())
return true;
@ -3567,7 +3570,7 @@ TypeObject::matchDefiniteProperties(HandleObject obj)
}
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));
@ -3583,19 +3586,19 @@ InlineAddTypeProperty(JSContext *cx, TypeObject *obj, jsid id, Type type)
}
void
TypeObject::addPropertyType(JSContext *cx, jsid id, Type type)
TypeObject::addPropertyType(ExclusiveContext *cx, jsid id, Type type)
{
InlineAddTypeProperty(cx, this, id, type);
}
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
TypeObject::addPropertyType(JSContext *cx, const char *name, Type type)
TypeObject::addPropertyType(ExclusiveContext *cx, const char *name, Type type)
{
jsid id = JSID_VOID;
if (name) {
@ -3611,13 +3614,13 @@ TypeObject::addPropertyType(JSContext *cx, const char *name, Type type)
}
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
TypeObject::markPropertyConfigured(JSContext *cx, jsid id)
TypeObject::markPropertyConfigured(ExclusiveContext *cx, jsid id)
{
AutoEnterAnalysis enter(cx);
@ -3629,24 +3632,28 @@ TypeObject::markPropertyConfigured(JSContext *cx, jsid id)
}
void
TypeObject::markStateChange(JSContext *cx)
TypeObject::markStateChange(ExclusiveContext *cxArg)
{
if (unknownProperties())
return;
AutoEnterAnalysis enter(cx);
TypeSet *types = maybeGetProperty(JSID_EMPTY, cx);
AutoEnterAnalysis enter(cxArg);
TypeSet *types = maybeGetProperty(cxArg, JSID_EMPTY);
if (types) {
TypeConstraint *constraint = types->constraintList;
while (constraint) {
constraint->newObjectState(cx, this, true);
constraint = constraint->next;
if (JSContext *cx = cxArg->maybeJSContext()) {
TypeConstraint *constraint = types->constraintList;
while (constraint) {
constraint->newObjectState(cx, this, true);
constraint = constraint->next;
}
} else {
JS_ASSERT(!types->constraintList);
}
}
}
void
TypeObject::setFlags(JSContext *cx, TypeObjectFlags flags)
TypeObject::setFlags(ExclusiveContext *cx, TypeObjectFlags flags)
{
if ((this->flags & flags) == flags)
return;
@ -3667,7 +3674,7 @@ TypeObject::setFlags(JSContext *cx, TypeObjectFlags flags)
}
void
TypeObject::markUnknown(JSContext *cx)
TypeObject::markUnknown(ExclusiveContext *cx)
{
AutoEnterAnalysis enter(cx);
@ -3701,7 +3708,7 @@ TypeObject::markUnknown(JSContext *cx)
}
void
TypeObject::clearNewScript(JSContext *cx)
TypeObject::clearNewScript(ExclusiveContext *cx)
{
JS_ASSERT(!(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
* the stack and fix up any such objects.
*/
Vector<uint32_t, 32> pcOffsets(cx);
for (ScriptFrameIter iter(cx); !iter.done(); ++iter) {
pcOffsets.append(uint32_t(iter.pc() - iter.script()->code));
if (iter.isConstructing() &&
iter.callee() == newScript->fun &&
iter.thisv().isObject() &&
!iter.thisv().toObject().hasLazyType() &&
iter.thisv().toObject().type() == this)
{
RootedObject obj(cx, &iter.thisv().toObject());
if (cx->isJSContext()) {
Vector<uint32_t, 32> pcOffsets(cx);
for (ScriptFrameIter iter(cx->asJSContext()); !iter.done(); ++iter) {
pcOffsets.append(uint32_t(iter.pc() - iter.script()->code));
if (iter.isConstructing() &&
iter.callee() == newScript->fun &&
iter.thisv().isObject() &&
!iter.thisv().toObject().hasLazyType() &&
iter.thisv().toObject().type() == this)
{
RootedObject obj(cx, &iter.thisv().toObject());
/* Whether all identified 'new' properties have been initialized. */
bool finished = false;
/* Whether all identified 'new' properties have been initialized. */
bool finished = false;
/* If not finished, number of properties that have been added. */
uint32_t numProperties = 0;
/* If not finished, number of properties that have been added. */
uint32_t numProperties = 0;
/*
* If non-zero, we are scanning initializers in a call which has
* already finished.
*/
size_t depth = 0;
size_t callDepth = pcOffsets.length() - 1;
uint32_t offset = pcOffsets[callDepth];
/*
* If non-zero, we are scanning initializers in a call which has
* already finished.
*/
size_t depth = 0;
size_t callDepth = pcOffsets.length() - 1;
uint32_t offset = pcOffsets[callDepth];
for (TypeNewScript::Initializer *init = newScript->initializerList;; init++) {
if (init->kind == TypeNewScript::Initializer::SETPROP) {
if (!depth && init->offset > offset) {
/* 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)
for (TypeNewScript::Initializer *init = newScript->initializerList;; init++) {
if (init->kind == TypeNewScript::Initializer::SETPROP) {
if (!depth && init->offset > offset) {
/* Advanced past all properties which have been initialized. */
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 {
/* 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. */
JS_ASSERT(init->kind == TypeNewScript::Initializer::DONE);
finished = true;
break;
}
} else {
JS_ASSERT(init->kind == TypeNewScript::Initializer::DONE);
finished = true;
break;
}
}
if (!finished)
obj->rollbackProperties(cx, numProperties);
if (!finished)
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. */
@ -5029,7 +5041,7 @@ AnalyzePoppedThis(JSContext *cx, SSAUseChain *use,
if (shape && shape->hasSlot()) {
Value protov = type->proto->getSlot(shape->slot());
TypeSet *types = TypeScript::BytecodeTypes(script, pc);
types->addType(cx, GetValueType(cx, protov));
types->addType(cx, GetValueType(protov));
}
return true;
@ -5530,7 +5542,7 @@ types::TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const
return;
}
Type type = GetValueType(cx, rval);
Type type = GetValueType(rval);
TypeSet *types = TypeScript::BytecodeTypes(script, pc);
if (types->hasType(type))
return;
@ -5804,14 +5816,12 @@ JSScript::makeAnalysis(JSContext *cx)
}
/* static */ bool
JSFunction::setTypeForScriptedFunction(ExclusiveContext *cxArg, HandleFunction fun,
JSFunction::setTypeForScriptedFunction(ExclusiveContext *cx, HandleFunction fun,
bool singleton /* = false */)
{
if (!cxArg->typeInferenceEnabled())
if (!cx->typeInferenceEnabled())
return true;
JSContext *cx = cxArg->asJSContext();
if (singleton) {
if (!setSingletonType(cx, fun))
return false;
@ -6051,7 +6061,7 @@ ExclusiveContext::getNewType(Class *clasp, TaggedProto proto_, JSFunction *fun_)
* 'prototype' property of some scripted function.
*/
if (type->newScript && type->newScript->fun != fun_)
type->clearNewScript(asJSContext());
type->clearNewScript(this);
return type;
}
@ -6077,8 +6087,7 @@ ExclusiveContext::getNewType(Class *clasp, TaggedProto proto_, JSFunction *fun_)
if (!typeInferenceEnabled())
return type;
JSContext *cx = asJSContext();
AutoEnterAnalysis enter(cx);
AutoEnterAnalysis enter(this);
/*
* 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.
*/
if (proto.isObject()) {
RootedObject obj(cx, proto.toObject());
RootedObject obj(this, proto.toObject());
if (fun)
CheckNewScriptProperties(cx, type, fun);
CheckNewScriptProperties(asJSContext(), type, fun);
if (obj->is<RegExpObject>()) {
AddTypeProperty(cx, type, "source", types::Type::StringType());
AddTypeProperty(cx, type, "global", types::Type::BooleanType());
AddTypeProperty(cx, type, "ignoreCase", types::Type::BooleanType());
AddTypeProperty(cx, type, "multiline", types::Type::BooleanType());
AddTypeProperty(cx, type, "sticky", types::Type::BooleanType());
AddTypeProperty(cx, type, "lastIndex", types::Type::Int32Type());
AddTypeProperty(this, type, "source", types::Type::StringType());
AddTypeProperty(this, type, "global", types::Type::BooleanType());
AddTypeProperty(this, type, "ignoreCase", types::Type::BooleanType());
AddTypeProperty(this, type, "multiline", types::Type::BooleanType());
AddTypeProperty(this, type, "sticky", types::Type::BooleanType());
AddTypeProperty(this, type, "lastIndex", types::Type::Int32Type());
}
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. */
inline Type GetValueType(JSContext *cx, const Value &val);
inline Type GetValueType(const Value &val);
/*
* 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
* 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. */
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
@ -1040,10 +1040,10 @@ struct TypeObject : gc::Cell
* assignment, and the own types of the property will be used instead of
* 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. */
inline HeapTypeSet *maybeGetProperty(jsid id, JSContext *cx);
inline HeapTypeSet *maybeGetProperty(ExclusiveContext *cx, jsid id);
inline unsigned getPropertyCount();
inline Property *getProperty(unsigned i);
@ -1056,19 +1056,19 @@ struct TypeObject : gc::Cell
/* Helpers */
bool addProperty(JSContext *cx, jsid id, Property **pprop);
bool addDefiniteProperties(JSContext *cx, JSObject *obj);
bool addProperty(ExclusiveContext *cx, jsid id, Property **pprop);
bool addDefiniteProperties(ExclusiveContext *cx, JSObject *obj);
bool matchDefiniteProperties(HandleObject obj);
void addPrototype(JSContext *cx, TypeObject *proto);
void addPropertyType(JSContext *cx, jsid id, Type type);
void addPropertyType(JSContext *cx, jsid id, const Value &value);
void addPropertyType(JSContext *cx, const char *name, Type type);
void addPropertyType(JSContext *cx, const char *name, const Value &value);
void markPropertyConfigured(JSContext *cx, jsid id);
void markStateChange(JSContext *cx);
void setFlags(JSContext *cx, TypeObjectFlags flags);
void markUnknown(JSContext *cx);
void clearNewScript(JSContext *cx);
void addPropertyType(ExclusiveContext *cx, jsid id, Type type);
void addPropertyType(ExclusiveContext *cx, jsid id, const Value &value);
void addPropertyType(ExclusiveContext *cx, const char *name, Type type);
void addPropertyType(ExclusiveContext *cx, const char *name, const Value &value);
void markPropertyConfigured(ExclusiveContext *cx, jsid id);
void markStateChange(ExclusiveContext *cx);
void setFlags(ExclusiveContext *cx, TypeObjectFlags flags);
void markUnknown(ExclusiveContext *cx);
void clearNewScript(ExclusiveContext *cx);
void getFromPrototypes(JSContext *cx, jsid id, TypeSet *types, bool force = false);
void print();
@ -1368,12 +1368,12 @@ struct TypeCompartment
ObjectTypeTable *objectTypeTable;
private:
void setTypeToHomogenousArray(JSContext *cx, JSObject *obj, Type type);
void setTypeToHomogenousArray(ExclusiveContext *cx, JSObject *obj, Type type);
public:
void fixArrayType(JSContext *cx, JSObject *obj);
void fixObjectType(JSContext *cx, JSObject *obj);
void fixRestArgumentsType(JSContext *cx, JSObject *obj);
void fixArrayType(ExclusiveContext *cx, JSObject *obj);
void fixObjectType(ExclusiveContext *cx, JSObject *obj);
void fixRestArgumentsType(ExclusiveContext *cx, JSObject *obj);
JSObject *newTypedObject(JSContext *cx, IdValuePair *properties, size_t nproperties);
@ -1414,7 +1414,7 @@ struct TypeCompartment
void processPendingRecompiles(FreeOp *fop);
/* 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. */
void addPendingRecompile(JSContext *cx, const RecompileInfo &info);

View File

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

View File

@ -226,12 +226,7 @@ js::StartOffThreadParseScript(JSContext *cx, const CompileOptions &options,
if (!global)
return false;
// For now, type inference is always disabled in exclusive zones, as type
// 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;
global->zone()->types.inferenceEnabled = cx->typeInferenceEnabled();
JS_SetCompartmentPrincipals(global->compartment(), cx->compartment()->principals);
RootedObject obj(cx);

View File

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

View File

@ -938,7 +938,7 @@ JSObject::clear(JSContext *cx, HandleObject obj)
}
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.