зеркало из 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 $x i32)
|
||||||
(field $to_odd (ref $odd))))
|
(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))))
|
(import "m" "f" (func $imp (param (ref $cons)) (result (ref $odd))))
|
||||||
|
|
||||||
;; The bodies do nothing since we have no operations on structs yet.
|
;; The bodies do nothing since we have no operations on structs yet.
|
||||||
|
|
|
@ -8359,6 +8359,7 @@ BaseCompiler::emitGetGlobal()
|
||||||
case ValType::F64:
|
case ValType::F64:
|
||||||
pushF64(value.f64());
|
pushF64(value.f64());
|
||||||
break;
|
break;
|
||||||
|
case ValType::Ref:
|
||||||
case ValType::AnyRef:
|
case ValType::AnyRef:
|
||||||
pushRef(intptr_t(value.ptr()));
|
pushRef(intptr_t(value.ptr()));
|
||||||
break;
|
break;
|
||||||
|
@ -8397,6 +8398,7 @@ BaseCompiler::emitGetGlobal()
|
||||||
pushF64(rv);
|
pushF64(rv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ValType::Ref:
|
||||||
case ValType::AnyRef: {
|
case ValType::AnyRef: {
|
||||||
RegPtr rv = needRef();
|
RegPtr rv = needRef();
|
||||||
ScratchI32 tmp(*this);
|
ScratchI32 tmp(*this);
|
||||||
|
@ -8454,6 +8456,7 @@ BaseCompiler::emitSetGlobal()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_GC
|
||||||
|
case ValType::Ref:
|
||||||
case ValType::AnyRef: {
|
case ValType::AnyRef: {
|
||||||
RegPtr valueAddr(PreBarrierReg);
|
RegPtr valueAddr(PreBarrierReg);
|
||||||
needRef(valueAddr);
|
needRef(valueAddr);
|
||||||
|
|
|
@ -68,8 +68,8 @@ Val::Val(const LitVal& val)
|
||||||
case ValType::F32: u.f32_ = val.f32(); return;
|
case ValType::F32: u.f32_ = val.f32(); return;
|
||||||
case ValType::I64: u.i64_ = val.i64(); return;
|
case ValType::I64: u.i64_ = val.i64(); return;
|
||||||
case ValType::F64: u.f64_ = val.f64(); return;
|
case ValType::F64: u.f64_ = val.f64(); return;
|
||||||
|
case ValType::Ref:
|
||||||
case ValType::AnyRef: u.ptr_ = val.ptr(); return;
|
case ValType::AnyRef: u.ptr_ = val.ptr(); return;
|
||||||
case ValType::Ref: break;
|
|
||||||
}
|
}
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1644,7 +1644,7 @@ DecodeMemorySection(Decoder& d, ModuleEnvironment* env)
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
DecodeInitializerExpression(Decoder& d, HasGcTypes gcTypesEnabled, const GlobalDescVector& globals,
|
DecodeInitializerExpression(Decoder& d, HasGcTypes gcTypesEnabled, const GlobalDescVector& globals,
|
||||||
ValType expected, InitExpr* init)
|
ValType expected, uint32_t numTypes, InitExpr* init)
|
||||||
{
|
{
|
||||||
OpBytes op;
|
OpBytes op;
|
||||||
if (!d.readOp(&op))
|
if (!d.readOp(&op))
|
||||||
|
@ -1683,12 +1683,18 @@ DecodeInitializerExpression(Decoder& d, HasGcTypes gcTypesEnabled, const GlobalD
|
||||||
if (gcTypesEnabled == HasGcTypes::False)
|
if (gcTypesEnabled == HasGcTypes::False)
|
||||||
return d.fail("unexpected initializer expression");
|
return d.fail("unexpected initializer expression");
|
||||||
uint8_t valType;
|
uint8_t valType;
|
||||||
uint32_t unusedRefTypeIndex;
|
uint32_t refTypeIndex;
|
||||||
if (!d.readValType(&valType, &unusedRefTypeIndex))
|
if (!d.readValType(&valType, &refTypeIndex))
|
||||||
return false;
|
return false;
|
||||||
if (valType != uint8_t(ValType::AnyRef))
|
if (valType == uint8_t(ValType::AnyRef)) {
|
||||||
return d.fail("expected anyref as type for ref.null");
|
*init = InitExpr(LitVal(ValType::AnyRef, nullptr));
|
||||||
*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;
|
break;
|
||||||
}
|
}
|
||||||
case uint16_t(Op::GetGlobal): {
|
case uint16_t(Op::GetGlobal): {
|
||||||
|
@ -1745,8 +1751,11 @@ DecodeGlobalSection(Decoder& d, ModuleEnvironment* env)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
InitExpr initializer;
|
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;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
env->globals.infallibleAppend(GlobalDesc(initializer, isMutable));
|
env->globals.infallibleAppend(GlobalDesc(initializer, isMutable));
|
||||||
}
|
}
|
||||||
|
@ -1927,8 +1936,10 @@ DecodeElemSection(Decoder& d, ModuleEnvironment* env)
|
||||||
|
|
||||||
InitExpr offset;
|
InitExpr offset;
|
||||||
if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, ValType::I32,
|
if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, ValType::I32,
|
||||||
&offset))
|
env->types.length(), &offset))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t numElems;
|
uint32_t numElems;
|
||||||
if (!d.readVarU32(&numElems))
|
if (!d.readVarU32(&numElems))
|
||||||
|
@ -2098,8 +2109,10 @@ DecodeDataSection(Decoder& d, ModuleEnvironment* env)
|
||||||
|
|
||||||
DataSegment seg;
|
DataSegment seg;
|
||||||
if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, ValType::I32,
|
if (!DecodeInitializerExpression(d, env->gcTypesEnabled, env->globals, ValType::I32,
|
||||||
&seg.offset))
|
env->types.length(), &seg.offset))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!d.readVarU32(&seg.length))
|
if (!d.readVarU32(&seg.length))
|
||||||
return d.fail("expected segment size");
|
return d.fail("expected segment size");
|
||||||
|
|
Загрузка…
Ссылка в новой задаче