зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1232205 - Wasm baseline: infrastructure. r=bbouvier, r=luke
--HG-- extra : rebase_source : 8e63d1b7ee1a07f8c7cb5d0331eeb11b29620abf
This commit is contained in:
Родитель
99a05c4022
Коммит
9e9fafcd38
|
@ -2372,7 +2372,7 @@ IsSimdTuple(ModuleValidator& m, ParseNode* pn, SimdType* type)
|
|||
}
|
||||
|
||||
static bool
|
||||
IsNumericLiteral(ModuleValidator& m, ParseNode* pn);
|
||||
IsNumericLiteral(ModuleValidator& m, ParseNode* pn, bool* isSimd = nullptr);
|
||||
|
||||
static NumLit
|
||||
ExtractNumericLiteral(ModuleValidator& m, ParseNode* pn);
|
||||
|
@ -2423,11 +2423,16 @@ IsSimdLiteral(ModuleValidator& m, ParseNode* pn)
|
|||
}
|
||||
|
||||
static bool
|
||||
IsNumericLiteral(ModuleValidator& m, ParseNode* pn)
|
||||
IsNumericLiteral(ModuleValidator& m, ParseNode* pn, bool* isSimd)
|
||||
{
|
||||
return IsNumericNonFloatLiteral(pn) ||
|
||||
IsFloatLiteral(m, pn) ||
|
||||
IsSimdLiteral(m, pn);
|
||||
if (IsNumericNonFloatLiteral(pn) || IsFloatLiteral(m, pn))
|
||||
return true;
|
||||
if (IsSimdLiteral(m, pn)) {
|
||||
if (isSimd)
|
||||
*isSimd = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// The JS grammar treats -42 as -(42) (i.e., with separate grammar
|
||||
|
@ -2756,9 +2761,13 @@ SimdToExpr(SimdType type, SimdOperation op)
|
|||
}
|
||||
|
||||
#undef CASE
|
||||
#undef I32CASE
|
||||
#undef F32CASE
|
||||
#undef B32CASE
|
||||
#undef I8x16CASE
|
||||
#undef I16x8CASE
|
||||
#undef I32x4CASE
|
||||
#undef F32x4CASE
|
||||
#undef B8x16CASE
|
||||
#undef B16x8CASE
|
||||
#undef B32x4CASE
|
||||
#undef ENUMERATE
|
||||
|
||||
typedef Vector<PropertyName*, 4, SystemAllocPolicy> NameVector;
|
||||
|
@ -2832,6 +2841,13 @@ class MOZ_STACK_CLASS FunctionValidator
|
|||
MOZ_ASSERT(continuableStack_.empty());
|
||||
MOZ_ASSERT(breakLabels_.empty());
|
||||
MOZ_ASSERT(continueLabels_.empty());
|
||||
for (auto iter = locals_.all(); !iter.empty(); iter.popFront()) {
|
||||
if (iter.front().value().type.isSimd()) {
|
||||
setUsesSimd();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return m_.mg().finishFuncDef(funcIndex, &fg_);
|
||||
}
|
||||
|
||||
|
@ -2851,6 +2867,16 @@ class MOZ_STACK_CLASS FunctionValidator
|
|||
return m_.failName(pn, fmt, name);
|
||||
}
|
||||
|
||||
/***************************************************** Attributes */
|
||||
|
||||
void setUsesSimd() {
|
||||
fg_.setUsesSimd();
|
||||
}
|
||||
|
||||
void setUsesAtomics() {
|
||||
fg_.setUsesAtomics();
|
||||
}
|
||||
|
||||
/***************************************************** Local scope setup */
|
||||
|
||||
bool addLocal(ParseNode* pn, PropertyName* name, Type type) {
|
||||
|
@ -3726,9 +3752,13 @@ IsLiteralOrConst(FunctionValidator& f, ParseNode* pn, NumLit* lit)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!IsNumericLiteral(f.m(), pn))
|
||||
bool isSimd = false;
|
||||
if (!IsNumericLiteral(f.m(), pn, &isSimd))
|
||||
return false;
|
||||
|
||||
if (isSimd)
|
||||
f.setUsesSimd();
|
||||
|
||||
*lit = ExtractNumericLiteral(f.m(), pn);
|
||||
return true;
|
||||
}
|
||||
|
@ -4528,6 +4558,8 @@ static bool
|
|||
CheckAtomicsBuiltinCall(FunctionValidator& f, ParseNode* callNode, AsmJSAtomicsBuiltinFunction func,
|
||||
Type* type)
|
||||
{
|
||||
f.setUsesAtomics();
|
||||
|
||||
switch (func) {
|
||||
case AsmJSAtomicsBuiltin_compareExchange:
|
||||
return CheckAtomicsCompareExchange(f, callNode, type);
|
||||
|
@ -5450,6 +5482,8 @@ static bool
|
|||
CheckSimdOperationCall(FunctionValidator& f, ParseNode* call, const ModuleValidator::Global* global,
|
||||
Type* type)
|
||||
{
|
||||
f.setUsesSimd();
|
||||
|
||||
MOZ_ASSERT(global->isSimdOperation());
|
||||
|
||||
SimdType opType = global->simdOperationType();
|
||||
|
@ -5542,6 +5576,8 @@ static bool
|
|||
CheckSimdCtorCall(FunctionValidator& f, ParseNode* call, const ModuleValidator::Global* global,
|
||||
Type* type)
|
||||
{
|
||||
f.setUsesSimd();
|
||||
|
||||
MOZ_ASSERT(call->isKind(PNK_CALL));
|
||||
|
||||
SimdType simdType = global->simdCtorType();
|
||||
|
@ -5674,7 +5710,10 @@ CheckCoercedCall(FunctionValidator& f, ParseNode* call, Type ret, Type* type)
|
|||
|
||||
JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
|
||||
|
||||
if (IsNumericLiteral(f.m(), call)) {
|
||||
bool isSimd = false;
|
||||
if (IsNumericLiteral(f.m(), call, &isSimd)) {
|
||||
if (isSimd)
|
||||
f.setUsesSimd();
|
||||
NumLit lit = ExtractNumericLiteral(f.m(), call);
|
||||
if (!f.writeConstExpr(lit))
|
||||
return false;
|
||||
|
@ -6213,8 +6252,12 @@ CheckExpr(FunctionValidator& f, ParseNode* expr, Type* type)
|
|||
{
|
||||
JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
|
||||
|
||||
if (IsNumericLiteral(f.m(), expr))
|
||||
bool isSimd = false;
|
||||
if (IsNumericLiteral(f.m(), expr, &isSimd)) {
|
||||
if (isSimd)
|
||||
f.setUsesSimd();
|
||||
return CheckNumericLiteral(f, expr, type);
|
||||
}
|
||||
|
||||
switch (expr->getKind()) {
|
||||
case PNK_NAME: return CheckVarRef(f, expr, type);
|
||||
|
|
|
@ -126,9 +126,8 @@ CheckValType(JSContext* cx, Decoder& d, ValType type)
|
|||
case ValType::F64:
|
||||
return true;
|
||||
case ValType::I64:
|
||||
#ifndef JS_CPU_X64
|
||||
return Fail(cx, d, "i64 NYI on this platform");
|
||||
#endif
|
||||
if (!IsI64Implemented())
|
||||
return Fail(cx, d, "i64 NYI on this platform");
|
||||
return true;
|
||||
default:
|
||||
// Note: it's important not to remove this default since readValType()
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
#include "asmjs/WasmBaselineCompile.h"
|
||||
|
||||
bool
|
||||
wasm::BaselineCanCompile(const FunctionGenerator* fg)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::BaselineCompileFunction(IonCompileTask* task)
|
||||
{
|
||||
MOZ_ASSERT(task->mode() == IonCompileTask::CompileMode::Baseline);
|
||||
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef asmjs_wasm_baseline_compile_h
|
||||
#define asmjs_wasm_baseline_compile_h
|
||||
|
||||
#include "asmjs/WasmBinary.h"
|
||||
#include "asmjs/WasmIonCompile.h"
|
||||
|
||||
namespace js {
|
||||
namespace wasm {
|
||||
|
||||
class FunctionGenerator;
|
||||
|
||||
// Return true if BaselineCompileFunction can generate code for the
|
||||
// function held in the FunctionGenerator. If false is returned a
|
||||
// different compilation strategy must be chosen.
|
||||
//
|
||||
// This allows the baseline compiler to have different capabilities on
|
||||
// different platforms and defer to the full Ion compiler if
|
||||
// capabilities are missing. The FunctionGenerator and other data
|
||||
// structures contain information about the capabilities that are
|
||||
// required to compile the function.
|
||||
bool
|
||||
BaselineCanCompile(const FunctionGenerator* fg);
|
||||
|
||||
// Generate adequate code quickly.
|
||||
bool
|
||||
BaselineCompileFunction(IonCompileTask* task);
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace js
|
||||
|
||||
#endif // asmjs_wasm_baseline_compile_h
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "mozilla/EnumeratedRange.h"
|
||||
|
||||
#include "asmjs/WasmBaselineCompile.h"
|
||||
#include "asmjs/WasmIonCompile.h"
|
||||
#include "asmjs/WasmStubs.h"
|
||||
|
||||
|
@ -802,14 +803,18 @@ ModuleGenerator::finishFuncDef(uint32_t funcIndex, FunctionGenerator* fg)
|
|||
if (!func)
|
||||
return false;
|
||||
|
||||
fg->task_->init(Move(func));
|
||||
JSRuntime* rt = cx_->compartment()->runtimeFromAnyThread();
|
||||
bool baselineCompile = rt->options().wasmAlwaysBaseline() && BaselineCanCompile(fg);
|
||||
|
||||
fg->task_->init(Move(func), baselineCompile ? IonCompileTask::CompileMode::Baseline
|
||||
: IonCompileTask::CompileMode::Ion);
|
||||
|
||||
if (parallel_) {
|
||||
if (!StartOffThreadWasmCompile(cx_, fg->task_))
|
||||
return false;
|
||||
outstanding_++;
|
||||
} else {
|
||||
if (!IonCompileFunction(fg->task_))
|
||||
if (!CompileFunction(fg->task_))
|
||||
return false;
|
||||
if (!finishTask(fg->task_))
|
||||
return false;
|
||||
|
|
|
@ -212,6 +212,8 @@ class MOZ_STACK_CLASS FunctionGenerator
|
|||
|
||||
ModuleGenerator* m_;
|
||||
IonCompileTask* task_;
|
||||
bool usesSimd_;
|
||||
bool usesAtomics_;
|
||||
|
||||
// Data created during function generation, then handed over to the
|
||||
// FuncBytes in ModuleGenerator::finishFunc().
|
||||
|
@ -222,9 +224,27 @@ class MOZ_STACK_CLASS FunctionGenerator
|
|||
|
||||
public:
|
||||
FunctionGenerator()
|
||||
: m_(nullptr), task_(nullptr), lineOrBytecode_(0)
|
||||
: m_(nullptr), task_(nullptr), usesSimd_(false), usesAtomics_(false), lineOrBytecode_(0)
|
||||
{}
|
||||
|
||||
bool usesSimd() const {
|
||||
return usesSimd_;
|
||||
}
|
||||
void setUsesSimd() {
|
||||
usesSimd_ = true;
|
||||
}
|
||||
|
||||
bool usesAtomics() const {
|
||||
return usesAtomics_;
|
||||
}
|
||||
void setUsesAtomics() {
|
||||
usesAtomics_ = true;
|
||||
}
|
||||
|
||||
bool usesSignalsForInterrupts() const {
|
||||
return m_->args().useSignalHandlersForInterrupt;
|
||||
}
|
||||
|
||||
Bytes& bytes() {
|
||||
return bytes_;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "asmjs/WasmIonCompile.h"
|
||||
|
||||
#include "asmjs/WasmBaselineCompile.h"
|
||||
#include "asmjs/WasmBinaryIterator.h"
|
||||
#include "asmjs/WasmGenerator.h"
|
||||
|
||||
|
@ -3393,6 +3394,8 @@ EmitExpr(FunctionCompiler& f)
|
|||
bool
|
||||
wasm::IonCompileFunction(IonCompileTask* task)
|
||||
{
|
||||
MOZ_ASSERT(task->mode() == IonCompileTask::CompileMode::Ion);
|
||||
|
||||
const FuncBytes& func = task->func();
|
||||
FuncCompileResults& results = task->results();
|
||||
|
||||
|
@ -3463,3 +3466,18 @@ wasm::IonCompileFunction(IonCompileTask* task)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::CompileFunction(IonCompileTask* task)
|
||||
{
|
||||
switch (task->mode()) {
|
||||
case wasm::IonCompileTask::CompileMode::Ion:
|
||||
return wasm::IonCompileFunction(task);
|
||||
case wasm::IonCompileTask::CompileMode::Baseline:
|
||||
return wasm::BaselineCompileFunction(task);
|
||||
case wasm::IonCompileTask::CompileMode::None:
|
||||
MOZ_CRASH("Uninitialized task");
|
||||
}
|
||||
// Silence gcc 5.2.1 warning.
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -98,10 +98,15 @@ class FuncCompileResults
|
|||
|
||||
class IonCompileTask
|
||||
{
|
||||
public:
|
||||
enum class CompileMode { None, Baseline, Ion };
|
||||
|
||||
private:
|
||||
JSRuntime* const runtime_;
|
||||
const ModuleGeneratorData& mg_;
|
||||
LifoAlloc lifo_;
|
||||
UniqueFuncBytes func_;
|
||||
CompileMode mode_;
|
||||
Maybe<FuncCompileResults> results_;
|
||||
|
||||
IonCompileTask(const IonCompileTask&) = delete;
|
||||
|
@ -109,7 +114,7 @@ class IonCompileTask
|
|||
|
||||
public:
|
||||
IonCompileTask(JSRuntime* rt, const ModuleGeneratorData& mg, size_t defaultChunkSize)
|
||||
: runtime_(rt), mg_(mg), lifo_(defaultChunkSize), func_(nullptr)
|
||||
: runtime_(rt), mg_(mg), lifo_(defaultChunkSize), func_(nullptr), mode_(CompileMode::None)
|
||||
{}
|
||||
JSRuntime* runtime() const {
|
||||
return runtime_;
|
||||
|
@ -120,10 +125,14 @@ class IonCompileTask
|
|||
const ModuleGeneratorData& mg() const {
|
||||
return mg_;
|
||||
}
|
||||
void init(UniqueFuncBytes func) {
|
||||
void init(UniqueFuncBytes func, CompileMode mode) {
|
||||
MOZ_ASSERT(!func_);
|
||||
func_ = Move(func);
|
||||
results_.emplace(lifo_);
|
||||
mode_ = mode;
|
||||
}
|
||||
CompileMode mode() const {
|
||||
return mode_;
|
||||
}
|
||||
const FuncBytes& func() const {
|
||||
MOZ_ASSERT(func_);
|
||||
|
@ -138,12 +147,16 @@ class IonCompileTask
|
|||
func_.reset(nullptr);
|
||||
results_.reset();
|
||||
lifo_.releaseAll();
|
||||
mode_ = CompileMode::None;
|
||||
}
|
||||
};
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
IonCompileFunction(IonCompileTask* task);
|
||||
|
||||
bool
|
||||
CompileFunction(IonCompileTask* task);
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -1097,6 +1097,7 @@ class JS_PUBLIC_API(RuntimeOptions) {
|
|||
ion_(true),
|
||||
asmJS_(true),
|
||||
wasm_(false),
|
||||
wasmAlwaysBaseline_(false),
|
||||
throwOnAsmJSValidationFailure_(false),
|
||||
nativeRegExp_(true),
|
||||
unboxedArrays_(false),
|
||||
|
@ -1149,6 +1150,16 @@ class JS_PUBLIC_API(RuntimeOptions) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool wasmAlwaysBaseline() const { return wasmAlwaysBaseline_; }
|
||||
RuntimeOptions& setWasmAlwaysBaseline(bool flag) {
|
||||
wasmAlwaysBaseline_ = flag;
|
||||
return *this;
|
||||
}
|
||||
RuntimeOptions& toggleWasmAlwaysBaseline() {
|
||||
wasmAlwaysBaseline_ = !wasmAlwaysBaseline_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool throwOnAsmJSValidationFailure() const { return throwOnAsmJSValidationFailure_; }
|
||||
RuntimeOptions& setThrowOnAsmJSValidationFailure(bool flag) {
|
||||
throwOnAsmJSValidationFailure_ = flag;
|
||||
|
@ -1224,6 +1235,7 @@ class JS_PUBLIC_API(RuntimeOptions) {
|
|||
bool ion_ : 1;
|
||||
bool asmJS_ : 1;
|
||||
bool wasm_ : 1;
|
||||
bool wasmAlwaysBaseline_ : 1;
|
||||
bool throwOnAsmJSValidationFailure_ : 1;
|
||||
bool nativeRegExp_ : 1;
|
||||
bool unboxedArrays_ : 1;
|
||||
|
|
|
@ -155,6 +155,7 @@ EXPORTS.js += [
|
|||
UNIFIED_SOURCES += [
|
||||
'asmjs/AsmJS.cpp',
|
||||
'asmjs/Wasm.cpp',
|
||||
'asmjs/WasmBaselineCompile.cpp',
|
||||
'asmjs/WasmBinary.cpp',
|
||||
'asmjs/WasmBinaryIterator.cpp',
|
||||
'asmjs/WasmBinaryToAST.cpp',
|
||||
|
|
|
@ -205,6 +205,7 @@ static bool enableAsmJS = false;
|
|||
static bool enableNativeRegExp = false;
|
||||
static bool enableUnboxedArrays = false;
|
||||
static bool enableSharedMemory = SHARED_MEMORY_DEFAULT;
|
||||
static bool enableWasmAlwaysBaseline = false;
|
||||
#ifdef JS_GC_ZEAL
|
||||
static uint32_t gZealBits = 0;
|
||||
static uint32_t gZealFrequency = 0;
|
||||
|
@ -6783,11 +6784,13 @@ SetRuntimeOptions(JSRuntime* rt, const OptionParser& op)
|
|||
enableAsmJS = !op.getBoolOption("no-asmjs");
|
||||
enableNativeRegExp = !op.getBoolOption("no-native-regexp");
|
||||
enableUnboxedArrays = op.getBoolOption("unboxed-arrays");
|
||||
enableWasmAlwaysBaseline = op.getBoolOption("wasm-always-baseline");
|
||||
|
||||
JS::RuntimeOptionsRef(rt).setBaseline(enableBaseline)
|
||||
.setIon(enableIon)
|
||||
.setAsmJS(enableAsmJS)
|
||||
.setWasm(true)
|
||||
.setWasmAlwaysBaseline(enableWasmAlwaysBaseline)
|
||||
.setNativeRegExp(enableNativeRegExp)
|
||||
.setUnboxedArrays(enableUnboxedArrays);
|
||||
|
||||
|
@ -7056,6 +7059,7 @@ SetWorkerRuntimeOptions(JSRuntime* rt)
|
|||
.setIon(enableIon)
|
||||
.setAsmJS(enableAsmJS)
|
||||
.setWasm(true)
|
||||
.setWasmAlwaysBaseline(enableWasmAlwaysBaseline)
|
||||
.setNativeRegExp(enableNativeRegExp)
|
||||
.setUnboxedArrays(enableUnboxedArrays);
|
||||
rt->setOffthreadIonCompilationEnabled(offthreadCompilation);
|
||||
|
@ -7243,6 +7247,7 @@ main(int argc, char** argv, char** envp)
|
|||
|| !op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation")
|
||||
|| !op.addBoolOption('\0', "no-unboxed-objects", "Disable creating unboxed plain objects")
|
||||
|| !op.addBoolOption('\0', "unboxed-arrays", "Allow creating unboxed arrays")
|
||||
|| !op.addBoolOption('\0', "wasm-always-baseline", "Enable experimental Wasm baseline compiler when possible")
|
||||
#ifdef ENABLE_SHARED_ARRAY_BUFFER
|
||||
|| !op.addStringOption('\0', "shared-memory", "on/off",
|
||||
"SharedArrayBuffer and Atomics "
|
||||
|
|
|
@ -1385,7 +1385,7 @@ HelperThread::handleWasmWorkload()
|
|||
AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation);
|
||||
|
||||
PerThreadData::AutoEnterRuntime enter(threadData.ptr(), task->runtime());
|
||||
success = wasm::IonCompileFunction(task);
|
||||
success = wasm::CompileFunction(task);
|
||||
}
|
||||
|
||||
// On success, try to move work to the finished list.
|
||||
|
|
Загрузка…
Ссылка в новой задаче