static bool CreateLazyScriptsForCompartment(JSContext *cx) { AutoObjectVector lazyFunctions(cx); // Find all live lazy scripts in the compartment, and via them all 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(), gc::FINALIZE_LAZY_SCRIPT); !i.done(); i.next()) { LazyScript *lazy = i.get<LazyScript>(); JSFunction *fun = lazy->functionNonDelazifying(); if (fun->compartment() == cx->compartment() && lazy->sourceObject() && !lazy->maybeScript() && !lazy->hasUncompiledEnclosingScript()) { MOZ_ASSERT(fun->isInterpretedLazy()); MOZ_ASSERT(lazy == fun->lazyScriptOrNull()); if (!lazyFunctions.append(fun)) return false; } } // Create scripts for each lazy function, updating the list of functions to // process with any newly exposed inner functions in created scripts. // A function cannot be delazified until its outer script exists. for (size_t i = 0; i < lazyFunctions.length(); i++) { JSFunction *fun = &lazyFunctions[i]->as<JSFunction>(); // lazyFunctions may have been populated with multiple functions for // a lazy script. if (!fun->isInterpretedLazy()) continue; JSScript *script = fun->getOrCreateScript(cx); if (!script) return false; if (!AddInnerLazyFunctionsFromScript(script, lazyFunctions)) 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; }