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

Commit

Permalink
Merge pull request #7047 from EOSIO/wavm_no_exceptions
Browse files Browse the repository at this point in the history
Remove unwinding frames from WAVM code generation
  • Loading branch information
spoonincode committed Apr 15, 2019
2 parents 6d7a5e7 + bbc57fd commit 6f4828f
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 32 deletions.
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());
}
}

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

0 comments on commit 6f4828f

Please sign in to comment.