bool StructTypeRepresentation::init(JSContext *cx, AutoPropertyNameVector &names, AutoObjectVector &typeReprOwners) { JS_ASSERT(names.length() == typeReprOwners.length()); fieldCount_ = names.length(); // We compute alignment into the field `align_` directly in the // loop below, but not `size_` because we have to very careful // about overflow. For now, we always use a uint32_t for // consistency across build environments. uint32_t totalSize = 0; // These will be adjusted in the loop below: alignment_ = 1; opaque_ = false; for (size_t i = 0; i < names.length(); i++) { SizedTypeRepresentation *fieldTypeRepr = fromOwnerObject(*typeReprOwners[i])->asSized(); if (fieldTypeRepr->opaque()) opaque_ = true; uint32_t alignedSize = alignTo(totalSize, fieldTypeRepr->alignment()); if (alignedSize < totalSize) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_TOO_BIG); return false; } new(fields() + i) StructField(i, names[i], fieldTypeRepr, alignedSize); alignment_ = js::Max(alignment_, fieldTypeRepr->alignment()); uint32_t incrementedSize = alignedSize + fieldTypeRepr->size(); if (incrementedSize < alignedSize) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_TOO_BIG); return false; } totalSize = incrementedSize; } uint32_t alignedSize = alignTo(totalSize, alignment_); if (alignedSize < totalSize) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_TOO_BIG); return false; } size_ = alignedSize; return true; }
// Add the given set of globals as explicit roots in the given roots // list. Returns false on OOM failure. static bool AddGlobalsAsRoots(AutoObjectVector& globals, ubi::RootList& roots) { unsigned length = globals.length(); for (unsigned i = 0; i < length; i++) { if (!roots.addRoot(ubi::Node(globals[i].get()), MOZ_UTF16("heap snapshot global"))) { return false; } } return true; }
// If we are only taking a snapshot of the heap affected by the given set of // globals, find the set of zones the globals are allocated within. Returns // false on OOM failure. static bool PopulateZonesWithGlobals(ZoneSet& zones, AutoObjectVector& globals) { if (!zones.init()) return false; unsigned length = globals.length(); for (unsigned i = 0; i < length; i++) { if (!zones.put(GetObjectZone(globals[i]))) return false; } return true; }
static bool AddInnerLazyFunctionsFromScript(JSScript *script, AutoObjectVector &lazyFunctions) { if (!script->hasObjects()) return true; ObjectArray *objects = script->objects(); for (size_t i = script->innerObjectsStart(); i < objects->length; i++) { JSObject *obj = objects->vector[i]; if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpretedLazy()) { if (!lazyFunctions.append(obj)) return false; } } return true; }
static bool AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, AllocKind kind) { // Find all live root lazy functions in the compartment: those which have a // source object, indicating that they have a parent, and which do not have // an uncompiled enclosing script. The last condition is so that we don't // compile lazy scripts whose enclosing scripts failed to compile, // indicating that the lazy script did not escape the script. // // Some LazyScripts have a non-null |JSScript* script| pointer. We still // want to delazify in that case: this pointer is weak so the JSScript // could be destroyed at the next GC. for (auto i = cx->zone()->cellIter<JSObject>(kind); !i.done(); i.next()) { JSFunction* fun = &i->as<JSFunction>(); // Sweeping is incremental; take care to not delazify functions that // are about to be finalized. GC things referenced by objects that are // about to be finalized (e.g., in slots) may already be freed. if (gc::IsAboutToBeFinalizedUnbarriered(&fun) || fun->compartment() != cx->compartment()) { continue; } if (fun->isInterpretedLazy()) { LazyScript* lazy = fun->lazyScriptOrNull(); if (lazy && lazy->sourceObject() && !lazy->hasUncompiledEnclosingScript()) { if (!lazyFunctions.append(fun)) return false; } } } return true; }
static bool AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, AllocKind kind) { // Find all live root lazy functions in the compartment: those which // have not been compiled, which have a source object, indicating that // they have a parent, and which do not have an uncompiled enclosing // script. The last condition is so that we don't compile lazy scripts // whose enclosing scripts failed to compile, indicating that the lazy // script did not escape the script. for (gc::ZoneCellIter i(cx->zone(), kind); !i.done(); i.next()) { JSObject* obj = i.get<JSObject>(); // Sweeping is incremental; take care to not delazify functions that // are about to be finalized. GC things referenced by objects that are // about to be finalized (e.g., in slots) may already be freed. if (gc::IsObjectAboutToBeFinalized(&obj) || obj->compartment() != cx->compartment() || !obj->is<JSFunction>()) { continue; } JSFunction* fun = &obj->as<JSFunction>(); if (fun->isInterpretedLazy()) { LazyScript* lazy = fun->lazyScriptOrNull(); if (lazy && lazy->sourceObject() && !lazy->maybeScript() && !lazy->hasUncompiledEnclosingScript()) { if (!lazyFunctions.append(fun)) return false; } } } return true; }