Bug 1472178 - Ref types for wasm globals. r=bbouvier

--HG--
extra : rebase_source : 2f64e3b52649574e350f4b45bad9547fb3e73975
This commit is contained in:
Lars T Hansen 2018-07-24 18:26:45 +02:00
Родитель aa46adb8f5
Коммит 6ae83a4406
5 изменённых файлов: 87 добавлений и 16 удалений

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

@ -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");