bool invalidateBailedOutScripts() { RootedScript script(cx_, fun_->toFunction()->nonLazyScript()); // Sometimes the script is collected or invalidated already, // for example when a full GC runs at an inconvenient time. if (!script->hasParallelIonScript()) { JS_ASSERT(hasNoPendingInvalidations()); return true; } IonScript *ion = script->parallelIonScript(); JS_ASSERT(pendingInvalidations.length() == ion->parallelInvalidatedScriptEntries()); Vector<types::RecompileInfo> invalid(cx_); for (uint32_t i = 0; i < pendingInvalidations.length(); i++) { JSScript *script = pendingInvalidations[i]; if (script && !hasScript(invalid, script)) { JS_ASSERT(script->hasParallelIonScript()); if (!invalid.append(script->parallelIonScript()->recompileInfo())) return false; ion->parallelInvalidatedScriptList()[i] = script; } pendingInvalidations[i] = NULL; } Invalidate(cx_, invalid); return true; }
virtual bool parallel(ForkJoinSlice &slice) { #ifndef JS_ION JS_NOT_REACHED("Parallel execution without ion"); return false; #else Spew(SpewOps, "Up"); // Make a new IonContext for the slice, which is needed if we need to // re-enter the VM. IonContext icx(cx_, NULL); JS_ASSERT(pendingInvalidations[slice.sliceId] == NULL); JS_ASSERT(fun_->isFunction()); RootedFunction callee(cx_, fun_->toFunction()); if (!callee->nonLazyScript()->hasParallelIonScript()) { // Sometimes, particularly with GCZeal, the parallel ion // script can be collected between starting the parallel // op and reaching this point. In that case, we just fail // and fallback. Spew(SpewOps, "Down (Script no longer present)"); return false; } ParallelIonInvoke<3> fii(cx_, callee, 3); fii.args[0] = Int32Value(slice.sliceId); fii.args[1] = Int32Value(slice.numSlices); fii.args[2] = BooleanValue(false); bool ok = fii.invoke(cx_); JS_ASSERT(ok == !slice.abortedScript); if (!ok) { JSScript *script = slice.abortedScript; Spew(SpewBailouts, "Aborted script: %p (hasParallelIonScript? %d)", script, script->hasParallelIonScript()); JS_ASSERT(script->hasParallelIonScript()); pendingInvalidations[slice.sliceId] = script; } Spew(SpewOps, "Down"); return ok; #endif // JS_ION }
bool js::ParallelDo::invalidateBailedOutScripts() { RootedScript script(cx_, fun_->toFunction()->nonLazyScript()); // Sometimes the script is collected or invalidated already, // for example when a full GC runs at an inconvenient time. if (!script->hasParallelIonScript()) { return true; } Vector<types::RecompileInfo> invalid(cx_); for (uint32_t i = 0; i < bailoutRecords.length(); i++) { JSScript *script = bailoutRecords[i].topScript; // No script to invalidate. if (!script || !script->hasParallelIonScript()) continue; switch (bailoutRecords[i].cause) { // An interrupt is not the fault of the script, so don't // invalidate it. case ParallelBailoutInterrupt: continue; // An illegal write will not be made legal by invalidation. case ParallelBailoutIllegalWrite: continue; // For other cases, consider invalidation. default: break; } // Already invalidated. if (hasScript(invalid, script)) continue; if (!invalid.append(script->parallelIonScript()->recompileInfo())) return false; } Invalidate(cx_, invalid); return true; }