mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
Bug 1445272: Add (entry/exit) stubs support for anyref; r=luke
--HG-- extra : rebase_source : 1d4e3f43414a718d739efbe4907c1a1c85f261f8
This commit is contained in:
parent
8d30a725fa
commit
a45951f2cd
@ -95,6 +95,7 @@ class JSFunction : public js::NativeObject
|
||||
NATIVE_CLASS_CTOR = NATIVE_FUN | CONSTRUCTOR | CLASSCONSTRUCTOR_KIND,
|
||||
ASMJS_CTOR = ASMJS_KIND | NATIVE_CTOR,
|
||||
ASMJS_LAMBDA_CTOR = ASMJS_KIND | NATIVE_CTOR | LAMBDA,
|
||||
ASMJS_NATIVE = ASMJS_KIND | NATIVE_FUN,
|
||||
WASM_FUN = NATIVE_FUN | WASM_OPTIMIZED,
|
||||
INTERPRETED_METHOD = INTERPRETED | METHOD_KIND,
|
||||
INTERPRETED_METHOD_GENERATOR_OR_ASYNC = INTERPRETED | METHOD_KIND,
|
||||
|
@ -536,6 +536,9 @@ AddressOf(SymbolicAddress imm, ABIFunctionType* abiType)
|
||||
case SymbolicAddress::CallImport_F64:
|
||||
*abiType = Args_General4;
|
||||
return FuncCast(Instance::callImport_f64, *abiType);
|
||||
case SymbolicAddress::CallImport_Ref:
|
||||
*abiType = Args_General4;
|
||||
return FuncCast(Instance::callImport_ref, *abiType);
|
||||
case SymbolicAddress::CoerceInPlace_ToInt32:
|
||||
*abiType = Args_General1;
|
||||
return FuncCast(CoerceInPlace_ToInt32, *abiType);
|
||||
@ -690,6 +693,7 @@ wasm::NeedsBuiltinThunk(SymbolicAddress sym)
|
||||
case SymbolicAddress::CallImport_I32:
|
||||
case SymbolicAddress::CallImport_I64:
|
||||
case SymbolicAddress::CallImport_F64:
|
||||
case SymbolicAddress::CallImport_Ref:
|
||||
case SymbolicAddress::CoerceInPlace_ToInt32: // GenerateImportJitExit
|
||||
case SymbolicAddress::CoerceInPlace_ToNumber:
|
||||
#if defined(JS_CODEGEN_MIPS32)
|
||||
|
@ -609,22 +609,25 @@ LazyStubSegment::addStubs(size_t codeLength, const Uint32Vector& funcExportIndic
|
||||
return false;
|
||||
|
||||
size_t i = 0;
|
||||
for (DebugOnly<uint32_t> funcExportIndex : funcExportIndices) {
|
||||
for (uint32_t funcExportIndex : funcExportIndices) {
|
||||
const CodeRange& interpRange = codeRanges[i];
|
||||
MOZ_ASSERT(interpRange.isInterpEntry());
|
||||
MOZ_ASSERT(interpRange.funcIndex() == funcExports[funcExportIndex].funcIndex());
|
||||
|
||||
codeRanges_.infallibleAppend(interpRange);
|
||||
codeRanges_.back().offsetBy(offsetInSegment);
|
||||
i++;
|
||||
|
||||
const CodeRange& jitRange = codeRanges[i + 1];
|
||||
if (funcExports[funcExportIndex].sig().temporarilyUnsupportedAnyRef())
|
||||
continue;
|
||||
|
||||
const CodeRange& jitRange = codeRanges[i];
|
||||
MOZ_ASSERT(jitRange.isJitEntry());
|
||||
MOZ_ASSERT(jitRange.funcIndex() == interpRange.funcIndex());
|
||||
|
||||
codeRanges_.infallibleAppend(jitRange);
|
||||
codeRanges_.back().offsetBy(offsetInSegment);
|
||||
|
||||
i += 2;
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -673,8 +676,10 @@ LazyStubTier::createMany(const Uint32Vector& funcExportIndices, const CodeTier&
|
||||
uint8_t* moduleSegmentBase = codeTier.segment().base();
|
||||
|
||||
CodeRangeVector codeRanges;
|
||||
DebugOnly<uint32_t> numExpectedRanges = 0;
|
||||
for (uint32_t funcExportIndex : funcExportIndices) {
|
||||
const FuncExport& fe = funcExports[funcExportIndex];
|
||||
numExpectedRanges += fe.sig().temporarilyUnsupportedAnyRef() ? 1 : 2;
|
||||
void* calleePtr = moduleSegmentBase +
|
||||
moduleRanges[fe.interpCodeRangeIndex()].funcNormalEntry();
|
||||
Maybe<ImmPtr> callee;
|
||||
@ -682,7 +687,7 @@ LazyStubTier::createMany(const Uint32Vector& funcExportIndices, const CodeTier&
|
||||
if (!GenerateEntryStubs(masm, funcExportIndex, fe, callee, /* asmjs*/ false, &codeRanges))
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(codeRanges.length() == 2 * funcExportIndices.length(), "two entries per function");
|
||||
MOZ_ASSERT(codeRanges.length() == numExpectedRanges, "incorrect number of entries per function");
|
||||
|
||||
masm.finish();
|
||||
|
||||
@ -743,7 +748,9 @@ LazyStubTier::createMany(const Uint32Vector& funcExportIndices, const CodeTier&
|
||||
fe.funcIndex(), &exportIndex));
|
||||
MOZ_ALWAYS_TRUE(exports_.insert(exports_.begin() + exportIndex, Move(lazyExport)));
|
||||
|
||||
interpRangeIndex += 2;
|
||||
// Functions with anyref in their sig have only one entry (interp).
|
||||
// All other functions get an extra jit entry.
|
||||
interpRangeIndex += fe.sig().temporarilyUnsupportedAnyRef() ? 1 : 2;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -763,6 +770,13 @@ LazyStubTier::createOne(uint32_t funcExportIndex, const CodeTier& codeTier)
|
||||
const UniqueLazyStubSegment& segment = stubSegments_[stubSegmentIndex];
|
||||
const CodeRangeVector& codeRanges = segment->codeRanges();
|
||||
|
||||
// Functions that have anyref in their sig don't get a jit entry.
|
||||
if (codeTier.metadata().funcExports[funcExportIndex].sig().temporarilyUnsupportedAnyRef()) {
|
||||
MOZ_ASSERT(codeRanges.length() >= 1);
|
||||
MOZ_ASSERT(codeRanges.back().isInterpEntry());
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(codeRanges.length() >= 2);
|
||||
MOZ_ASSERT(codeRanges[codeRanges.length() - 2].isInterpEntry());
|
||||
|
||||
|
@ -1139,6 +1139,7 @@ ThunkedNativeToDescription(SymbolicAddress func)
|
||||
case SymbolicAddress::CallImport_I32:
|
||||
case SymbolicAddress::CallImport_I64:
|
||||
case SymbolicAddress::CallImport_F64:
|
||||
case SymbolicAddress::CallImport_Ref:
|
||||
case SymbolicAddress::CoerceInPlace_ToInt32:
|
||||
case SymbolicAddress::CoerceInPlace_ToNumber:
|
||||
MOZ_ASSERT(!NeedsBuiltinThunk(func), "not in sync with NeedsBuiltinThunk");
|
||||
|
@ -133,6 +133,10 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con
|
||||
case ValType::F64:
|
||||
args[i].set(JS::CanonicalizedDoubleValue(*(double*)&argv[i]));
|
||||
break;
|
||||
case ValType::AnyRef: {
|
||||
args[i].set(ObjectOrNullValue(*(JSObject**)&argv[i]));
|
||||
break;
|
||||
}
|
||||
case ValType::I64:
|
||||
case ValType::I8x16:
|
||||
case ValType::I16x8:
|
||||
@ -188,23 +192,28 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con
|
||||
if (!TypeScript::ThisTypes(script)->hasType(TypeSet::UndefinedType()))
|
||||
return true;
|
||||
|
||||
// Functions with anyref in signature don't have a jit exit at the moment.
|
||||
if (fi.sig().temporarilyUnsupportedAnyRef())
|
||||
return true;
|
||||
|
||||
const ValTypeVector& importArgs = fi.sig().args();
|
||||
|
||||
size_t numKnownArgs = Min(importArgs.length(), importFun->nargs());
|
||||
for (uint32_t i = 0; i < numKnownArgs; i++) {
|
||||
TypeSet::Type type = TypeSet::UnknownType();
|
||||
switch (importArgs[i]) {
|
||||
case ValType::I32: type = TypeSet::Int32Type(); break;
|
||||
case ValType::F32: type = TypeSet::DoubleType(); break;
|
||||
case ValType::F64: type = TypeSet::DoubleType(); break;
|
||||
case ValType::I64: MOZ_CRASH("NYI");
|
||||
case ValType::I8x16: MOZ_CRASH("NYI");
|
||||
case ValType::I16x8: MOZ_CRASH("NYI");
|
||||
case ValType::I32x4: MOZ_CRASH("NYI");
|
||||
case ValType::F32x4: MOZ_CRASH("NYI");
|
||||
case ValType::B8x16: MOZ_CRASH("NYI");
|
||||
case ValType::B16x8: MOZ_CRASH("NYI");
|
||||
case ValType::B32x4: MOZ_CRASH("NYI");
|
||||
case ValType::I32: type = TypeSet::Int32Type(); break;
|
||||
case ValType::F32: type = TypeSet::DoubleType(); break;
|
||||
case ValType::F64: type = TypeSet::DoubleType(); break;
|
||||
case ValType::AnyRef: MOZ_CRASH("case guarded above");
|
||||
case ValType::I64: MOZ_CRASH("NYI");
|
||||
case ValType::I8x16: MOZ_CRASH("NYI");
|
||||
case ValType::I16x8: MOZ_CRASH("NYI");
|
||||
case ValType::I32x4: MOZ_CRASH("NYI");
|
||||
case ValType::F32x4: MOZ_CRASH("NYI");
|
||||
case ValType::B8x16: MOZ_CRASH("NYI");
|
||||
case ValType::B16x8: MOZ_CRASH("NYI");
|
||||
case ValType::B32x4: MOZ_CRASH("NYI");
|
||||
}
|
||||
if (!TypeScript::ArgTypes(script, i)->hasType(type))
|
||||
return true;
|
||||
@ -265,6 +274,31 @@ Instance::callImport_f64(Instance* instance, int32_t funcImportIndex, int32_t ar
|
||||
return ToNumber(cx, rval, (double*)argv);
|
||||
}
|
||||
|
||||
static bool
|
||||
ToRef(JSContext* cx, HandleValue val, void* addr)
|
||||
{
|
||||
if (val.isNull()) {
|
||||
*(JSObject**)addr = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject* obj = ToObject(cx, val);
|
||||
if (!obj)
|
||||
return false;
|
||||
*(JSObject**)addr = obj;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ int32_t
|
||||
Instance::callImport_ref(Instance* instance, int32_t funcImportIndex, int32_t argc, uint64_t* argv)
|
||||
{
|
||||
JSContext* cx = TlsContext.get();
|
||||
RootedValue rval(cx);
|
||||
if (!instance->callImport(cx, funcImportIndex, argc, argv, &rval))
|
||||
return false;
|
||||
return ToRef(cx, rval, argv);
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
Instance::growMemory_i32(Instance* instance, uint32_t delta)
|
||||
{
|
||||
@ -672,6 +706,11 @@ Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args)
|
||||
if (!ToNumber(cx, v, (double*)&exportArgs[i]))
|
||||
return false;
|
||||
break;
|
||||
case ValType::AnyRef: {
|
||||
if (!ToRef(cx, v, &exportArgs[i]))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ValType::I8x16: {
|
||||
SimdConstant simd;
|
||||
if (!ToSimdConstant<Int8x16>(cx, v, &simd))
|
||||
@ -755,6 +794,8 @@ Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args)
|
||||
}
|
||||
|
||||
void* retAddr = &exportArgs[0];
|
||||
|
||||
bool expectsObject = false;
|
||||
JSObject* retObj = nullptr;
|
||||
switch (func.sig().ret()) {
|
||||
case ExprType::Void:
|
||||
@ -771,6 +812,10 @@ Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args)
|
||||
case ExprType::F64:
|
||||
args.rval().set(NumberValue(*(double*)retAddr));
|
||||
break;
|
||||
case ExprType::AnyRef:
|
||||
retObj = *(JSObject**)retAddr;
|
||||
expectsObject = true;
|
||||
break;
|
||||
case ExprType::I8x16:
|
||||
retObj = CreateSimd<Int8x16>(cx, (int8_t*)retAddr);
|
||||
if (!retObj)
|
||||
@ -810,7 +855,9 @@ Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args)
|
||||
MOZ_CRASH("Limit");
|
||||
}
|
||||
|
||||
if (retObj)
|
||||
if (expectsObject)
|
||||
args.rval().set(ObjectOrNullValue(retObj));
|
||||
else if (retObj)
|
||||
args.rval().set(ObjectValue(*retObj));
|
||||
|
||||
return true;
|
||||
|
@ -164,6 +164,7 @@ class Instance
|
||||
static int32_t callImport_i32(Instance*, int32_t, int32_t, uint64_t*);
|
||||
static int32_t callImport_i64(Instance*, int32_t, int32_t, uint64_t*);
|
||||
static int32_t callImport_f64(Instance*, int32_t, int32_t, uint64_t*);
|
||||
static int32_t callImport_ref(Instance*, int32_t, int32_t, uint64_t*);
|
||||
static uint32_t growMemory_i32(Instance* instance, uint32_t delta);
|
||||
static uint32_t currentMemory_i32(Instance* instance);
|
||||
static int32_t wait_i32(Instance* instance, uint32_t byteOffset, int32_t value, int64_t timeout);
|
||||
|
@ -1291,11 +1291,23 @@ WasmInstanceObject::getExportedFunction(JSContext* cx, HandleWasmInstanceObject
|
||||
RootedAtom name(cx, NumberToAtom(cx, funcIndex));
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
// Functions with anyref don't have jit entries yet, so they should
|
||||
// mostly behave like asm.js functions. Pretend it's the case, until
|
||||
// jit entries are implemented.
|
||||
JSFunction::Flags flags = sig.temporarilyUnsupportedAnyRef()
|
||||
? JSFunction::ASMJS_NATIVE
|
||||
: JSFunction::WASM_FUN;
|
||||
|
||||
fun.set(NewNativeFunction(cx, WasmCall, numArgs, name, gc::AllocKind::FUNCTION_EXTENDED,
|
||||
SingletonObject, JSFunction::WASM_FUN));
|
||||
SingletonObject, flags));
|
||||
if (!fun)
|
||||
return false;
|
||||
fun->setWasmJitEntry(instance.code().getAddressOfJitEntry(funcIndex));
|
||||
|
||||
if (sig.temporarilyUnsupportedAnyRef())
|
||||
fun->setAsmJSIndex(funcIndex);
|
||||
else
|
||||
fun->setWasmJitEntry(instance.code().getAddressOfJitEntry(funcIndex));
|
||||
}
|
||||
|
||||
fun->setExtendedSlot(FunctionExtended::WASM_INSTANCE_SLOT, ObjectValue(*instanceObj));
|
||||
|
@ -92,6 +92,10 @@ SetupABIArguments(MacroAssembler& masm, const FuncExport& fe, Register argv, Reg
|
||||
masm.load32(src, iter->gpr());
|
||||
else if (type == MIRType::Int64)
|
||||
masm.load64(src, iter->gpr64());
|
||||
else if (type == MIRType::Pointer)
|
||||
masm.loadPtr(src, iter->gpr());
|
||||
else
|
||||
MOZ_CRASH("unknown GPR type");
|
||||
break;
|
||||
#ifdef JS_CODEGEN_REGISTER_PAIR
|
||||
case ABIArg::GPR_PAIR:
|
||||
@ -148,6 +152,10 @@ SetupABIArguments(MacroAssembler& masm, const FuncExport& fe, Register argv, Reg
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case MIRType::Pointer:
|
||||
masm.loadPtr(src, scratch);
|
||||
masm.storePtr(scratch, Address(masm.getStackPointer(), iter->offsetFromArgBase()));
|
||||
break;
|
||||
case MIRType::Double:
|
||||
masm.loadDouble(src, ScratchDoubleReg);
|
||||
masm.storeDouble(ScratchDoubleReg,
|
||||
@ -204,6 +212,9 @@ StoreABIReturn(MacroAssembler& masm, const FuncExport& fe, Register argv)
|
||||
masm.canonicalizeDouble(ReturnDoubleReg);
|
||||
masm.storeDouble(ReturnDoubleReg, Address(argv, 0));
|
||||
break;
|
||||
case ExprType::AnyRef:
|
||||
masm.storePtr(ReturnReg, Address(argv, 0));
|
||||
break;
|
||||
case ExprType::I8x16:
|
||||
case ExprType::I16x8:
|
||||
case ExprType::I32x4:
|
||||
@ -758,6 +769,9 @@ GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport&
|
||||
masm.canonicalizeDouble(ReturnDoubleReg);
|
||||
masm.boxDouble(ReturnDoubleReg, JSReturnOperand, ScratchDoubleReg);
|
||||
break;
|
||||
case ExprType::AnyRef:
|
||||
MOZ_CRASH("return anyref in jitentry NYI");
|
||||
break;
|
||||
case ExprType::I64:
|
||||
case ExprType::I8x16:
|
||||
case ExprType::I16x8:
|
||||
@ -845,6 +859,9 @@ StackCopy(MacroAssembler& masm, MIRType type, Register scratch, Address src, Add
|
||||
masm.load64(src, scratch64);
|
||||
masm.store64(scratch64, dst);
|
||||
#endif
|
||||
} else if (type == MIRType::Pointer) {
|
||||
masm.loadPtr(src, scratch);
|
||||
masm.storePtr(scratch, dst);
|
||||
} else if (type == MIRType::Float32) {
|
||||
masm.loadFloat32(src, ScratchFloat32Reg);
|
||||
masm.storeFloat32(ScratchFloat32Reg, dst);
|
||||
@ -878,8 +895,10 @@ FillArgumentArray(MacroAssembler& masm, const ValTypeVector& args, unsigned argO
|
||||
masm.breakpoint();
|
||||
else
|
||||
masm.store64(i->gpr64(), dst);
|
||||
} else {
|
||||
MOZ_CRASH("unexpected input type?");
|
||||
} else if (type == MIRType::Pointer) {
|
||||
if (toValue)
|
||||
MOZ_CRASH("generating a jit exit for anyref NYI");
|
||||
masm.storePtr(i->gpr(), dst);
|
||||
}
|
||||
break;
|
||||
#ifdef JS_CODEGEN_REGISTER_PAIR
|
||||
@ -926,6 +945,8 @@ FillArgumentArray(MacroAssembler& masm, const ValTypeVector& args, unsigned argO
|
||||
} else if (type == MIRType::Int64) {
|
||||
// We can't box int64 into Values (yet).
|
||||
masm.breakpoint();
|
||||
} else if (type == MIRType::Pointer) {
|
||||
MOZ_CRASH("generating a jit exit for anyref NYI");
|
||||
} else {
|
||||
MOZ_ASSERT(IsFloatingPointType(type));
|
||||
if (type == MIRType::Float32) {
|
||||
@ -1122,6 +1143,11 @@ GenerateImportInterpExit(MacroAssembler& masm, const FuncImport& fi, uint32_t fu
|
||||
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
|
||||
masm.loadDouble(argv, ReturnDoubleReg);
|
||||
break;
|
||||
case ExprType::AnyRef:
|
||||
masm.call(SymbolicAddress::CallImport_Ref);
|
||||
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
|
||||
masm.loadPtr(argv, ReturnReg);
|
||||
break;
|
||||
case ExprType::I8x16:
|
||||
case ExprType::I16x8:
|
||||
case ExprType::I32x4:
|
||||
@ -1297,6 +1323,9 @@ GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* throwLa
|
||||
case ExprType::F64:
|
||||
masm.convertValueToDouble(JSReturnOperand, ReturnDoubleReg, &oolConvert);
|
||||
break;
|
||||
case ExprType::AnyRef:
|
||||
MOZ_CRASH("anyref returned by import (jit exit) NYI");
|
||||
break;
|
||||
case ExprType::I8x16:
|
||||
case ExprType::I16x8:
|
||||
case ExprType::I32x4:
|
||||
@ -1712,7 +1741,7 @@ wasm::GenerateEntryStubs(MacroAssembler& masm, size_t funcExportIndex, const Fun
|
||||
if (!codeRanges->emplaceBack(CodeRange::InterpEntry, fe.funcIndex(), offsets))
|
||||
return false;
|
||||
|
||||
if (isAsmJS)
|
||||
if (isAsmJS || fe.sig().temporarilyUnsupportedAnyRef())
|
||||
return true;
|
||||
|
||||
if (!GenerateJitEntry(masm, funcExportIndex, fe, callee, &offsets))
|
||||
@ -1748,6 +1777,9 @@ wasm::GenerateStubs(const ModuleEnvironment& env, const FuncImportVector& import
|
||||
if (!code->codeRanges.emplaceBack(CodeRange::ImportInterpExit, funcIndex, interpOffsets))
|
||||
return false;
|
||||
|
||||
if (fi.sig().temporarilyUnsupportedAnyRef())
|
||||
continue;
|
||||
|
||||
JitExitOffsets jitOffsets;
|
||||
if (!GenerateImportJitExit(masm, fi, &throwLabel, &jitOffsets))
|
||||
return false;
|
||||
|
@ -591,8 +591,17 @@ class Sig
|
||||
bool hasI64ArgOrRet() const {
|
||||
if (ret() == ExprType::I64)
|
||||
return true;
|
||||
for (ValType a : args()) {
|
||||
if (a == ValType::I64)
|
||||
for (ValType arg : args()) {
|
||||
if (arg == ValType::I64)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool temporarilyUnsupportedAnyRef() const {
|
||||
if (ret() == ExprType::AnyRef)
|
||||
return true;
|
||||
for (ValType arg : args()) {
|
||||
if (arg == ValType::AnyRef)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1459,6 +1468,7 @@ enum class SymbolicAddress
|
||||
CallImport_I32,
|
||||
CallImport_I64,
|
||||
CallImport_F64,
|
||||
CallImport_Ref,
|
||||
CoerceInPlace_ToInt32,
|
||||
CoerceInPlace_ToNumber,
|
||||
CoerceInPlace_JitEntry,
|
||||
|
Loading…
Reference in New Issue
Block a user