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; }
MethodStatus compileForParallelExecution() { // The kernel should be a self-hosted function. if (!fun_->isFunction()) return Method_Skipped; RootedFunction callee(cx_, fun_->toFunction()); if (!callee->isInterpreted() || !callee->isSelfHostedBuiltin()) return Method_Skipped; if (callee->isInterpretedLazy() && !callee->initializeLazyScript(cx_)) return Method_Error; // If this function has not been run enough to enable parallel // execution, perform a warmup. RootedScript script(cx_, callee->nonLazyScript()); if (script->getUseCount() < js_IonOptions.usesBeforeCompileParallel) { if (!warmupForParallelExecution()) return Method_Error; } if (script->hasParallelIonScript() && !script->parallelIonScript()->hasInvalidatedCallTarget()) { Spew(SpewOps, "Already compiled"); return Method_Compiled; } Spew(SpewOps, "Compiling all reachable functions"); ParallelCompileContext compileContext(cx_); if (!compileContext.appendToWorklist(script)) return Method_Error; MethodStatus status = compileContext.compileTransitively(); if (status != Method_Compiled) return status; // it can happen that during transitive compilation, our // callee's parallel ion script is invalidated or GC'd. So // before we declare success, double check that it's still // compiled! if (!callee->nonLazyScript()->hasParallelIonScript()) return Method_Skipped; return Method_Compiled; }
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 }
JSObject * js_InitBooleanClass(JSContext *cx, HandleObject obj) { JS_ASSERT(obj->isNative()); Rooted<GlobalObject*> global(cx, &obj->asGlobal()); RootedObject booleanProto (cx, global->createBlankPrototype(cx, &BooleanClass)); if (!booleanProto) return NULL; booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false)); RootedFunction ctor(cx, global->createConstructor(cx, Boolean, cx->names().Boolean, 1)); if (!ctor) return NULL; if (!LinkConstructorAndPrototype(cx, ctor, booleanProto)) return NULL; if (!DefinePropertiesAndBrand(cx, booleanProto, NULL, boolean_methods)) return NULL; Handle<PropertyName*> valueOfName = cx->names().valueOf; RootedFunction valueOf(cx, js_NewFunction(cx, NullPtr(), bool_valueOf, 0, JSFunction::NATIVE_FUN, global, valueOfName)); if (!valueOf) return NULL; RootedValue value(cx, ObjectValue(*valueOf)); if (!JSObject::defineProperty(cx, booleanProto, valueOfName, value, JS_PropertyStub, JS_StrictPropertyStub, 0)) { return NULL; } global->setBooleanValueOf(valueOf); if (!DefineConstructorAndPrototype(cx, global, JSProto_Boolean, ctor, booleanProto)) return NULL; return booleanProto; }
JSObject * js_InitBooleanClass(JSContext *cx, JSObject *obj) { JS_ASSERT(obj->isNative()); Rooted<GlobalObject*> global(cx, &obj->asGlobal()); RootedObject booleanProto (cx, global->createBlankPrototype(cx, &BooleanClass)); if (!booleanProto) return NULL; booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false)); RootedFunction ctor(cx, global->createConstructor(cx, Boolean, CLASS_NAME(cx, Boolean), 1)); if (!ctor) return NULL; if (!LinkConstructorAndPrototype(cx, ctor, booleanProto)) return NULL; if (!DefinePropertiesAndBrand(cx, booleanProto, NULL, boolean_methods)) return NULL; Rooted<PropertyName*> valueOfName(cx, cx->runtime->atomState.valueOfAtom); Rooted<JSFunction*> valueOf(cx, js_NewFunction(cx, NULL, bool_valueOf, 0, 0, global, valueOfName)); if (!valueOf) return NULL; if (!booleanProto->defineProperty(cx, valueOfName, ObjectValue(*valueOf), JS_PropertyStub, JS_StrictPropertyStub, 0)) { return NULL; } global->setBooleanValueOf(valueOf); if (!DefineConstructorAndPrototype(cx, global, JSProto_Boolean, ctor, booleanProto)) return NULL; return booleanProto; }
bool append(uint32_t index, HandleValue v) { JS_ASSERT(!array->getOps()->getElement); return !!baseops::DefineElement(cx, array, index, v, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE); }