Bug 1232205 - Wasm baseline: infrastructure. r=bbouvier, r=luke

--HG--
extra : rebase_source : 8e63d1b7ee1a07f8c7cb5d0331eeb11b29620abf
This commit is contained in:
Lars T Hansen 2016-06-14 11:22:21 +01:00
Родитель 99a05c4022
Коммит 9e9fafcd38
12 изменённых файлов: 218 добавлений и 20 удалений

Просмотреть файл

@ -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.