From 3899368c4e327bccf52bfe65299fc19314c55292 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Sat, 8 Mar 2014 10:57:38 -0700 Subject: [PATCH] Bug 980630 - Remove type nuking, r=jandem. --- js/src/gc/GCInternals.h | 3 - js/src/gc/StoreBuffer.h | 7 +- js/src/gc/Verifier.cpp | 9 - js/src/jit-test/tests/gc/bug-914614.js | 6 - js/src/jit/IonAnalysis.cpp | 3 +- js/src/jit/IonBuilder.cpp | 30 +- js/src/jit/IonBuilder.h | 2 +- js/src/jit/MCallOptimize.cpp | 3 +- js/src/jit/MIR.cpp | 32 +- js/src/jit/MIR.h | 2 +- js/src/jsanalyze.cpp | 4 +- js/src/jscntxt.cpp | 8 + js/src/jsinfer.cpp | 387 ++++++++----------------- js/src/jsinfer.h | 31 +- js/src/jsinferinlines.h | 72 ++--- js/src/jsstr.cpp | 4 +- 16 files changed, 200 insertions(+), 403 deletions(-) delete mode 100644 js/src/jit-test/tests/gc/bug-914614.js diff --git a/js/src/gc/GCInternals.h b/js/src/gc/GCInternals.h index 2fcb99808309..02ca149c5be6 100644 --- a/js/src/gc/GCInternals.h +++ b/js/src/gc/GCInternals.h @@ -152,9 +152,6 @@ struct AutoStopVerifyingBarriers }; #endif /* JS_GC_ZEAL */ -void -CrashAtUnhandlableOOM(const char *reason); - } /* namespace gc */ } /* namespace js */ diff --git a/js/src/gc/StoreBuffer.h b/js/src/gc/StoreBuffer.h index c760b1872e1f..08cb126fe3e5 100644 --- a/js/src/gc/StoreBuffer.h +++ b/js/src/gc/StoreBuffer.h @@ -24,10 +24,11 @@ #include "js/Tracer.h" namespace js { -namespace gc { -extern void -CrashAtUnhandlableOOM(const char *); +void +CrashAtUnhandlableOOM(const char *reason); + +namespace gc { /* * BufferableRef represents an abstract reference for use in the generational diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp index 36a43edd5db8..f521d7572625 100644 --- a/js/src/gc/Verifier.cpp +++ b/js/src/gc/Verifier.cpp @@ -882,12 +882,3 @@ js::gc::FinishVerifier(JSRuntime *rt) } #endif /* JS_GC_ZEAL */ - -void -js::gc::CrashAtUnhandlableOOM(const char *reason) -{ - char msgbuf[1024]; - JS_snprintf(msgbuf, sizeof(msgbuf), "[unhandlable oom] %s", reason); - MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__); - MOZ_CRASH(); -} diff --git a/js/src/jit-test/tests/gc/bug-914614.js b/js/src/jit-test/tests/gc/bug-914614.js deleted file mode 100644 index 018503c700e3..000000000000 --- a/js/src/jit-test/tests/gc/bug-914614.js +++ /dev/null @@ -1,6 +0,0 @@ -// |jit-test| allow-oom -if (typeof oomAfterAllocations == 'function') { - gczeal(4); - oomAfterAllocations(1); - var s = new Set; -} diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp index 0cfa76bbe714..08f8e8fd38c5 100644 --- a/js/src/jit/IonAnalysis.cpp +++ b/js/src/jit/IonAnalysis.cpp @@ -2065,7 +2065,8 @@ AnalyzePoppedThis(JSContext *cx, types::TypeObject *type, block = rp->block(), rp = block->callerResumePoint()) { JSScript *script = rp->block()->info().script(); - types::AddClearDefiniteFunctionUsesInScript(cx, type, script, block->info().script()); + if (!types::AddClearDefiniteFunctionUsesInScript(cx, type, script, block->info().script())) + return true; if (!callerResumePoints.append(rp)) return false; } diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 4f0ab41a85ac..40cedd5819a4 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -617,8 +617,7 @@ IonBuilder::build() } #endif - if (!initParameters()) - return false; + initParameters(); // Initialize local variables. for (uint32_t i = 0; i < info().nlocals(); i++) { @@ -910,20 +909,18 @@ IonBuilder::rewriteParameters() } } -bool +void IonBuilder::initParameters() { if (!info().funMaybeLazy()) - return true; + return; // If we are doing OSR on a frame which initially executed in the // interpreter and didn't accumulate type information, try to use that OSR // frame to determine possible initial types for 'this' and parameters. - if (thisTypes->empty() && baselineFrame_) { - if (!thisTypes->addType(baselineFrame_->thisType, alloc_->lifoAlloc())) - return false; - } + if (thisTypes->empty() && baselineFrame_) + thisTypes->addType(baselineFrame_->thisType, alloc_->lifoAlloc()); MParameter *param = MParameter::New(alloc(), MParameter::THIS_SLOT, thisTypes); current->add(param); @@ -934,16 +931,13 @@ IonBuilder::initParameters() if (types->empty() && baselineFrame_ && !script_->baselineScript()->modifiesArguments()) { - if (!types->addType(baselineFrame_->argTypes[i], alloc_->lifoAlloc())) - return false; + types->addType(baselineFrame_->argTypes[i], alloc_->lifoAlloc()); } param = MParameter::New(alloc(), i, types); current->add(param); current->initSlot(info().argSlotUnchecked(i), param); } - - return true; } bool @@ -4971,14 +4965,12 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing) types::TemporaryTypeSet *observed = bytecodeTypes(pc); if (observed->empty()) { if (BytecodeFlowsToBitop(pc)) { - if (!observed->addType(types::Type::Int32Type(), alloc_->lifoAlloc())) - return false; + observed->addType(types::Type::Int32Type(), alloc_->lifoAlloc()); } else if (*GetNextPc(pc) == JSOP_POS) { // Note: this is lame, overspecialized on the code patterns used // by asm.js and should be replaced by a more general mechanism. // See bug 870847. - if (!observed->addType(types::Type::DoubleType(), alloc_->lifoAlloc())) - return false; + observed->addType(types::Type::DoubleType(), alloc_->lifoAlloc()); } } @@ -7091,8 +7083,7 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index) // Indexed call on an element of an array. Populate the observed types // with any objects that could be in the array, to avoid extraneous // type barriers. - if (!AddObjectsForPropertyRead(obj, nullptr, types)) - return false; + AddObjectsForPropertyRead(obj, nullptr, types); } bool barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj, nullptr, types); @@ -9288,8 +9279,7 @@ IonBuilder::jsop_setarg(uint32_t arg) } if (!otherUses) { JS_ASSERT(op->resultTypeSet() == &argTypes[arg]); - if (!argTypes[arg].addType(types::Type::UnknownType(), alloc_->lifoAlloc())) - return false; + argTypes[arg].addType(types::Type::UnknownType(), alloc_->lifoAlloc()); if (val->isMul()) { val->setResultType(MIRType_Double); val->toMul()->setSpecialization(MIRType_Double); diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index 70bd0117051d..0c5dc96bfe28 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -327,7 +327,7 @@ class IonBuilder : public MIRGenerator void insertRecompileCheck(); - bool initParameters(); + void initParameters(); void rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex); void rewriteParameters(); bool initScopeChain(MDefinition *callee = nullptr); diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index f6f1c809021e..fcfd1f5f3543 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -940,8 +940,7 @@ IonBuilder::inlineMathFRound(CallInfo &callInfo) if (returned->empty()) { // As there's only one possible returned type, just add it to the observed // returned typeset - if (!returned->addType(types::Type::DoubleType(), alloc_->lifoAlloc())) - return InliningStatus_Error; + returned->addType(types::Type::DoubleType(), alloc_->lifoAlloc()); } else { MIRType returnType = getInlineReturnType(); if (!IsNumberType(returnType)) diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 38aadf7cb80e..9577fb0b59b1 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -2765,10 +2765,8 @@ InlinePropertyTable::buildTypeSetForFunction(JSFunction *func) const if (!types) return nullptr; for (size_t i = 0; i < numEntries(); i++) { - if (entries_[i]->func == func) { - if (!types->addType(types::Type::ObjectType(entries_[i]->typeObj), alloc)) - return nullptr; - } + if (entries_[i]->func == func) + types->addType(types::Type::ObjectType(entries_[i]->typeObj), alloc); } return types; } @@ -3172,7 +3170,7 @@ jit::PropertyReadIsIdempotent(types::CompilerConstraintList *constraints, return true; } -bool +void jit::AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name, types::TemporaryTypeSet *observed) { @@ -3182,16 +3180,20 @@ jit::AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name, LifoAlloc *alloc = GetIonContext()->temp->lifoAlloc(); types::TemporaryTypeSet *types = obj->resultTypeSet(); - if (!types || types->unknownObject()) - return observed->addType(types::Type::AnyObjectType(), alloc); + if (!types || types->unknownObject()) { + observed->addType(types::Type::AnyObjectType(), alloc); + return; + } for (size_t i = 0; i < types->getObjectCount(); i++) { types::TypeObjectKey *object = types->getObject(i); if (!object) continue; - if (object->unknownProperties()) - return observed->addType(types::Type::AnyObjectType(), alloc); + if (object->unknownProperties()) { + observed->addType(types::Type::AnyObjectType(), alloc); + return; + } jsid id = name ? NameToId(name) : JSID_VOID; types::HeapTypeSetKey property = object->property(id); @@ -3199,17 +3201,17 @@ jit::AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name, if (!types) continue; - if (types->unknownObject()) - return observed->addType(types::Type::AnyObjectType(), alloc); + if (types->unknownObject()) { + observed->addType(types::Type::AnyObjectType(), alloc); + return; + } for (size_t i = 0; i < types->getObjectCount(); i++) { types::TypeObjectKey *object = types->getObject(i); - if (object && !observed->addType(types::Type::ObjectType(object), alloc)) - return false; + if (object) + observed->addType(types::Type::ObjectType(object), alloc); } } - - return true; } static bool diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 6695a4e09995..35927a836a8b 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -9866,7 +9866,7 @@ bool PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *cons types::TemporaryTypeSet *observed); bool PropertyReadIsIdempotent(types::CompilerConstraintList *constraints, MDefinition *obj, PropertyName *name); -bool AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name, +void AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name, types::TemporaryTypeSet *observed); bool PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstraintList *constraints, MBasicBlock *current, MDefinition **pobj, diff --git a/js/src/jsanalyze.cpp b/js/src/jsanalyze.cpp index a27e0562cebe..82ae4610d6d7 100644 --- a/js/src/jsanalyze.cpp +++ b/js/src/jsanalyze.cpp @@ -2206,10 +2206,8 @@ ScriptAnalysis::needsArgsObj(JSContext *cx, SeenVector &seen, const SSAValue &v) if (v == seen[i]) return false; } - if (!seen.append(v)) { - cx->compartment()->types.setPendingNukeTypes(cx); + if (!seen.append(v)) return true; - } SSAUseChain *use = useChain(v); while (use) { diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 741cdd2b2e23..05dd178b5e42 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -1365,3 +1365,11 @@ void CompartmentChecker::check(AbstractFramePtr frame) } #endif +void +js::CrashAtUnhandlableOOM(const char *reason) +{ + char msgbuf[1024]; + JS_snprintf(msgbuf, sizeof(msgbuf), "[unhandlable oom] %s", reason); + MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__); + MOZ_CRASH(); +} diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 3d5140f4f336..0a74b41545f5 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -374,7 +374,7 @@ TypeSet::enumerateTypes(TypeList *list) return true; } -inline void +inline bool TypeSet::addTypesToConstraint(JSContext *cx, TypeConstraint *constraint) { /* @@ -383,19 +383,20 @@ TypeSet::addTypesToConstraint(JSContext *cx, TypeConstraint *constraint) */ TypeList types; if (!enumerateTypes(&types)) - cx->compartment()->types.setPendingNukeTypes(cx); + return false; for (unsigned i = 0; i < types.length(); i++) constraint->newType(cx, this, types[i]); + + return true; } -void -ConstraintTypeSet::add(JSContext *cx, TypeConstraint *constraint, bool callExisting) +bool +ConstraintTypeSet::addConstraint(JSContext *cx, TypeConstraint *constraint, bool callExisting) { if (!constraint) { /* OOM failure while constructing the constraint. */ - cx->compartment()->types.setPendingNukeTypes(cx); - return; + return false; } JS_ASSERT(cx->compartment()->activeAnalysis); @@ -410,7 +411,8 @@ ConstraintTypeSet::add(JSContext *cx, TypeConstraint *constraint, bool callExist constraintList = constraint; if (callExisting) - addTypesToConstraint(cx, constraint); + return addTypesToConstraint(cx, constraint); + return true; } void @@ -502,14 +504,12 @@ TypeSet::unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc) if (!res->unknownObject()) { for (size_t i = 0; i < a->getObjectCount() && !res->unknownObject(); i++) { - TypeObjectKey *key = a->getObject(i); - if (key && !res->addType(Type::ObjectType(key), alloc)) - return nullptr; + if (TypeObjectKey *key = a->getObject(i)) + res->addType(Type::ObjectType(key), alloc); } for (size_t i = 0; i < b->getObjectCount() && !res->unknownObject(); i++) { - TypeObjectKey *key = b->getObject(i); - if (key && !res->addType(Type::ObjectType(key), alloc)) - return nullptr; + if (TypeObjectKey *key = b->getObject(i)) + res->addType(Type::ObjectType(key), alloc); } } @@ -761,13 +761,11 @@ class TypeCompilerConstraint : public TypeConstraint cx->zone()->types.addPendingRecompile(cx, compilation); } - TypeConstraint *sweep(TypeZone &zone) { + bool sweep(TypeZone &zone, TypeConstraint **res) { if (data.shouldSweep() || compilation.shouldSweep(zone)) - return nullptr; - TypeConstraint *res = zone.typeLifoAlloc.new_ >(compilation, data); - if (!res) - zone.setPendingNukeTypes(); - return res; + return false; + *res = zone.typeLifoAlloc.new_ >(compilation, data); + return true; } }; @@ -784,9 +782,8 @@ CompilerConstraintInstance::generateTypeConstraint(JSContext *cx, RecompileIn if (!data.constraintHolds(cx, property, expected)) return false; - property.maybeTypes()->add(cx, cx->typeLifoAlloc().new_ >(recompileInfo, data), - /* callExisting = */ false); - return true; + return property.maybeTypes()->addConstraint(cx, cx->typeLifoAlloc().new_ >(recompileInfo, data), + /* callExisting = */ false); } } /* anonymous namespace */ @@ -941,13 +938,11 @@ class TypeConstraintFreezeStack : public TypeConstraint cx->zone()->types.addPendingRecompile(cx, script_); } - TypeConstraint *sweep(TypeZone &zone) { + bool sweep(TypeZone &zone, TypeConstraint **res) { if (IsScriptAboutToBeFinalized(&script_)) - return nullptr; - TypeConstraint *res = zone.typeLifoAlloc.new_(script_); - if (!res) - zone.setPendingNukeTypes(); - return res; + return false; + *res = zone.typeLifoAlloc.new_(script_); + return true; } }; @@ -1017,8 +1012,10 @@ types::FinishCompilation(JSContext *cx, HandleScript script, ExecutionMode execu size_t count = TypeScript::NumTypeSets(entry.script); StackTypeSet *array = entry.script->types->typeArray(); - for (size_t i = 0; i < count; i++) - array[i].add(cx, cx->typeLifoAlloc().new_(entry.script), false); + for (size_t i = 0; i < count; i++) { + if (!array[i].addConstraint(cx, cx->typeLifoAlloc().new_(entry.script), false)) + succeeded = false; + } } if (!succeeded || types.compilerOutputs->back().pendingInvalidation()) { @@ -1976,7 +1973,7 @@ TypeCompartment::addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey ke if (!allocationSiteTable) { allocationSiteTable = cx->new_(); if (!allocationSiteTable || !allocationSiteTable->init()) { - cx->compartment()->types.setPendingNukeTypes(cx); + js_delete(allocationSiteTable); return nullptr; } } @@ -2012,10 +2009,8 @@ TypeCompartment::addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey ke Rooted tagged(cx, TaggedProto(proto)); res = newTypeObject(cx, GetClassForProtoKey(key.kind), tagged, OBJECT_FLAG_FROM_ALLOCATION_SITE); - if (!res) { - cx->compartment()->types.setPendingNukeTypes(cx); + if (!res) return nullptr; - } key.script = keyScript; } @@ -2031,10 +2026,8 @@ TypeCompartment::addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey ke return nullptr; } - if (!allocationSiteTable->add(p, key, res)) { - cx->compartment()->types.setPendingNukeTypes(cx); + if (!allocationSiteTable->add(p, key, res)) return nullptr; - } return res; } @@ -2209,60 +2202,6 @@ TypeZone::processPendingRecompiles(FreeOp *fop) fop->delete_(pending); } -void -TypeCompartment::setPendingNukeTypes(ExclusiveContext *cx) -{ - TypeZone *zone = &compartment()->zone()->types; - if (!zone->pendingNukeTypes) { - if (cx->compartment()) - js_ReportOutOfMemory(cx); - zone->pendingNukeTypes = true; - } -} - -void -TypeZone::setPendingNukeTypes() -{ - pendingNukeTypes = true; -} - -void -TypeZone::nukeTypes(FreeOp *fop) -{ - /* - * This is the usual response if we encounter an OOM while adding a type - * or resolving type constraints. Reset the compartment to not use type - * inference, and recompile all scripts. - * - * Because of the nature of constraint-based analysis (add constraints, and - * iterate them until reaching a fixpoint), we can't undo an add of a type set, - * and merely aborting the operation which triggered the add will not be - * sufficient for correct behavior as we will be leaving the types in an - * inconsistent state. - */ - JS_ASSERT(pendingNukeTypes); - - if (pendingRecompiles) { - fop->free_(pendingRecompiles); - pendingRecompiles = nullptr; - } - - inferenceEnabled = false; - -#ifdef JS_ION - jit::InvalidateAll(fop, zone()); - - /* Throw away all JIT code in the compartment, but leave everything else alone. */ - - for (gc::CellIter i(zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) { - JSScript *script = i.get(); - jit::FinishInvalidation(fop, script); - } -#endif /* JS_ION */ - - pendingNukeTypes = false; -} - void TypeZone::addPendingRecompile(JSContext *cx, const RecompileInfo &info) { @@ -2270,23 +2209,19 @@ TypeZone::addPendingRecompile(JSContext *cx, const RecompileInfo &info) if (!co || !co->isValid() || co->pendingInvalidation()) return; - if (!pendingRecompiles) { - pendingRecompiles = cx->new_< Vector >(cx); - if (!pendingRecompiles) { - cx->compartment()->types.setPendingNukeTypes(cx); - return; - } - } - - if (!pendingRecompiles->append(info)) { - cx->compartment()->types.setPendingNukeTypes(cx); - return; - } - InferSpew(ISpewOps, "addPendingRecompile: %p:%s:%d", co->script(), co->script()->filename(), co->script()->lineno()); co->setPendingInvalidation(); + + if (!pendingRecompiles) { + pendingRecompiles = cx->new_< Vector >(cx); + if (!pendingRecompiles) + CrashAtUnhandlableOOM("Could not update pendingRecompiles"); + } + + if (!pendingRecompiles->append(info)) + CrashAtUnhandlableOOM("Could not update pendingRecompiles"); } void @@ -2325,32 +2260,18 @@ TypeCompartment::markSetsUnknown(JSContext *cx, TypeObject *target) AutoEnterAnalysis enter(cx); - /* - * Mark both persistent and transient type sets which contain obj as having - * a generic object type. It is not sufficient to mark just the persistent - * sets, as analysis of individual opcodes can pull type objects from - * static information (like initializer objects at various offsets). - * - * We make a list of properties to update and fix them afterwards, as adding - * types can't be done while iterating over cells as it can potentially make - * new type objects as well or trigger GC. - */ - Vector pending(cx); + /* Mark type sets which contain obj as having a generic object types. */ + for (gc::CellIter i(cx->zone(), gc::FINALIZE_TYPE_OBJECT); !i.done(); i.next()) { TypeObject *object = i.get(); unsigned count = object->getPropertyCount(); for (unsigned i = 0; i < count; i++) { Property *prop = object->getProperty(i); - if (prop && prop->types.hasType(Type::ObjectType(target))) { - if (!pending.append(&prop->types)) - cx->compartment()->types.setPendingNukeTypes(cx); - } + if (prop && prop->types.hasType(Type::ObjectType(target))) + prop->types.addType(cx, Type::AnyObjectType()); } } - for (unsigned i = 0; i < pending.length(); i++) - pending[i]->addType(cx, Type::AnyObjectType()); - for (gc::CellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) { RootedScript script(cx, i.get()); if (script->types) { @@ -2461,7 +2382,6 @@ TypeCompartment::setTypeToHomogenousArray(ExclusiveContext *cx, arrayTypeTable = cx->new_(); if (!arrayTypeTable || !arrayTypeTable->init()) { arrayTypeTable = nullptr; - cx->compartment()->types.setPendingNukeTypes(cx); return; } } @@ -2474,20 +2394,15 @@ TypeCompartment::setTypeToHomogenousArray(ExclusiveContext *cx, /* Make a new type to use for future arrays with the same elements. */ RootedObject objProto(cx, obj->getProto()); TypeObject *objType = newTypeObject(cx, &ArrayObject::class_, objProto); - if (!objType) { - cx->compartment()->types.setPendingNukeTypes(cx); + if (!objType) return; - } obj->setType(objType); if (!objType->unknownProperties()) objType->addPropertyType(cx, JSID_VOID, elementType); key.proto = objProto; - if (!p.add(cx, *arrayTypeTable, key, objType)) { - cx->compartment()->types.setPendingNukeTypes(cx); - return; - } + (void) p.add(cx, *arrayTypeTable, key, objType); } } @@ -2625,8 +2540,8 @@ TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj) if (!objectTypeTable) { objectTypeTable = cx->new_(); if (!objectTypeTable || !objectTypeTable->init()) { + js_delete(objectTypeTable); objectTypeTable = nullptr; - cx->compartment()->types.setPendingNukeTypes(cx); return; } } @@ -2646,10 +2561,8 @@ TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj) return; Vector properties(cx); - if (!properties.resize(obj->slotSpan())) { - cx->compartment()->types.setPendingNukeTypes(cx); + if (!properties.resize(obj->slotSpan())) return; - } Shape *shape = obj->lastProperty(); while (!shape->isEmptyShape()) { @@ -2674,25 +2587,19 @@ TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj) /* Make a new type to use for the object and similar future ones. */ Rooted objProto(cx, obj->getTaggedProto()); TypeObject *objType = newTypeObject(cx, &JSObject::class_, objProto); - if (!objType || !objType->addDefiniteProperties(cx, obj)) { - cx->compartment()->types.setPendingNukeTypes(cx); + if (!objType || !objType->addDefiniteProperties(cx, obj)) return; - } if (obj->isIndexed()) objType->setFlags(cx, OBJECT_FLAG_SPARSE_INDEXES); - jsid *ids = cx->pod_calloc(properties.length()); - if (!ids) { - cx->compartment()->types.setPendingNukeTypes(cx); + ScopedJSFreePtr ids(cx->pod_calloc(properties.length())); + if (!ids) return; - } - Type *types = cx->pod_calloc(properties.length()); - if (!types) { - cx->compartment()->types.setPendingNukeTypes(cx); + ScopedJSFreePtr types(cx->pod_calloc(properties.length())); + if (!types) return; - } for (size_t i = 0; i < properties.length(); i++) { ids[i] = properties[i].id; @@ -2712,13 +2619,13 @@ TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj) entry.shape = obj->lastProperty(); entry.types = types; - p = objectTypeTable->lookupForAdd(lookup); - if (!objectTypeTable->add(p, key, entry)) { - cx->compartment()->types.setPendingNukeTypes(cx); - return; - } - obj->setType(objType); + + p = objectTypeTable->lookupForAdd(lookup); + if (objectTypeTable->add(p, key, entry)) { + ids.forget(); + types.forget(); + } } JSObject * @@ -2729,8 +2636,8 @@ TypeCompartment::newTypedObject(JSContext *cx, IdValuePair *properties, size_t n if (!objectTypeTable) { objectTypeTable = cx->new_(); if (!objectTypeTable || !objectTypeTable->init()) { + js_delete(objectTypeTable); objectTypeTable = nullptr; - cx->compartment()->types.setPendingNukeTypes(cx); return nullptr; } } @@ -2807,8 +2714,7 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, JSObject *obj, Shap if (shape->hasGetterValue() || shape->hasSetterValue()) { types->setNonDataProperty(cx); - if (!types->TypeSet::addType(Type::UnknownType(), &cx->typeLifoAlloc())) - cx->compartment()->types.setPendingNukeTypes(cx); + types->TypeSet::addType(Type::UnknownType(), &cx->typeLifoAlloc()); } else if (shape->hasDefaultGetter() && shape->hasSlot()) { if (!indexed && types->canSetDefinite(shape->slot())) types->setDefinite(shape->slot()); @@ -2822,8 +2728,7 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, JSObject *obj, Shap */ if (indexed || !value.isUndefined() || !CanHaveEmptyPropertyTypesForOwnProperty(obj)) { Type type = GetValueType(value); - if (!types->TypeSet::addType(type, &cx->typeLifoAlloc())) - cx->compartment()->types.setPendingNukeTypes(cx); + types->TypeSet::addType(type, &cx->typeLifoAlloc()); } } } @@ -2833,10 +2738,8 @@ TypeObject::addProperty(ExclusiveContext *cx, jsid id, Property **pprop) { JS_ASSERT(!*pprop); Property *base = cx->typeLifoAlloc().new_(id); - if (!base) { - cx->compartment()->types.setPendingNukeTypes(cx); + if (!base) return false; - } if (singleton() && singleton()->isNative()) { /* @@ -2860,8 +2763,7 @@ TypeObject::addProperty(ExclusiveContext *cx, jsid id, Property **pprop) const Value &value = singleton()->getDenseElement(i); if (!value.isMagic(JS_ELEMENTS_HOLE)) { Type type = GetValueType(value); - if (!base->types.TypeSet::addType(type, &cx->typeLifoAlloc())) - cx->compartment()->types.setPendingNukeTypes(cx); + base->types.TypeSet::addType(type, &cx->typeLifoAlloc()); } } } else if (!JSID_IS_EMPTY(id)) { @@ -2969,28 +2871,6 @@ TypeObject::addPropertyType(ExclusiveContext *cx, jsid id, const Value &value) InlineAddTypeProperty(cx, this, id, GetValueType(value)); } -void -TypeObject::addPropertyType(ExclusiveContext *cx, const char *name, Type type) -{ - jsid id = JSID_VOID; - if (name) { - JSAtom *atom = Atomize(cx, name, strlen(name)); - if (!atom) { - AutoEnterAnalysis enter(cx); - cx->compartment()->types.setPendingNukeTypes(cx); - return; - } - id = AtomToId(atom); - } - InlineAddTypeProperty(cx, this, id, type); -} - -void -TypeObject::addPropertyType(ExclusiveContext *cx, const char *name, const Value &value) -{ - addPropertyType(cx, name, GetValueType(value)); -} - void TypeObject::markPropertyNonData(ExclusiveContext *cx, jsid id) { @@ -3242,10 +3122,8 @@ TypeObject::clearNewScriptAddendum(ExclusiveContext *cx) } } - if (!finished) { - if (!JSObject::rollbackProperties(cx, obj, numProperties)) - cx->compartment()->types.setPendingNukeTypes(cx); - } + if (!finished) + (void) JSObject::rollbackProperties(cx, obj, numProperties); } } else { // Threads with an ExclusiveContext are not allowed to run scripts. @@ -3339,13 +3217,11 @@ class TypeConstraintClearDefiniteGetterSetter : public TypeConstraint void newType(JSContext *cx, TypeSet *source, Type type) {} - TypeConstraint *sweep(TypeZone &zone) { + bool sweep(TypeZone &zone, TypeConstraint **res) { if (IsTypeObjectAboutToBeFinalized(&object)) - return nullptr; - TypeConstraint *res = zone.typeLifoAlloc.new_(object); - if (!res) - zone.setPendingNukeTypes(); - return res; + return false; + *res = zone.typeLifoAlloc.new_(object); + return true; } }; @@ -3365,7 +3241,8 @@ types::AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, TypeObject * HeapTypeSet *parentTypes = parentObject->getProperty(cx, id); if (!parentTypes || parentTypes->nonDataProperty() || parentTypes->nonWritableProperty()) return false; - parentTypes->add(cx, cx->typeLifoAlloc().new_(type)); + if (!parentTypes->addConstraint(cx, cx->typeLifoAlloc().new_(type))) + return false; parent = parent->getProto(); } return true; @@ -3394,17 +3271,15 @@ class TypeConstraintClearDefiniteSingle : public TypeConstraint object->clearAddendum(cx); } - TypeConstraint *sweep(TypeZone &zone) { + bool sweep(TypeZone &zone, TypeConstraint **res) { if (IsTypeObjectAboutToBeFinalized(&object)) - return nullptr; - TypeConstraint *res = zone.typeLifoAlloc.new_(object); - if (!res) - zone.setPendingNukeTypes(); - return res; + return false; + *res = zone.typeLifoAlloc.new_(object); + return true; } }; -void +bool types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, TypeObject *type, JSScript *script, JSScript *calleeScript) { @@ -3437,10 +3312,12 @@ types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, TypeObject *type, } // This is a type set that might have been used when inlining // |calleeScript| into |script|. - types->add(cx, - cx->typeLifoAlloc().new_(type)); + if (!types->addConstraint(cx, cx->typeLifoAlloc().new_(type))) + return false; } } + + return true; } /* @@ -3464,12 +3341,8 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun) Vector initializerList(cx); - if (!jit::AnalyzeNewScriptProperties(cx, fun, type, baseobj, &initializerList)) { - cx->compartment()->types.setPendingNukeTypes(cx); - return; - } - - if (baseobj->slotSpan() == 0 || + if (!jit::AnalyzeNewScriptProperties(cx, fun, type, baseobj, &initializerList) || + baseobj->slotSpan() == 0 || !!(type->flags() & OBJECT_FLAG_ADDENDUM_CLEARED)) { if (type->hasNewScript()) @@ -3509,7 +3382,6 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun) !type->addDefiniteProperties(cx, baseobj) || !initializerList.append(done)) { - cx->compartment()->types.setPendingNukeTypes(cx); return; } @@ -3526,15 +3398,13 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun) #else newScript = (TypeNewScript *) cx->calloc_(numBytes); #endif + if (!newScript) + return; + new (newScript) TypeNewScript(); type->setAddendum(newScript); - if (!newScript) { - cx->compartment()->types.setPendingNukeTypes(cx); - return; - } - newScript->fun = fun; newScript->templateObject = baseobj; @@ -3684,10 +3554,8 @@ JSScript::makeTypes(JSContext *cx) unsigned count = TypeScript::NumTypeSets(this); TypeScript *typeScript = (TypeScript *) cx->calloc_(sizeof(TypeScript) + (sizeof(StackTypeSet) * count)); - if (!typeScript) { - cx->compartment()->types.setPendingNukeTypes(cx); + if (!typeScript) return false; - } new(typeScript) TypeScript(); @@ -3836,6 +3704,7 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj) { JS_ASSERT(obj->hasLazyType()); JS_ASSERT(cx->compartment() == obj->compartment()); + JS_ASSERT(cx->typeInferenceEnabled()); /* De-lazification of functions can GC, so we need to do it up here. */ if (obj->is() && obj->as().isInterpretedLazy()) { @@ -3859,17 +3728,8 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj) Rooted proto(cx, obj->getTaggedProto()); TypeObject *type = cx->compartment()->types.newTypeObject(cx, obj->getClass(), proto, initialFlags); - if (!type) { - if (cx->typeInferenceEnabled()) - cx->compartment()->types.setPendingNukeTypes(cx); + if (!type) return nullptr; - } - - if (!cx->typeInferenceEnabled()) { - /* This can only happen if types were previously nuked. */ - obj->type_ = type; - return type; - } AutoEnterAnalysis enter(cx); @@ -4048,22 +3908,22 @@ ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto, JSFunction * */ if (obj->is()) { - 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()); + type->addPropertyType(this, NameToId(names().source), Type::StringType()); + type->addPropertyType(this, NameToId(names().global), Type::BooleanType()); + type->addPropertyType(this, NameToId(names().ignoreCase), Type::BooleanType()); + type->addPropertyType(this, NameToId(names().multiline), Type::BooleanType()); + type->addPropertyType(this, NameToId(names().sticky), Type::BooleanType()); + type->addPropertyType(this, NameToId(names().lastIndex), Type::Int32Type()); } if (obj->is()) - AddTypeProperty(this, type, "length", Type::Int32Type()); + type->addPropertyType(this, NameToId(names().length), Type::Int32Type()); if (obj->is()) { - AddTypeProperty(this, type, "fileName", types::Type::StringType()); - AddTypeProperty(this, type, "lineNumber", types::Type::Int32Type()); - AddTypeProperty(this, type, "columnNumber", types::Type::Int32Type()); - AddTypeProperty(this, type, "stack", types::Type::StringType()); + type->addPropertyType(this, NameToId(names().fileName), Type::StringType()); + type->addPropertyType(this, NameToId(names().lineNumber), Type::Int32Type()); + type->addPropertyType(this, NameToId(names().columnNumber), Type::Int32Type()); + type->addPropertyType(this, NameToId(names().stack), Type::StringType()); } } @@ -4152,10 +4012,9 @@ ConstraintTypeSet::sweep(Zone *zone) TypeObjectKey **pentry = HashSetInsert (zone->types.typeLifoAlloc, objectSet, objectCount, object); - if (pentry) - *pentry = object; - else - zone->types.setPendingNukeTypes(); + if (!pentry) + CrashAtUnhandlableOOM("OOM in ConstraintTypeSet::sweep"); + *pentry = object; } } setBaseObjectCount(objectCount); @@ -4174,7 +4033,10 @@ ConstraintTypeSet::sweep(Zone *zone) TypeConstraint *constraint = constraintList; constraintList = nullptr; while (constraint) { - if (TypeConstraint *copy = constraint->sweep(zone->types)) { + TypeConstraint *copy; + if (constraint->sweep(zone->types, ©)) { + if (!copy) + CrashAtUnhandlableOOM("OOM in ConstraintTypeSet::sweep"); copy->next = constraintList; constraintList = copy; } @@ -4230,20 +4092,19 @@ TypeObject::sweep(FreeOp *fop) */ continue; } + Property *newProp = typeLifoAlloc.new_(*prop); - if (newProp) { - Property **pentry = - HashSetInsert - (typeLifoAlloc, propertySet, propertyCount, prop->id); - if (pentry) { - *pentry = newProp; - newProp->types.sweep(zone()); - } else { - zone()->types.setPendingNukeTypes(); - } - } else { - zone()->types.setPendingNukeTypes(); - } + if (!newProp) + CrashAtUnhandlableOOM("OOM in TypeObject::sweep"); + + Property **pentry = + HashSetInsert + (typeLifoAlloc, propertySet, propertyCount, prop->id); + if (!pentry) + CrashAtUnhandlableOOM("OOM in TypeObject::sweep"); + + *pentry = newProp; + newProp->types.sweep(zone()); } } setBasePropertyCount(propertyCount); @@ -4254,12 +4115,11 @@ TypeObject::sweep(FreeOp *fop) clearProperties(); } else { Property *newProp = typeLifoAlloc.new_(*prop); - if (newProp) { - propertySet = (Property **) newProp; - newProp->types.sweep(zone()); - } else { - zone()->types.setPendingNukeTypes(); - } + if (!newProp) + CrashAtUnhandlableOOM("OOM in TypeObject::sweep"); + + propertySet = (Property **) newProp; + newProp->types.sweep(zone()); } } @@ -4449,7 +4309,6 @@ TypeZone::TypeZone(Zone *zone) typeLifoAlloc(TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), compilerOutputs(nullptr), pendingRecompiles(nullptr), - pendingNukeTypes(false), inferenceEnabled(false) { } diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h index 32864777048d..ae11d43cc2cc 100644 --- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -242,6 +242,10 @@ class Type return data > JSVAL_TYPE_UNKNOWN; } + bool isObjectUnchecked() const { + return data > JSVAL_TYPE_UNKNOWN; + } + inline TypeObjectKey *objectKey() const; /* Accessors for JSObject types */ @@ -335,7 +339,7 @@ public: * If the data this constraint refers to is still live, copy it into the * zone's new allocator. Type constraints only hold weak references. */ - virtual TypeConstraint *sweep(TypeZone &zone) = 0; + virtual bool sweep(TypeZone &zone, TypeConstraint **res) = 0; }; /* Flags and other state stored in TypeSet::flags */ @@ -528,7 +532,7 @@ class TypeSet static TemporaryTypeSet *unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc); /* Add a type to this set using the specified allocator. */ - inline bool addType(Type type, LifoAlloc *alloc); + inline void addType(Type type, LifoAlloc *alloc); /* Get a list of all types in this set. */ typedef Vector TypeList; @@ -543,7 +547,6 @@ class TypeSet inline TypeObjectKey *getObject(unsigned i) const; inline JSObject *getSingleObject(unsigned i) const; inline TypeObject *getTypeObject(unsigned i) const; - inline bool getTypeOrSingleObject(JSContext *cx, unsigned i, TypeObject **obj) const; /* The Class of an object in this set. */ inline const Class *getObjectClass(unsigned i) const; @@ -568,7 +571,7 @@ class TypeSet bool isSubset(TypeSet *other); /* Forward all types in this set to the specified constraint. */ - void addTypesToConstraint(JSContext *cx, TypeConstraint *constraint); + bool addTypesToConstraint(JSContext *cx, TypeConstraint *constraint); // Clone a type set into an arbitrary allocator. TemporaryTypeSet *clone(LifoAlloc *alloc) const; @@ -599,7 +602,7 @@ class ConstraintTypeSet : public TypeSet inline void addType(ExclusiveContext *cx, Type type); /* Add a new constraint to this set. */ - void add(JSContext *cx, TypeConstraint *constraint, bool callExisting = true); + bool addConstraint(JSContext *cx, TypeConstraint *constraint, bool callExisting = true); inline void sweep(JS::Zone *zone); }; @@ -739,7 +742,7 @@ class TemporaryTypeSet : public TypeSet bool AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, TypeObject *type, HandleId id); -void +bool AddClearDefiniteFunctionUsesInScript(JSContext *cx, TypeObject *type, JSScript *script, JSScript *calleeScript); @@ -1108,8 +1111,6 @@ struct TypeObject : gc::BarrieredCell void addPrototype(JSContext *cx, TypeObject *proto); 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 markPropertyNonData(ExclusiveContext *cx, jsid id); void markPropertyNonWritable(ExclusiveContext *cx, jsid id); void markStateChange(ExclusiveContext *cx); @@ -1527,9 +1528,6 @@ struct TypeCompartment /* Get or make an object for an allocation site, and add to the allocation site table. */ TypeObject *addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey key); - /* Mark all types as needing destruction once inference has 'finished'. */ - void setPendingNukeTypes(ExclusiveContext *cx); - /* Mark any type set containing obj as having a generic object type. */ void markSetsUnknown(JSContext *cx, TypeObject *obj); @@ -1562,12 +1560,6 @@ struct TypeZone /* Pending recompilations to perform before execution of JIT code can resume. */ Vector *pendingRecompiles; - /* - * Bit set if all current types must be marked as unknown, and all scripts - * recompiled. Caused by OOM failure within inference operations. - */ - bool pendingNukeTypes; - /* Whether type inference is enabled in this compartment. */ bool inferenceEnabled; @@ -1579,16 +1571,11 @@ struct TypeZone void sweep(FreeOp *fop, bool releaseTypes); - /* Mark all types as needing destruction once inference has 'finished'. */ - void setPendingNukeTypes(); - /* Mark a script as needing recompilation once inference has finished. */ void addPendingRecompile(JSContext *cx, const RecompileInfo &info); void addPendingRecompile(JSContext *cx, JSScript *script); void processPendingRecompiles(FreeOp *fop); - - void nukeTypes(FreeOp *fop); }; enum SpewChannel { diff --git a/js/src/jsinferinlines.h b/js/src/jsinferinlines.h index 87a9cdaaa5a7..ddb7d2d3f198 100644 --- a/js/src/jsinferinlines.h +++ b/js/src/jsinferinlines.h @@ -247,9 +247,7 @@ struct AutoEnterAnalysis */ if (!compartment->activeAnalysis) { TypeZone &types = compartment->zone()->types; - if (types.pendingNukeTypes) - types.nukeTypes(freeOp); - else if (types.pendingRecompiles) + if (types.pendingRecompiles) types.processPendingRecompiles(freeOp); } } @@ -385,12 +383,11 @@ EnsureTrackPropertyTypes(JSContext *cx, JSObject *obj, jsid id) if (obj->hasSingletonType()) { AutoEnterAnalysis enter(cx); if (obj->hasLazyType() && !obj->getType(cx)) { - cx->compartment()->types.setPendingNukeTypes(cx); - cx->clearPendingException(); + CrashAtUnhandlableOOM("Could not allocate TypeObject in EnsureTrackPropertyTypes"); return; } if (!obj->type()->unknownProperties() && !obj->type()->getProperty(cx, id)) { - cx->compartment()->types.setPendingNukeTypes(cx); + obj->type()->markUnknown(cx); return; } } @@ -450,17 +447,17 @@ AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, const Value &val } inline void -AddTypeProperty(ExclusiveContext *cx, TypeObject *obj, const char *name, Type type) +AddTypeProperty(ExclusiveContext *cx, TypeObject *obj, jsid id, Type type) { if (cx->typeInferenceEnabled() && !obj->unknownProperties()) - obj->addPropertyType(cx, name, type); + obj->addPropertyType(cx, id, type); } inline void -AddTypeProperty(ExclusiveContext *cx, TypeObject *obj, const char *name, const Value &value) +AddTypeProperty(ExclusiveContext *cx, TypeObject *obj, jsid id, const Value &value) { if (cx->typeInferenceEnabled() && !obj->unknownProperties()) - obj->addPropertyType(cx, name, value); + obj->addPropertyType(cx, id, value); } /* Set one or more dynamic flags on a type object. */ @@ -1055,34 +1052,34 @@ TypeSet::clearObjects() objectSet = nullptr; } -bool +void TypeSet::addType(Type type, LifoAlloc *alloc) { if (unknown()) - return true; + return; if (type.isUnknown()) { flags |= TYPE_FLAG_BASE_MASK; clearObjects(); JS_ASSERT(unknown()); - return true; + return; } if (type.isPrimitive()) { TypeFlags flag = PrimitiveTypeFlag(type.primitive()); if (flags & flag) - return true; + return; /* If we add float to a type set it is also considered to contain int. */ if (flag == TYPE_FLAG_DOUBLE) flag |= TYPE_FLAG_INT32; flags |= flag; - return true; + return; } if (flags & TYPE_FLAG_ANYOBJECT) - return true; + return; if (type.isAnyObject()) goto unknownObject; @@ -1092,9 +1089,9 @@ TypeSet::addType(Type type, LifoAlloc *alloc) TypeObjectKey **pentry = HashSetInsert (*alloc, objectSet, objectCount, object); if (!pentry) - return false; + goto unknownObject; if (*pentry) - return true; + return; *pentry = object; setBaseObjectCount(objectCount); @@ -1116,8 +1113,6 @@ TypeSet::addType(Type type, LifoAlloc *alloc) flags |= TYPE_FLAG_ANYOBJECT; clearObjects(); } - - return true; } inline void @@ -1128,10 +1123,10 @@ ConstraintTypeSet::addType(ExclusiveContext *cxArg, Type type) if (hasType(type)) return; - if (!TypeSet::addType(type, &cxArg->typeLifoAlloc())) { - cxArg->compartment()->types.setPendingNukeTypes(cxArg); - return; - } + TypeSet::addType(type, &cxArg->typeLifoAlloc()); + + if (type.isObjectUnchecked() && unknownObject()) + type = Type::AnyObjectType(); InferSpew(ISpewOps, "addType: %sT%p%s %s", InferSpewColor(this), this, InferSpewColorReset(), @@ -1219,30 +1214,6 @@ TypeSet::getTypeObject(unsigned i) const return (key && key->isTypeObject()) ? key->asTypeObject() : nullptr; } -inline bool -TypeSet::getTypeOrSingleObject(JSContext *cx, unsigned i, TypeObject **result) const -{ - JS_ASSERT(result); - JS_ASSERT(cx->compartment()->activeAnalysis); - - *result = nullptr; - - TypeObject *type = getTypeObject(i); - if (!type) { - JSObject *singleton = getSingleObject(i); - if (!singleton) - return true; - - type = singleton->uninlinedGetType(cx); - if (!type) { - cx->compartment()->types.setPendingNukeTypes(cx); - return false; - } - } - *result = type; - return true; -} - inline const Class * TypeSet::getObjectClass(unsigned i) const { @@ -1302,7 +1273,7 @@ TypeObject::getProperty(ExclusiveContext *cx, jsid id) Property **pprop = HashSetInsert (cx->typeLifoAlloc(), propertySet, propertyCount, id); if (!pprop) { - cx->compartment()->types.setPendingNukeTypes(cx); + markUnknown(cx); return nullptr; } @@ -1310,8 +1281,7 @@ TypeObject::getProperty(ExclusiveContext *cx, jsid id) setBasePropertyCount(propertyCount); if (!addProperty(cx, id, pprop)) { - setBasePropertyCount(0); - propertySet = nullptr; + markUnknown(cx); return nullptr; } diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index f5bf26cca9d2..54ed095d5be0 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -3209,7 +3209,7 @@ SplitHelper(JSContext *cx, Handle str, uint32_t limit, const Ma return nullptr; } else { /* Only string entries have been accounted for so far. */ - AddTypeProperty(cx, type, nullptr, UndefinedValue()); + AddTypeProperty(cx, type, JSID_VOID, UndefinedValue()); if (!splits.append(UndefinedValue())) return nullptr; } @@ -3344,7 +3344,7 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp) RootedTypeObject type(cx, GetTypeCallerInitObject(cx, JSProto_Array)); if (!type) return false; - AddTypeProperty(cx, type, nullptr, Type::StringType()); + AddTypeProperty(cx, type, JSID_VOID, Type::StringType()); /* Step 5: Use the second argument as the split limit, if given. */ uint32_t limit;