mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 04:15:43 +00:00
Backed out changeset 1b3a45aebcaf (bug 1258972) for landing with wrong bugnumber
This commit is contained in:
parent
41cca25d10
commit
2fb495c645
@ -590,20 +590,6 @@ class AstElemSegment : public AstNode
|
||||
|
||||
typedef AstVector<AstElemSegment*> AstElemSegmentVector;
|
||||
|
||||
class AstStartFunc : public AstNode
|
||||
{
|
||||
AstRef func_;
|
||||
|
||||
public:
|
||||
explicit AstStartFunc(AstRef func)
|
||||
: func_(func)
|
||||
{}
|
||||
|
||||
AstRef& func() {
|
||||
return func_;
|
||||
}
|
||||
};
|
||||
|
||||
class AstModule : public AstNode
|
||||
{
|
||||
public:
|
||||
@ -622,7 +608,6 @@ class AstModule : public AstNode
|
||||
Maybe<AstResizable> table_;
|
||||
Maybe<AstResizable> memory_;
|
||||
ExportVector exports_;
|
||||
Maybe<AstStartFunc> startFunc_;
|
||||
FuncVector funcs_;
|
||||
AstDataSegmentVector dataSegments_;
|
||||
AstElemSegmentVector elemSegments_;
|
||||
@ -677,18 +662,6 @@ class AstModule : public AstNode
|
||||
const AstElemSegmentVector& elemSegments() const {
|
||||
return elemSegments_;
|
||||
}
|
||||
bool hasStartFunc() const {
|
||||
return !!startFunc_;
|
||||
}
|
||||
bool setStartFunc(AstStartFunc startFunc) {
|
||||
if (startFunc_)
|
||||
return false;
|
||||
startFunc_.emplace(startFunc);
|
||||
return true;
|
||||
}
|
||||
AstStartFunc& startFunc() {
|
||||
return *startFunc_;
|
||||
}
|
||||
bool declare(AstSig&& sig, uint32_t* sigIndex) {
|
||||
SigMap::AddPtr p = sigMap_.lookupForAdd(sig);
|
||||
if (p) {
|
||||
|
@ -33,7 +33,6 @@ static const char FunctionSectionId[] = "function";
|
||||
static const char TableSectionId[] = "table";
|
||||
static const char MemorySectionId[] = "memory";
|
||||
static const char ExportSectionId[] = "export";
|
||||
static const char StartSectionId[] = "start";
|
||||
static const char CodeSectionId[] = "code";
|
||||
static const char ElemSectionId[] = "elem";
|
||||
static const char DataSectionId[] = "data";
|
||||
|
@ -1086,39 +1086,6 @@ DecodeFunctionBody(Decoder& d, ModuleGenerator& mg, uint32_t funcIndex)
|
||||
return mg.finishFuncDef(funcIndex, &fg);
|
||||
}
|
||||
|
||||
static bool
|
||||
DecodeStartSection(Decoder& d, ModuleGenerator& mg)
|
||||
{
|
||||
|
||||
uint32_t sectionStart, sectionSize;
|
||||
if (!d.startSection(StartSectionId, §ionStart, §ionSize))
|
||||
return Fail(d, "failed to start section");
|
||||
if (sectionStart == Decoder::NotStarted)
|
||||
return true;
|
||||
|
||||
uint32_t startFuncIndex;
|
||||
if (!d.readVarU32(&startFuncIndex))
|
||||
return Fail(d, "failed to read start func index");
|
||||
|
||||
if (startFuncIndex >= mg.numFuncSigs())
|
||||
return Fail(d, "unknown start function");
|
||||
|
||||
const DeclaredSig& sig = mg.funcSig(startFuncIndex);
|
||||
if (sig.ret() != ExprType::Void)
|
||||
return Fail(d, "start function must not return anything");
|
||||
|
||||
if (sig.args().length())
|
||||
return Fail(d, "start function must be nullary");
|
||||
|
||||
if (!mg.setStartFunction(startFuncIndex))
|
||||
return false;
|
||||
|
||||
if (!d.finishSection(sectionStart, sectionSize))
|
||||
return Fail(d, "data section byte size mismatch");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DecodeCodeSection(Decoder& d, ModuleGenerator& mg)
|
||||
{
|
||||
@ -1424,9 +1391,6 @@ wasm::Compile(Bytes&& bytecode, CompileArgs&& args, UniqueChars* error)
|
||||
if (!DecodeExportSection(d, newFormat, memoryExported, mg))
|
||||
return nullptr;
|
||||
|
||||
if (!DecodeStartSection(d, mg))
|
||||
return nullptr;
|
||||
|
||||
if (!DecodeCodeSection(d, mg))
|
||||
return nullptr;
|
||||
|
||||
|
@ -649,8 +649,6 @@ ModuleGenerator::funcImport(uint32_t funcImportIndex) const
|
||||
bool
|
||||
ModuleGenerator::declareExport(UniqueChars fieldName, uint32_t funcIndex, uint32_t* exportIndex)
|
||||
{
|
||||
MOZ_ASSERT(!exportMap_.hasStartFunction());
|
||||
|
||||
if (!exportMap_.fieldNames.append(Move(fieldName)))
|
||||
return false;
|
||||
|
||||
@ -689,23 +687,6 @@ ModuleGenerator::addMemoryExport(UniqueChars fieldName)
|
||||
exportMap_.fieldsToExports.append(MemoryExport);
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::setStartFunction(uint32_t funcIndex)
|
||||
{
|
||||
FuncIndexMap::AddPtr p = funcIndexToExport_.lookupForAdd(funcIndex);
|
||||
if (p) {
|
||||
exportMap_.setStartFunction(p->value());
|
||||
return true;
|
||||
}
|
||||
|
||||
Sig copy;
|
||||
if (!copy.clone(funcSig(funcIndex)))
|
||||
return false;
|
||||
|
||||
exportMap_.setStartFunction(metadata_->exports.length());
|
||||
return metadata_->exports.emplaceBack(Move(copy), funcIndex);
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::startFuncDefs()
|
||||
{
|
||||
|
@ -184,9 +184,6 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||
MOZ_MUST_USE bool finishFuncDef(uint32_t funcIndex, FunctionGenerator* fg);
|
||||
MOZ_MUST_USE bool finishFuncDefs();
|
||||
|
||||
// Start function:
|
||||
bool setStartFunction(uint32_t funcIndex);
|
||||
|
||||
// Segments:
|
||||
MOZ_MUST_USE bool addDataSegment(DataSegment s) { return dataSegments_.append(s); }
|
||||
MOZ_MUST_USE bool addElemSegment(ElemSegment&& s);
|
||||
|
@ -30,7 +30,7 @@ class WasmInstanceObject;
|
||||
|
||||
namespace wasm {
|
||||
|
||||
class ExportMap;
|
||||
struct ExportMap;
|
||||
|
||||
// Instance represents a wasm instance and provides all the support for runtime
|
||||
// execution of code in the instance. Instances share various immutable data
|
||||
@ -100,9 +100,9 @@ class Instance
|
||||
bool profilingEnabled() const { return profilingEnabled_; }
|
||||
const char* profilingLabel(uint32_t funcIndex) const { return funcLabels_[funcIndex].get(); }
|
||||
|
||||
// If the source binary was saved (by passing the bytecode to the
|
||||
// constructor), this method will render the binary as text. Otherwise, a
|
||||
// diagnostic string will be returned.
|
||||
// If the source binary was saved (by passing the bytecode to 'create'),
|
||||
// this method will render the binary as text. Otherwise, a diagnostic
|
||||
// string will be returned.
|
||||
|
||||
JSString* createText(JSContext* cx);
|
||||
|
||||
|
@ -162,8 +162,7 @@ size_t
|
||||
ExportMap::serializedSize() const
|
||||
{
|
||||
return SerializedVectorSize(fieldNames) +
|
||||
SerializedPodVectorSize(fieldsToExports) +
|
||||
sizeof(uint32_t);
|
||||
SerializedPodVectorSize(fieldsToExports);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
@ -171,7 +170,6 @@ ExportMap::serialize(uint8_t* cursor) const
|
||||
{
|
||||
cursor = SerializeVector(cursor, fieldNames);
|
||||
cursor = SerializePodVector(cursor, fieldsToExports);
|
||||
cursor = WriteScalar(cursor, startExportIndex);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@ -179,8 +177,7 @@ const uint8_t*
|
||||
ExportMap::deserialize(const uint8_t* cursor)
|
||||
{
|
||||
(cursor = DeserializeVector(cursor, &fieldNames)) &&
|
||||
(cursor = DeserializePodVector(cursor, &fieldsToExports)) &&
|
||||
(cursor = ReadScalar(cursor, &startExportIndex));
|
||||
(cursor = DeserializePodVector(cursor, &fieldsToExports));
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@ -567,16 +564,6 @@ Module::instantiate(JSContext* cx,
|
||||
|
||||
Debugger::onNewWasmInstance(cx, instanceObj);
|
||||
|
||||
// Call the start function, if there's one. By specification, it does not
|
||||
// take any arguments nor does it return a value, so just create a dummy
|
||||
// arguments object.
|
||||
|
||||
if (exportMap_.hasStartFunction()) {
|
||||
FixedInvokeArgs<0> args(cx);
|
||||
if (!instanceObj->instance().callExport(cx, exportMap_.startFunctionExportIndex(), args))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -111,38 +111,16 @@ typedef Vector<Import, 0, SystemAllocPolicy> ImportVector;
|
||||
// - the sentinel value MemoryExport indicating an export of linear memory; or
|
||||
// - the index of an export into the ExportVector in Metadata
|
||||
//
|
||||
// ExportMap also contains the start function's export index, which maps to the
|
||||
// export that is called at each instantiation of a given module.
|
||||
//
|
||||
// ExportMap is built incrementally by ModuleGenerator and then stored immutably
|
||||
// by Module.
|
||||
|
||||
static const uint32_t MemoryExport = UINT32_MAX;
|
||||
|
||||
static const uint32_t NO_START_FUNCTION = UINT32_MAX;
|
||||
|
||||
class ExportMap
|
||||
struct ExportMap
|
||||
{
|
||||
uint32_t startExportIndex;
|
||||
|
||||
public:
|
||||
CacheableCharsVector fieldNames;
|
||||
Uint32Vector fieldsToExports;
|
||||
|
||||
ExportMap() : startExportIndex(NO_START_FUNCTION) {}
|
||||
|
||||
bool hasStartFunction() const {
|
||||
return startExportIndex != NO_START_FUNCTION;
|
||||
}
|
||||
void setStartFunction(uint32_t index) {
|
||||
MOZ_ASSERT(!hasStartFunction());
|
||||
startExportIndex = index;
|
||||
}
|
||||
uint32_t startFunctionExportIndex() const {
|
||||
MOZ_ASSERT(hasStartFunction());
|
||||
return startExportIndex;
|
||||
}
|
||||
|
||||
WASM_DECLARE_SERIALIZABLE(ExportMap)
|
||||
};
|
||||
|
||||
|
@ -90,6 +90,8 @@ class WasmToken
|
||||
If,
|
||||
Import,
|
||||
Index,
|
||||
UnsignedInteger,
|
||||
SignedInteger,
|
||||
Memory,
|
||||
NegativeZero,
|
||||
Load,
|
||||
@ -106,8 +108,6 @@ class WasmToken
|
||||
Return,
|
||||
Segment,
|
||||
SetLocal,
|
||||
SignedInteger,
|
||||
Start,
|
||||
Store,
|
||||
Table,
|
||||
TernaryOpcode,
|
||||
@ -116,7 +116,6 @@ class WasmToken
|
||||
Type,
|
||||
UnaryOpcode,
|
||||
Unreachable,
|
||||
UnsignedInteger,
|
||||
ValueType
|
||||
};
|
||||
private:
|
||||
@ -1321,8 +1320,6 @@ WasmTokenStream::next()
|
||||
return WasmToken(WasmToken::SetLocal, begin, cur_);
|
||||
if (consume(MOZ_UTF16("segment")))
|
||||
return WasmToken(WasmToken::Segment, begin, cur_);
|
||||
if (consume(MOZ_UTF16("start")))
|
||||
return WasmToken(WasmToken::Start, begin, cur_);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
@ -2408,21 +2405,6 @@ ParseMemory(WasmParseContext& c, WasmToken token, AstModule* module)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseStartFunc(WasmParseContext& c, WasmToken token, AstModule* module)
|
||||
{
|
||||
AstRef func;
|
||||
if (!c.ts.matchRef(&func, c.error))
|
||||
return false;
|
||||
|
||||
if (!module->setStartFunc(AstStartFunc(func))) {
|
||||
c.ts.generateError(token, c.error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static AstImport*
|
||||
ParseImport(WasmParseContext& c, bool newFormat, AstModule* module)
|
||||
{
|
||||
@ -2573,11 +2555,6 @@ ParseModule(const char16_t* text, bool newFormat, LifoAlloc& lifo, UniqueChars*
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
case WasmToken::Start: {
|
||||
if (!ParseStartFunc(c, section, module))
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
case WasmToken::Memory: {
|
||||
if (!ParseMemory(c, section, module))
|
||||
return nullptr;
|
||||
@ -3091,11 +3068,6 @@ ResolveModule(LifoAlloc& lifo, AstModule* module, UniqueChars* error)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (module->hasStartFunc()) {
|
||||
if (!r.resolveFunction(module->startFunc().func()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3750,23 +3722,6 @@ EncodeFunctionBody(Encoder& e, AstFunc& func)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeStartSection(Encoder& e, AstModule& module)
|
||||
{
|
||||
if (!module.hasStartFunc())
|
||||
return true;
|
||||
|
||||
size_t offset;
|
||||
if (!e.startSection(StartSectionId, &offset))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(module.startFunc().func().index()))
|
||||
return false;
|
||||
|
||||
e.finishSection(offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeCodeSection(Encoder& e, AstModule& module)
|
||||
{
|
||||
@ -3918,9 +3873,6 @@ EncodeModule(AstModule& module, bool newFormat, Bytes* bytes)
|
||||
if (!EncodeExportSection(e, newFormat, module))
|
||||
return false;
|
||||
|
||||
if (!EncodeStartSection(e, module))
|
||||
return false;
|
||||
|
||||
if (!EncodeCodeSection(e, module))
|
||||
return false;
|
||||
|
||||
|
@ -262,7 +262,7 @@ var tooBigNameSection = {
|
||||
wasmEval(moduleWithSections([tooBigNameSection]));
|
||||
|
||||
// Checking stack trace.
|
||||
function runStackTraceTest(namesContent, expectedName) {
|
||||
function runStartTraceTest(namesContent, expectedName) {
|
||||
var sections = [
|
||||
sigSection([v2vSig]),
|
||||
importSection([{sigIndex:0, module:"env", func:"callback"}]),
|
||||
@ -281,15 +281,15 @@ function runStackTraceTest(namesContent, expectedName) {
|
||||
assertEq(result, expectedName);
|
||||
};
|
||||
|
||||
runStackTraceTest(null, 'wasm-function[0]');
|
||||
runStackTraceTest([{name: 'test'}], 'test');
|
||||
runStackTraceTest([{name: 'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
|
||||
runStackTraceTest([{name: 'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
|
||||
runStackTraceTest([{name: 'test1'}, {name: 'test2'}], 'test1');
|
||||
runStackTraceTest([{name: 'test☃'}], 'test☃');
|
||||
runStackTraceTest([{name: 'te\xE0\xFF'}], 'te\xE0\xFF');
|
||||
runStackTraceTest([], 'wasm-function[0]');
|
||||
runStartTraceTest(null, 'wasm-function[0]');
|
||||
runStartTraceTest([{name: 'test'}], 'test');
|
||||
runStartTraceTest([{name: 'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
|
||||
runStartTraceTest([{name: 'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
|
||||
runStartTraceTest([{name: 'test1'}, {name: 'test2'}], 'test1');
|
||||
runStartTraceTest([{name: 'test☃'}], 'test☃');
|
||||
runStartTraceTest([{name: 'te\xE0\xFF'}], 'te\xE0\xFF');
|
||||
runStartTraceTest([], 'wasm-function[0]');
|
||||
// Notice that invalid names section content shall not fail the parsing
|
||||
runStackTraceTest([{nameLen: 100, name: 'test'}], 'wasm-function[0]'); // invalid name size
|
||||
runStackTraceTest([{name: 'test', locals: [{nameLen: 40, name: 'var1'}]}], 'wasm-function[0]'); // invalid variable name size
|
||||
runStackTraceTest([{name: ''}], 'wasm-function[0]'); // empty name
|
||||
runStartTraceTest([{nameLen: 100, name: 'test'}], 'wasm-function[0]'); // invalid name size
|
||||
runStartTraceTest([{name: 'test', locals: [{nameLen: 40, name: 'var1'}]}], 'wasm-function[0]'); // invalid variable name size
|
||||
runStartTraceTest([{name: ''}], 'wasm-function[0]'); // empty name
|
||||
|
@ -1,2 +1,4 @@
|
||||
// |jit-test| test-also-wasm-baseline
|
||||
// TODO start opcode
|
||||
quit();
|
||||
var importedArgs = ['start.wast']; load(scriptdir + '../spec.js');
|
||||
|
@ -1,46 +0,0 @@
|
||||
// |jit-test| test-also-wasm-baseline
|
||||
load(libdir + "wasm.js");
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (func) (start 0) (start 0))'), SyntaxError, /wasm text error/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (func) (start 1))'), TypeError, /unknown start function/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (func) (start $unknown))'), SyntaxError, /label.*not found/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (param i32)) (start 0))'), TypeError, /must be nullary/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (param i32) (param f32)) (start 0))'), TypeError, /must be nullary/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (param i32) (param f32) (param f64)) (start 0))'), TypeError, /must be nullary/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (result f32)) (start 0))'), TypeError, /must not return anything/);
|
||||
|
||||
// Basic use case.
|
||||
var count = 0;
|
||||
function inc() { count++; }
|
||||
var exports = wasmEvalText(`(module (import "inc" "") (func (param i32)) (func (call_import 0)) (start 1))`, { inc });
|
||||
assertEq(count, 1);
|
||||
assertEq(Object.keys(exports).length, 0);
|
||||
|
||||
count = 0;
|
||||
exports = wasmEvalText(`(module (import "inc" "") (func $start (call_import 0)) (start $start) (export "" 0))`, { inc });
|
||||
assertEq(count, 1);
|
||||
assertEq(typeof exports, 'function');
|
||||
assertEq(exports(), undefined);
|
||||
assertEq(count, 2);
|
||||
|
||||
// New API.
|
||||
const Module = WebAssembly.Module;
|
||||
const Instance = WebAssembly.Instance;
|
||||
const textToBinary = str => wasmTextToBinary(str, 'new-format');
|
||||
|
||||
count = 0;
|
||||
const m = new Module(textToBinary('(module (import "inc" "") (func) (func (call_import 0)) (start 1) (export "" 1))'));
|
||||
assertEq(count, 0);
|
||||
|
||||
assertErrorMessage(() => new Instance(m), TypeError, /no import object given/);
|
||||
assertEq(count, 0);
|
||||
|
||||
const i1 = new Instance(m, { inc });
|
||||
assertEq(count, 1);
|
||||
i1.exports[""]();
|
||||
assertEq(count, 2);
|
||||
|
||||
const i2 = new Instance(m, { inc });
|
||||
assertEq(count, 3);
|
Loading…
Reference in New Issue
Block a user