%PDF- %PDF-
| Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/wasm/ |
| Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/wasm/module-compiler.h |
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#if !V8_ENABLE_WEBASSEMBLY
#error This header should only be included if WebAssembly is enabled.
#endif // !V8_ENABLE_WEBASSEMBLY
#ifndef V8_WASM_MODULE_COMPILER_H_
#define V8_WASM_MODULE_COMPILER_H_
#include <atomic>
#include <functional>
#include <memory>
#include "include/v8-metrics.h"
#include "src/base/optional.h"
#include "src/base/platform/elapsed-timer.h"
#include "src/base/platform/mutex.h"
#include "src/base/platform/time.h"
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/logging/counters.h"
#include "src/tasks/cancelable-task.h"
#include "src/wasm/compilation-environment.h"
#include "src/wasm/wasm-features.h"
#include "src/wasm/wasm-import-wrapper-cache.h"
#include "src/wasm/wasm-module.h"
namespace v8 {
namespace base {
template <typename T>
class Vector;
} // namespace base
namespace internal {
class JSArrayBuffer;
class JSPromise;
class Counters;
class WasmModuleObject;
class WasmInstanceObject;
namespace wasm {
struct CompilationEnv;
class CompilationResultResolver;
class ErrorThrower;
class ModuleCompiler;
class NativeModule;
class ProfileInformation;
class StreamingDecoder;
class WasmCode;
struct WasmModule;
V8_EXPORT_PRIVATE
std::shared_ptr<NativeModule> CompileToNativeModule(
Isolate* isolate, WasmFeatures enabled_features, ErrorThrower* thrower,
std::shared_ptr<const WasmModule> module, ModuleWireBytes wire_bytes,
int compilation_id, v8::metrics::Recorder::ContextId context_id,
ProfileInformation* pgo_info);
V8_EXPORT_PRIVATE
void CompileJsToWasmWrappers(Isolate* isolate, const WasmModule* module);
// Compiles the wrapper for this (kind, sig) pair and sets the corresponding
// cache entry. Assumes the key already exists in the cache but has not been
// compiled yet.
V8_EXPORT_PRIVATE
WasmCode* CompileImportWrapper(
NativeModule* native_module, Counters* counters, ImportCallKind kind,
const FunctionSig* sig, uint32_t canonical_type_index, int expected_arity,
Suspend suspend, WasmImportWrapperCache::ModificationScope* cache_scope);
// Triggered by the WasmCompileLazy builtin. The return value indicates whether
// compilation was successful. Lazy compilation can fail only if validation is
// also lazy.
bool CompileLazy(Isolate*, Tagged<WasmInstanceObject>, int func_index);
// Throws the compilation error after failed lazy compilation.
void ThrowLazyCompilationError(Isolate* isolate,
const NativeModule* native_module,
int func_index);
// Trigger tier-up of a particular function to TurboFan. If tier-up was already
// triggered, we instead increase the priority with exponential back-off.
V8_EXPORT_PRIVATE void TriggerTierUp(Tagged<WasmInstanceObject> instance,
int func_index);
// Synchronous version of the above.
void TierUpNowForTesting(Isolate* isolate, Tagged<WasmInstanceObject> instance,
int func_index);
template <typename Key, typename KeyInfo, typename Hash>
class WrapperQueue {
public:
// Removes an arbitrary key from the queue and returns it.
// If the queue is empty, returns nullopt.
// Thread-safe.
base::Optional<std::pair<Key, KeyInfo>> pop() {
base::Optional<std::pair<Key, KeyInfo>> key = base::nullopt;
base::MutexGuard lock(&mutex_);
auto it = queue_.begin();
if (it != queue_.end()) {
key = *it;
queue_.erase(it);
}
return key;
}
// Add the given key to the queue and returns true iff the insert was
// successful.
// Not thread-safe.
bool insert(const Key& key, KeyInfo key_info) {
return queue_.insert({key, key_info}).second;
}
size_t size() {
base::MutexGuard lock(&mutex_);
return queue_.size();
}
private:
base::Mutex mutex_;
std::unordered_map<Key, KeyInfo, Hash> queue_;
};
// Encapsulates all the state and steps of an asynchronous compilation.
// An asynchronous compile job consists of a number of tasks that are executed
// as foreground and background tasks. Any phase that touches the V8 heap or
// allocates on the V8 heap (e.g. creating the module object) must be a
// foreground task. All other tasks (e.g. decoding and validating, the majority
// of the work of compilation) can be background tasks.
// TODO(wasm): factor out common parts of this with the synchronous pipeline.
class AsyncCompileJob {
public:
AsyncCompileJob(Isolate* isolate, WasmFeatures enabled_features,
base::OwnedVector<const uint8_t> bytes,
Handle<Context> context,
Handle<NativeContext> incumbent_context,
const char* api_method_name,
std::shared_ptr<CompilationResultResolver> resolver,
int compilation_id);
~AsyncCompileJob();
void Start();
std::shared_ptr<StreamingDecoder> CreateStreamingDecoder();
void Abort();
void CancelPendingForegroundTask();
Isolate* isolate() const { return isolate_; }
Handle<NativeContext> context() const { return native_context_; }
v8::metrics::Recorder::ContextId context_id() const { return context_id_; }
private:
class CompileTask;
class CompileStep;
class CompilationStateCallback;
// States of the AsyncCompileJob.
// Step 1 (async). Decodes the wasm module.
// --> Fail on decoding failure,
// --> PrepareAndStartCompile on success.
class DecodeModule;
// Step 2 (sync). Prepares runtime objects and starts background compilation.
// --> finish directly on native module cache hit,
// --> finish directly on validation error,
// --> trigger eager compilation, if any; FinishCompile is triggered when
// done.
class PrepareAndStartCompile;
// Step 3 (sync). Compilation finished. Finalize the module and resolve the
// promise.
class FinishCompilation;
// Step 4 (sync). Decoding, validation or compilation failed. Reject the
// promise.
class Fail;
friend class AsyncStreamingProcessor;
enum FinishingComponent { kStreamingDecoder, kCompilation };
// Decrements the number of outstanding finishers. The last caller of this
// function should finish the asynchronous compilation, see the comment on
// {outstanding_finishers_}.
V8_WARN_UNUSED_RESULT bool DecrementAndCheckFinisherCount(
FinishingComponent component) {
base::MutexGuard guard(&check_finisher_mutex_);
DCHECK_LT(0, outstanding_finishers_);
if (outstanding_finishers_-- == 2) {
// The first component finished, we just start a timer for a histogram.
streaming_until_finished_timer_.Start();
return false;
}
// The timer has only been started above in the case of streaming
// compilation.
if (streaming_until_finished_timer_.IsStarted()) {
// We measure the time delta from when the StreamingDecoder finishes until
// when module compilation finishes. Depending on whether streaming or
// compilation finishes first we add the delta to the according histogram.
int elapsed = static_cast<int>(
streaming_until_finished_timer_.Elapsed().InMilliseconds());
if (component == kStreamingDecoder) {
isolate_->counters()
->wasm_compilation_until_streaming_finished()
->AddSample(elapsed);
} else {
isolate_->counters()
->wasm_streaming_until_compilation_finished()
->AddSample(elapsed);
}
}
DCHECK_EQ(0, outstanding_finishers_);
return true;
}
void CreateNativeModule(std::shared_ptr<const WasmModule> module,
size_t code_size_estimate);
// Return true for cache hit, false for cache miss.
bool GetOrCreateNativeModule(std::shared_ptr<const WasmModule> module,
size_t code_size_estimate);
void PrepareRuntimeObjects();
void FinishCompile(bool is_after_cache_hit);
void Failed();
void AsyncCompileSucceeded(Handle<WasmModuleObject> result);
void FinishSuccessfully();
void StartForegroundTask();
void ExecuteForegroundTaskImmediately();
void StartBackgroundTask();
enum UseExistingForegroundTask : bool {
kUseExistingForegroundTask = true,
kAssertNoExistingForegroundTask = false
};
// Switches to the compilation step {Step} and starts a foreground task to
// execute it. Most of the time we know that there cannot be a running
// foreground task. If there might be one, then pass
// kUseExistingForegroundTask to avoid spawning a second one.
template <typename Step,
UseExistingForegroundTask = kAssertNoExistingForegroundTask,
typename... Args>
void DoSync(Args&&... args);
// Switches to the compilation step {Step} and immediately executes that step.
template <typename Step, typename... Args>
void DoImmediately(Args&&... args);
// Switches to the compilation step {Step} and starts a background task to
// execute it.
template <typename Step, typename... Args>
void DoAsync(Args&&... args);
// Switches to the compilation step {Step} but does not start a task to
// execute it.
template <typename Step, typename... Args>
void NextStep(Args&&... args);
Isolate* const isolate_;
const char* const api_method_name_;
const WasmFeatures enabled_features_;
const DynamicTiering dynamic_tiering_;
base::TimeTicks start_time_;
// Copy of the module wire bytes, moved into the {native_module_} on its
// creation.
base::OwnedVector<const uint8_t> bytes_copy_;
// Reference to the wire bytes (held in {bytes_copy_} or as part of
// {native_module_}).
ModuleWireBytes wire_bytes_;
Handle<NativeContext> native_context_;
Handle<NativeContext> incumbent_context_;
v8::metrics::Recorder::ContextId context_id_;
v8::metrics::WasmModuleDecoded metrics_event_;
const std::shared_ptr<CompilationResultResolver> resolver_;
Handle<WasmModuleObject> module_object_;
std::shared_ptr<NativeModule> native_module_;
std::unique_ptr<CompileStep> step_;
CancelableTaskManager background_task_manager_;
std::shared_ptr<v8::TaskRunner> foreground_task_runner_;
// For async compilation the AsyncCompileJob is the only finisher. For
// streaming compilation also the AsyncStreamingProcessor has to finish before
// compilation can be finished.
int32_t outstanding_finishers_ = 1;
base::ElapsedTimer streaming_until_finished_timer_;
base::Mutex check_finisher_mutex_;
// A reference to a pending foreground task, or {nullptr} if none is pending.
CompileTask* pending_foreground_task_ = nullptr;
// The AsyncCompileJob owns the StreamingDecoder because the StreamingDecoder
// contains data which is needed by the AsyncCompileJob for streaming
// compilation. The AsyncCompileJob does not actively use the
// StreamingDecoder.
std::shared_ptr<StreamingDecoder> stream_;
// The compilation id to identify trace events linked to this compilation.
const int compilation_id_;
};
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_MODULE_COMPILER_H_