mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 906060 - Allow ExclusiveContext zones to have TI enabled, r=billm.
This commit is contained in:
parent
36d43a2d51
commit
3ea6fd69a7
@ -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() ||
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_++;
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user