Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Remove unwinding frames from WAVM code generation #7047

Merged
merged 3 commits into from
Apr 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions libraries/chain/include/eosio/chain/webassembly/wavm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,12 @@ struct intrinsic_invoker_impl<Ret, std::tuple<>, std::tuple<Translated...>> {

template<next_method_type Method>
static native_to_wasm_t<Ret> invoke(Translated... translated) {
return convert_native_to_wasm(the_running_instance_context, Method(the_running_instance_context, translated...));
try {
return convert_native_to_wasm(the_running_instance_context, Method(the_running_instance_context, translated...));
}
catch(...) {
Platform::immediately_exit(std::current_exception());
}
}

template<next_method_type Method>
Expand All @@ -331,7 +336,12 @@ struct intrinsic_invoker_impl<void_type, std::tuple<>, std::tuple<Translated...>

template<next_method_type Method>
static void invoke(Translated... translated) {
Method(the_running_instance_context, translated...);
try {
Method(the_running_instance_context, translated...);
}
catch(...) {
Platform::immediately_exit(std::current_exception());
}
}

template<next_method_type Method>
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/webassembly/wavm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ void wavm_runtime::immediately_exit_currently_running_module() {
#ifdef _WIN32
throw wasm_exit();
#else
Platform::immediately_exit();
Platform::immediately_exit(nullptr);
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion libraries/wasm-jit/Include/Platform/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ namespace Platform
Uptr& outTrapOperand,
const std::function<void()>& thunk
);
PLATFORM_API void immediately_exit();
PLATFORM_API [[noreturn]] void immediately_exit(std::exception_ptr except);

//
// Threading
Expand Down
8 changes: 7 additions & 1 deletion libraries/wasm-jit/Source/Platform/POSIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ namespace Platform
THREAD_LOCAL Uptr* signalOperand = nullptr;
THREAD_LOCAL bool isReentrantSignal = false;
THREAD_LOCAL bool isCatchingSignals = false;
thread_local std::exception_ptr thrown_exception;

void signalHandler(int signalNumber,siginfo_t* signalInfo,void*)
{
Expand Down Expand Up @@ -252,6 +253,7 @@ namespace Platform
jmp_buf oldSignalReturnEnv;
memcpy(&oldSignalReturnEnv,&signalReturnEnv,sizeof(jmp_buf));
const bool oldIsCatchingSignals = isCatchingSignals;
thrown_exception = nullptr;

// Use setjmp to allow signals to jump back to this point.
bool isReturningFromSignalHandler = sigsetjmp(signalReturnEnv,1);
Expand All @@ -273,10 +275,14 @@ namespace Platform
signalCallStack = nullptr;
signalOperand = nullptr;

if(thrown_exception)
std::rethrow_exception(thrown_exception);

return signalType;
}

void immediately_exit() {
void immediately_exit(std::exception_ptr except) {
thrown_exception = except;
siglongjmp(signalReturnEnv,1);
}

Expand Down
4 changes: 4 additions & 0 deletions libraries/wasm-jit/Source/Platform/Windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,10 @@ namespace Platform
{
errorUnless(SetEvent(reinterpret_cast<HANDLE>(event)));
}

void immediately_exit(std::exception_ptr except) {
std::rethrow_exception(except);
}
}

#endif
6 changes: 0 additions & 6 deletions libraries/wasm-jit/Source/Runtime/LLVMJIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,9 @@ namespace LLVMJIT

void registerEHFrames(U8* addr, U64 loadAddr,uintptr_t numBytes) override
{
llvm::RTDyldMemoryManager::registerEHFrames(addr,loadAddr,numBytes);
hasRegisteredEHFrames = true;
ehFramesAddr = addr;
ehFramesLoadAddr = loadAddr;
ehFramesNumBytes = numBytes;
}
void deregisterEHFrames(U8* addr, U64 loadAddr,uintptr_t numBytes) override
{
llvm::RTDyldMemoryManager::deregisterEHFrames(addr,loadAddr,numBytes);
}

virtual bool needsToReserveAllocationSpace() override { return true; }
Expand Down
59 changes: 38 additions & 21 deletions libraries/wasm-jit/Source/Runtime/WAVMIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@

namespace Runtime
{
static void causeIntrensicException(Exception::Cause cause) {
try {
Platform::immediately_exit(std::make_exception_ptr(Exception{cause, std::vector<std::string>()}));
}
catch (...) {
Platform::immediately_exit(std::current_exception());
}
__builtin_unreachable();
}

template<typename Float>
Float quietNaN(Float value)
{
Expand Down Expand Up @@ -104,11 +114,11 @@ namespace Runtime
{
if(sourceValue != sourceValue)
{
causeException(Exception::Cause::invalidFloatOperation);
causeIntrensicException(Exception::Cause::invalidFloatOperation);
}
else if(sourceValue >= maxValue || (isMinInclusive ? sourceValue <= minValue : sourceValue < minValue))
{
causeException(Exception::Cause::integerDivideByZeroOrIntegerOverflow);
causeIntrensicException(Exception::Cause::integerDivideByZeroOrIntegerOverflow);
}
return (Dest)sourceValue;
}
Expand All @@ -125,45 +135,51 @@ namespace Runtime

DEFINE_INTRINSIC_FUNCTION0(wavmIntrinsics,divideByZeroOrIntegerOverflowTrap,divideByZeroOrIntegerOverflowTrap,none)
{
causeException(Exception::Cause::integerDivideByZeroOrIntegerOverflow);
causeIntrensicException(Exception::Cause::integerDivideByZeroOrIntegerOverflow);
}

DEFINE_INTRINSIC_FUNCTION0(wavmIntrinsics,unreachableTrap,unreachableTrap,none)
{
causeException(Exception::Cause::reachedUnreachable);
causeIntrensicException(Exception::Cause::reachedUnreachable);
}

DEFINE_INTRINSIC_FUNCTION0(wavmIntrinsics,accessViolationTrap,accessViolationTrap,none)
{
causeException(Exception::Cause::accessViolation);
causeIntrensicException(Exception::Cause::accessViolation);
}

DEFINE_INTRINSIC_FUNCTION3(wavmIntrinsics,indirectCallSignatureMismatch,indirectCallSignatureMismatch,none,i32,index,i64,expectedSignatureBits,i64,tableBits)
{
TableInstance* table = reinterpret_cast<TableInstance*>(tableBits);
void* elementValue = table->baseAddress[index].value;
const FunctionType* actualSignature = table->baseAddress[index].type;
const FunctionType* expectedSignature = reinterpret_cast<const FunctionType*>((Uptr)expectedSignatureBits);
std::string ipDescription = "<unknown>";
LLVMJIT::describeInstructionPointer(reinterpret_cast<Uptr>(elementValue),ipDescription);
Log::printf(Log::Category::debug,"call_indirect signature mismatch: expected %s at index %u but got %s (%s)\n",
asString(expectedSignature).c_str(),
index,
actualSignature ? asString(actualSignature).c_str() : "nullptr",
ipDescription.c_str()
);
causeException(elementValue == nullptr ? Exception::Cause::undefinedTableElement : Exception::Cause::indirectCallSignatureMismatch);
try {
TableInstance* table = reinterpret_cast<TableInstance*>(tableBits);
void* elementValue = table->baseAddress[index].value;
const FunctionType* actualSignature = table->baseAddress[index].type;
const FunctionType* expectedSignature = reinterpret_cast<const FunctionType*>((Uptr)expectedSignatureBits);
std::string ipDescription = "<unknown>";
LLVMJIT::describeInstructionPointer(reinterpret_cast<Uptr>(elementValue),ipDescription);
Log::printf(Log::Category::debug,"call_indirect signature mismatch: expected %s at index %u but got %s (%s)\n",
asString(expectedSignature).c_str(),
index,
actualSignature ? asString(actualSignature).c_str() : "nullptr",
ipDescription.c_str()
);
causeIntrensicException(elementValue == nullptr ? Exception::Cause::undefinedTableElement : Exception::Cause::indirectCallSignatureMismatch);
}
catch (...) {
Platform::immediately_exit(std::current_exception());
}
}
heifner marked this conversation as resolved.
Show resolved Hide resolved

DEFINE_INTRINSIC_FUNCTION0(wavmIntrinsics,indirectCallIndexOutOfBounds,indirectCallIndexOutOfBounds,none)
{
causeException(Exception::Cause::undefinedTableElement);
causeIntrensicException(Exception::Cause::undefinedTableElement);
}

DEFINE_INTRINSIC_FUNCTION2(wavmIntrinsics,_growMemory,growMemory,i32,i32,deltaPages,i64,memoryBits)
{
MemoryInstance* memory = reinterpret_cast<MemoryInstance*>(memoryBits);
WAVM_ASSERT_THROW(memory);
if(!memory)
causeIntrensicException(Exception::Cause::outOfMemory);
const Iptr numPreviousMemoryPages = growMemory(memory,(Uptr)deltaPages);
if(numPreviousMemoryPages + (Uptr)deltaPages > IR::maxMemoryPages) { return -1; }
else { return (I32)numPreviousMemoryPages; }
Expand All @@ -172,7 +188,8 @@ namespace Runtime
DEFINE_INTRINSIC_FUNCTION1(wavmIntrinsics,_currentMemory,currentMemory,i32,i64,memoryBits)
{
MemoryInstance* memory = reinterpret_cast<MemoryInstance*>(memoryBits);
WAVM_ASSERT_THROW(memory);
if(!memory)
causeIntrensicException(Exception::Cause::outOfMemory);
Uptr numMemoryPages = getMemoryNumPages(memory);
if(numMemoryPages > UINT32_MAX) { numMemoryPages = UINT32_MAX; }
return (U32)numMemoryPages;
Expand Down