зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1472178 - Ref types for wasm globals. r=bbouvier
--HG-- extra : rebase_source : 2f64e3b52649574e350f4b45bad9547fb3e73975
This commit is contained in:
Родитель
aa46adb8f5
Коммит
6ae83a4406
|
@ -0,0 +1,61 @@
|
|||
if (!wasmGcEnabled())
|
||||
quit(0);
|
||||
|
||||
// Basic private-to-module functionality. At the moment all we have is null
|
||||
// pointers, not very exciting.
|
||||
|
||||
{
|
||||
let bin = wasmTextToBinary(
|
||||
`(module
|
||||
|
||||
(type $point (struct
|
||||
(field $x f64)
|
||||
(field $y f64)))
|
||||
|
||||
(global $g1 (mut (ref $point)) (ref.null (ref $point)))
|
||||
(global $g2 (mut (ref $point)) (ref.null (ref $point)))
|
||||
(global $g3 (ref $point) (ref.null (ref $point)))
|
||||
|
||||
(func (export "get") (result (ref $point))
|
||||
(get_global $g1))
|
||||
|
||||
(func (export "copy")
|
||||
(set_global $g2 (get_global $g1)))
|
||||
|
||||
(func (export "clear")
|
||||
(set_global $g1 (get_global $g3))
|
||||
(set_global $g2 (ref.null (ref $point)))))`);
|
||||
|
||||
let mod = new WebAssembly.Module(bin);
|
||||
let ins = new WebAssembly.Instance(mod).exports;
|
||||
|
||||
assertEq(ins.get(), null);
|
||||
ins.copy(); // Should not crash
|
||||
ins.clear(); // Should not crash
|
||||
}
|
||||
|
||||
// We can't import a global of a reference type because we don't have a good
|
||||
// notion of structural type compatibility yet.
|
||||
{
|
||||
let bin = wasmTextToBinary(
|
||||
`(module
|
||||
(type $box (struct (field $val i32)))
|
||||
(import "m" "g" (global (mut (ref $box)))))`);
|
||||
|
||||
assertErrorMessage(() => new WebAssembly.Module(bin), WebAssembly.CompileError,
|
||||
/unexpected variable type in global import\/export/);
|
||||
}
|
||||
|
||||
// We can't export a global of a reference type because we can't later import
|
||||
// it. (Once we can export it, the value setter must also perform the necessary
|
||||
// subtype check, which implies we have some notion of exporting types, and we
|
||||
// don't have that yet.)
|
||||
{
|
||||
let bin = wasmTextToBinary(
|
||||
`(module
|
||||
(type $box (struct (field $val i32)))
|
||||
(global $boxg (export "box") (mut (ref $box)) (ref.null (ref $box))))`);
|
||||
|
||||
assertErrorMessage(() => new WebAssembly.Module(bin), WebAssembly.CompileError,
|
||||
/unexpected variable type in global import\/export/);
|
||||
}
|
|
@ -20,12 +20,6 @@ var bin = wasmTextToBinary(
|
|||
(field $x i32)
|
||||
(field $to_odd (ref $odd))))
|
||||
|
||||
;; No globals of reference type yet.
|
||||
;;
|
||||
;;(import "m" "g" (global (ref $cons)))
|
||||
;;
|
||||
;;(global $glob (ref $cons) (ref.null $cons))
|
||||
|
||||
(import "m" "f" (func $imp (param (ref $cons)) (result (ref $odd))))
|
||||
|
||||
;; The bodies do nothing since we have no operations on structs yet.
|
||||
|
|
|
@ -8359,6 +8359,7 @@ BaseCompiler::emitGetGlobal()
|
|||
case ValType::F64:
|
||||
pushF64(value.f64());
|
||||
break;
|
||||
case ValType::Ref:
|
||||
case ValType::AnyRef:
|
||||
pushRef(intptr_t(value.ptr()));
|
||||
break;
|
||||
|
@ -8397,6 +8398,7 @@ BaseCompiler::emitGetGlobal()
|
|||
pushF64(rv);
|
||||
break;
|
||||
}
|
||||
case ValType::Ref:
|
||||
case ValType::AnyRef: {
|
||||
RegPtr rv = needRef();
|
||||
ScratchI32 tmp(*this);
|
||||
|
@ -8454,6 +8456,7 @@ BaseCompiler::emitSetGlobal()
|
|||
break;
|
||||
}
|
||||
#ifdef ENABLE_WASM_GC
|
||||
case ValType::Ref:
|
||||
case ValType::AnyRef: {
|
||||
RegPtr valueAddr(PreBarrierReg);
|
||||
needRef(valueAddr);
|
||||
|
|
|
@ -68,8 +68,8 @@ Val::Val(const LitVal& val)
|
|||
case ValType::F32: u.f32_ = val.f32(); return;
|
||||
case ValType::I64: u.i64_ = val.i64(); return;
|
||||
case ValType::F64: u.f64_ = val.f64(); return;
|
||||
case ValType::Ref:
|
||||
case ValType::AnyRef: u.ptr_ = val.ptr(); return;
|
||||
case ValType::Ref: break;
|
||||
}
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
|
|
@ -1644,7 +1644,7 @@ DecodeMemorySection(Decoder& d, ModuleEnvironment* env)
|
|||
|
||||
static bool
|
||||
DecodeInitializerExpression(Decoder& d, HasGcTypes gcTypesEnabled, const GlobalDescVector& globals,
|
||||
ValType expected, InitExpr* init)
|
||||
ValType expected, uint32_t numTypes, InitExpr* init)
|
||||
{
|
||||
OpBytes op;
|
||||
if (!d.readOp(&op))
|
||||
|
@ -1683,12 +1683,18 @@ DecodeInitializerExpression(Decoder& d, HasGcTypes gcTypesEnabled, const GlobalD
|
|||
if (gcTypesEnabled == HasGcTypes::False)
|
||||
return d.fail("unexpected initializer expression");
|
||||
uint8_t valType;
|
||||
uint32_t unusedRefTypeIndex;
|
||||
if (!d.readValType(&valType, &unusedRefTypeIndex))
|
||||
uint32_t refTypeIndex;
|
||||
if (!d.readValType(&valType, &refTypeIndex))
|
||||
return false;
|
||||
if (valType != uint8_t(ValType::AnyRef))
|
||||
return d.fail("expected anyref as type for ref.null");
|
||||
*init = InitExpr(LitVal(ValType::AnyRef, nullptr));
|
||||
if (valType == uint8_t(ValType::AnyRef)) {
|
||||
*init = InitExpr(LitVal(ValType::AnyRef, nullptr));
|
||||
} else if (valType == uint8_t(ValType::Ref)) {
|
||||
if (refTypeIndex >= numTypes)
|
||||
return d.fail("invalid reference type for ref.null");
|
||||
*init = InitExpr(LitVal(ValType(ValType::Ref, refTypeIndex), nullptr));
|
||||
} else {
|
||||
return d.fail("expected anyref/ref as type for ref.null");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case uint16_t(Op::GetGlobal): {
|
||||
|
@ -1745,8 +1751,11 @@ DecodeGlobalSection(Decoder& d, ModuleEnvironment* env)
|
|||
return false;
|
||||
|
||||
InitExpr initializer;
|
||||
if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, type, &initializer))
|
||||
if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, type,
|
||||
env->types.length(), &initializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
env->globals.infallibleAppend(GlobalDesc(initializer, isMutable));
|
||||
}
|
||||
|
@ -1927,8 +1936,10 @@ DecodeElemSection(Decoder& d, ModuleEnvironment* env)
|
|||
|
||||
InitExpr offset;
|
||||
if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, ValType::I32,
|
||||
&offset))
|
||||
env->types.length(), &offset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t numElems;
|
||||
if (!d.readVarU32(&numElems))
|
||||
|
@ -2098,8 +2109,10 @@ DecodeDataSection(Decoder& d, ModuleEnvironment* env)
|
|||
|
||||
DataSegment seg;
|
||||
if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, ValType::I32,
|
||||
&seg.offset))
|
||||
env->types.length(), &seg.offset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!d.readVarU32(&seg.length))
|
||||
return d.fail("expected segment size");
|
||||
|
|
Загрузка…
Ссылка в новой задаче