#include "config.h"
#include "WasmPlan.h"
#if ENABLE(WEBASSEMBLY)
#include "B3Compilation.h"
#include "WasmB3IRGenerator.h"
#include "WasmBinding.h"
#include "WasmCallee.h"
#include "WasmCallingConvention.h"
#include "WasmFaultSignalHandler.h"
#include "WasmMemory.h"
#include "WasmModuleParser.h"
#include "WasmValidate.h"
#include <wtf/DataLog.h>
#include <wtf/Locker.h>
#include <wtf/MonotonicTime.h>
#include <wtf/StdLibExtras.h>
#include <wtf/SystemTracing.h>
namespace JSC { namespace Wasm {
namespace WasmPlanInternal {
static const bool verbose = false;
}
Plan::Plan(Context* context, Ref<ModuleInformation> info, CompletionTask&& task, CreateEmbedderWrapper&& createEmbedderWrapper, ThrowWasmException throwWasmException)
: m_moduleInformation(WTFMove(info))
, m_createEmbedderWrapper(WTFMove(createEmbedderWrapper))
, m_throwWasmException(throwWasmException)
, m_source(m_moduleInformation->source.data())
, m_sourceLength(m_moduleInformation->source.size())
{
m_completionTasks.append(std::make_pair(context, WTFMove(task)));
}
Plan::Plan(Context* context, Ref<ModuleInformation> info, CompletionTask&& task)
: Plan(context, WTFMove(info), WTFMove(task), nullptr, nullptr)
{
}
Plan::Plan(Context* context, const uint8_t* source, size_t sourceLength, CompletionTask&& task)
: m_moduleInformation(adoptRef(*new ModuleInformation(Vector<uint8_t>())))
, m_source(source)
, m_sourceLength(sourceLength)
{
m_completionTasks.append(std::make_pair(context, WTFMove(task)));
}
void Plan::runCompletionTasks(const AbstractLocker&)
{
ASSERT(isComplete() && !hasWork());
for (auto& task : m_completionTasks)
task.second->run(*this);
m_completionTasks.clear();
m_completed.notifyAll();
}
void Plan::addCompletionTask(Context* context, CompletionTask&& task)
{
LockHolder locker(m_lock);
if (!isComplete())
m_completionTasks.append(std::make_pair(context, WTFMove(task)));
else
task->run(*this);
}
void Plan::waitForCompletion()
{
LockHolder locker(m_lock);
if (!isComplete()) {
m_completed.wait(m_lock);
}
}
bool Plan::tryRemoveContextAndCancelIfLast(Context& context)
{
LockHolder locker(m_lock);
if (!ASSERT_DISABLED) {
for (unsigned i = 1; i < m_completionTasks.size(); ++i)
ASSERT(m_completionTasks[i].first);
}
bool removedAnyTasks = false;
m_completionTasks.removeAllMatching([&] (const std::pair<Context*, CompletionTask>& pair) {
bool shouldRemove = pair.first == &context;
removedAnyTasks |= shouldRemove;
return shouldRemove;
});
if (!removedAnyTasks)
return false;
if (isComplete()) {
return true;
}
if (m_completionTasks.isEmpty() || (m_completionTasks.size() == 1 && !m_completionTasks[0].first)) {
fail(locker, ASCIILiteral("WebAssembly Plan was cancelled. If you see this error message please file a bug at bugs.webkit.org!"));
return true;
}
return false;
}
void Plan::fail(const AbstractLocker& locker, String&& errorMessage)
{
dataLogLnIf(WasmPlanInternal::verbose, "failing with message: ", errorMessage);
m_errorMessage = WTFMove(errorMessage);
complete(locker);
}
Plan::~Plan() { }
} }
#endif // ENABLE(WEBASSEMBLY)