/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * * Copyright 2015 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
// Display the main error, if any. if (!success) { constchar* errorString = error ? error.get() : "out of memory"; if (maybeFuncIndex.isSome()) {
LogOffThread( "'%s': wasm partial tier-2 (func index %u) failed with '%s'.\n",
contextString, maybeFuncIndex.value(), errorString);
} else {
LogOffThread("'%s': wasm complete tier-2 failed with '%s'.\n",
contextString, errorString);
}
}
// Display warnings as a follow-up, avoiding spamming the console.
size_t numWarnings = std::min<size_t>(warnings.length(), 3);
for (size_t i = 0; i < numWarnings; i++) { // Per the assertion above, we won't get warnings for partial tier-2.
LogOffThread("'%s': wasm complete tier-2 warning: '%s'.\n'.", contextString,
warnings[i].get());
} if (warnings.length() > numWarnings) {
LogOffThread("'%s': other warnings suppressed.\n", contextString);
}
}
class Module::CompleteTier2GeneratorTaskImpl
: public CompleteTier2GeneratorTask {
SharedBytes bytecode_;
SharedModule module_;
mozilla::Atomic<bool> cancelled_;
// Compile complete tier-2 and report any warning/errors as long as it's // not a cancellation. Encountering a warning/error during compilation // and being cancelled may race with each other, but the only observable // race should be being cancelled after a warning/error is set, and // that's okay.
UniqueChars error;
UniqueCharsVector warnings; bool success = CompileCompleteTier2(bytecode_->vector, *module_, &error,
&warnings, &cancelled_); if (!cancelled_) { // We could try to dispatch a runnable to the thread that started this // compilation, so as to report the warning/error using a JSContext*. // For now we just report to stderr.
ReportTier2ResultsOffThread(success, mozilla::Nothing(),
module_->codeMeta().scriptedCaller(), error,
warnings);
}
}
// During shutdown the main thread will wait for any ongoing (cancelled) // complete tier-2 generation to shut down normally. To do so, it waits on // the HelperThreadState's condition variable for the count of finished // generators to rise.
HelperThreadState().incWasmCompleteTier2GeneratorsFinished(locked);
// The task is finished, release it.
js_delete(this);
}
auto task = MakeUnique<CompleteTier2GeneratorTaskImpl>(bytecode, *this); if (!task) { return;
}
// These will be cleared asynchronously by ~CompleteTier2GeneratorTaskImpl() // if not sooner by finishTier2().
completeTier2Listener_ = listener;
testingTier2Active_ = true;
// Tier-2 is done; let everyone know. Mark tier-2 active for testing // purposes so that wasmHasTier2CompilationCompleted() only returns true // after tier-2 has been fully cached.
if (completeTier2Listener_ && canSerialize()) {
Bytes bytes; if (serialize(&bytes)) {
completeTier2Listener_->storeOptimizedEncoding(bytes.begin(),
bytes.length());
}
completeTier2Listener_ = nullptr;
}
testingTier2Active_ = false;
returntrue;
}
void Module::testingBlockOnTier2Complete() const { while (testingTier2Active_) {
ThisThread::SleepMilliseconds(1);
}
}
/* virtual */
JSObject* Module::createObjectForAsmJS(JSContext* cx) const { // Use nullptr to get the default object prototype. These objects are never // exposed to script for asm.js. return WasmModuleObject::create(cx, *this, nullptr);
}
bool wasm::GetOptimizedEncodingBuildId(JS::BuildIdCharVector* buildId) { // From a JS API perspective, the "build id" covers everything that can // cause machine code to become invalid, so include both the actual build-id // and cpu-id.
if (!GetBuildId || !GetBuildId(buildId)) { returnfalse;
}
// Extracting machine code as JS object. The result has the "code" property, as // a Uint8Array, and the "segments" property as array objects. The objects // contain offsets in the "code" array and basic information about a code // segment/function body. bool Module::extractCode(JSContext* cx, Tier tier,
MutableHandleValue vp) const {
Rooted<PlainObject*> result(cx, NewPlainObject(cx)); if (!result) { returnfalse;
}
// This function is only used for testing purposes so we can simply // block on tiered compilation to complete.
testingBlockOnTier2Complete();
if (!code_->hasCompleteTier(tier)) {
vp.setNull(); returntrue;
}
// asm.js module instantiation supplies its own buffer, but for wasm, create and // initialize the buffer if one is requested. Either way, the buffer is wrapped // in a WebAssembly.Memory object which is what the Instance stores. bool Module::instantiateMemories(
JSContext* cx, const WasmMemoryObjectVector& memoryImports,
MutableHandle<WasmMemoryObjectVector> memoryObjs) const { for (uint32_t memoryIndex = 0; memoryIndex < codeMeta().memories.length();
memoryIndex++) { const MemoryDesc& desc = codeMeta().memories[memoryIndex];
RootedVal val(cx); if (global.kind() == GlobalKind::Import) { // If this is an import, then this must be a constant global that was // provided without a global object. We must initialize it with the // provided value while we still can differentiate this case.
MOZ_ASSERT(!global.isMutable());
val.set(Val(globalImportValues[globalIndex]));
} else { // If this is not an import, then the initial value will be set by // Instance::init() for indirect globals or else by CreateExportObject(). // In either case, we initialize with a default value here.
val.set(Val(global.type()));
}
bool Module::instantiateGlobals(JSContext* cx, const ValVector& globalImportValues,
WasmGlobalObjectVector& globalObjs) const { // If there are exported globals that aren't in globalObjs because they // originate in this module or because they were immutable imports that came // in as primitive values then we must create cells in the globalObjs for // them here, as WasmInstanceObject::create() and CreateExportObject() will // need the cells to exist.
for (const Export& exp : moduleMeta().exports) { if (exp.kind() != DefinitionKind::Global) { continue;
} unsigned globalIndex = exp.globalIndex(); const GlobalDesc& global = globals[globalIndex]; if (!EnsureExportedGlobalObject(cx, globalImportValues, globalIndex, global,
globalObjs)) { returnfalse;
}
}
// Imported globals that are not re-exported may also have received only a // primitive value; these globals are always immutable. Assert that we do // not need to create any additional Global objects for such imports.
staticbool GetGlobalExport(JSContext* cx,
Handle<WasmInstanceObject*> instanceObj, const JSObjectVector& funcImports, const GlobalDesc& global, uint32_t globalIndex, const ValVector& globalImportValues, const WasmGlobalObjectVector& globalObjs,
MutableHandleValue val) { // A global object for this index is guaranteed to exist by // instantiateGlobals.
Rooted<WasmGlobalObject*> globalObj(cx, globalObjs[globalIndex]);
val.setObject(*globalObj);
// We are responsible to set the initial value of the global object here if // it's not imported or indirect. Imported global objects have their initial // value set by their defining module, or are set by // EnsureExportedGlobalObject when a constant value is provided as an import. // Indirect exported globals that are not imported, are initialized in // Instance::init. if (global.isIndirect() || global.isImport()) { returntrue;
}
// This must be an exported immutable global defined in this module. The // instance either has compiled the value into the code or has its own copy // in its global data area. Either way, we must initialize the global object // with the same initial value.
MOZ_ASSERT(!global.isMutable());
MOZ_RELEASE_ASSERT(!global.isImport());
RootedVal globalVal(cx);
instanceObj->instance().constantGlobalGet(globalIndex, &globalVal);
globalObj->setVal(globalVal); returntrue;
}
if (!instantiateFunctions(cx, imports.funcs)) { returnfalse;
}
Rooted<WasmMemoryObjectVector> memories(cx); if (!instantiateMemories(cx, imports.memories, &memories)) { returnfalse;
}
// Note that the following will extend imports.exceptionObjs with wrappers for // the local (non-imported) exceptions of the module. // The resulting vector is sparse, i.e., it will be null in slots that contain // exceptions that are neither exported or imported. // On the contrary, all the slots of exceptionTags will be filled with // unique tags.
if (!instantiateTags(cx, imports.tagObjs)) { returnfalse;
}
// Note that tableObjs is sparse: it will be null in slots that contain // tables that are neither exported nor imported.
// Register the instance with the Realm so that it can find out about global // events like profiling being enabled in the realm. Registration does not // require a fully-initialized instance and must precede initSegments as the // final pre-requisite for a live instance.
if (!cx->realm()->wasm.registerInstance(cx, instance)) {
ReportOutOfMemory(cx); returnfalse;
}
// Perform initialization as the final step after the instance is fully // constructed since this can make the instance live to content (even if the // start function fails).
if (!instance->instance().initSegments(cx, moduleMeta().dataSegments,
moduleMeta().elemSegments)) { returnfalse;
}
// Now that the instance is fully live and initialized, the start function. // Note that failure may cause instantiation to throw, but the instance may // still be live via edges created by initSegments or the start function.
if (codeMeta().startFuncIndex) {
FixedInvokeArgs<0> args(cx); if (!instance->instance().callExport(cx, *codeMeta().startFuncIndex,
args)) { returnfalse;
}
}
if (cx->options().testWasmAwaitTier2() &&
code().mode() != CompileMode::LazyTiering) {
testingBlockOnTier2Complete();
}
returntrue;
}
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.29Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.