diff --git a/example/trap.c b/example/trap.c index 74620dc..543fad3 100644 --- a/example/trap.c +++ b/example/trap.c @@ -20,6 +20,16 @@ own wasm_trap_t* fail_callback( } +void print_frame(wasm_frame_t* frame) { + printf("> %p @ 0x%zx = %"PRIu32".0x%zx\n", + wasm_frame_instance(frame), + wasm_frame_module_offset(frame), + wasm_frame_func_index(frame), + wasm_frame_func_offset(frame) + ); +} + + int main(int argc, const char* argv[]) { // Initialize. printf("Initializing...\n"); @@ -104,6 +114,27 @@ int main(int argc, const char* argv[]) { wasm_trap_message(trap, &message); printf("> %s\n", message.data); + printf("Printing origin...\n"); + own wasm_frame_t* frame = wasm_trap_origin(trap); + if (frame) { + print_frame(frame); + wasm_frame_delete(frame); + } else { + printf("> Empty origin.\n"); + } + + printf("Printing trace...\n"); + own wasm_frame_vec_t trace; + wasm_trap_trace(trap, &trace); + if (trace.size > 0) { + for (size_t i = 0; i < trace.size; ++i) { + print_frame(trace.data[i]); + } + } else { + printf("> Empty trace.\n"); + } + + wasm_frame_vec_delete(&trace); wasm_trap_delete(trap); wasm_name_delete(&message); } diff --git a/example/trap.cc b/example/trap.cc index 3311621..1cfd77f 100644 --- a/example/trap.cc +++ b/example/trap.cc @@ -17,6 +17,14 @@ auto fail_callback( } +void print_frame(const wasm::Frame* frame) { + std::cout << "> " << frame->instance(); + std::cout << " @ 0x" << std::hex << frame->module_offset(); + std::cout << " = " << frame->func_index(); + std::cout << ".0x" << std::hex << frame->func_offset() << std::endl; +} + + void run() { // Initialize. std::cout << "Initializing..." << std::endl; @@ -85,6 +93,24 @@ void run() { std::cout << "Printing message..." << std::endl; std::cout << "> " << trap->message().get() << std::endl; + + std::cout << "Printing origin..." << std::endl; + auto frame = trap->origin(); + if (frame) { + print_frame(frame.get()); + } else { + std::cout << "> Empty origin." << std::endl; + } + + std::cout << "Printing trace..." << std::endl; + auto trace = trap->trace(); + if (trace.size() > 0) { + for (size_t i = 0; i < trace.size(); ++i) { + print_frame(trace[i].get()); + } + } else { + std::cout << "> Empty trace." << std::endl; + } } // Shut down. diff --git a/include/wasm.h b/include/wasm.h index 86fb4c7..658ad6c 100644 --- a/include/wasm.h +++ b/include/wasm.h @@ -345,6 +345,18 @@ WASM_DECLARE_VEC(val, ) WASM_DECLARE_REF_BASE(ref) +// Frames + +WASM_DECLARE_OWN(frame) +WASM_DECLARE_VEC(frame, *) +own wasm_frame_t* wasm_frame_copy(const wasm_frame_t*); + +struct wasm_instance_t* wasm_frame_instance(const wasm_frame_t*); +uint32_t wasm_frame_func_index(const wasm_frame_t*); +size_t wasm_frame_func_offset(const wasm_frame_t*); +size_t wasm_frame_module_offset(const wasm_frame_t*); + + // Traps typedef wasm_name_t wasm_message_t; // null terminated @@ -354,6 +366,8 @@ WASM_DECLARE_REF(trap) own wasm_trap_t* wasm_trap_new(wasm_store_t* store, const wasm_message_t*); void wasm_trap_message(const wasm_trap_t*, own wasm_message_t* out); +own wasm_frame_t* wasm_trap_origin(const wasm_trap_t*); +void wasm_trap_trace(const wasm_trap_t*, own wasm_frame_vec_t* out); // Foreign Objects diff --git a/include/wasm.hh b/include/wasm.hh index d5c3b94..024f834 100644 --- a/include/wasm.hh +++ b/include/wasm.hh @@ -584,6 +584,22 @@ template<> inline auto Val::get() const -> uint64_t { using Message = vec; // null terminated +class Instance; + +class Frame { +public: + Frame() = delete; + ~Frame(); + void operator delete(void*); + + auto copy() const -> own; + + auto instance() const -> Instance*; + auto func_index() const -> uint32_t; + auto func_offset() const -> size_t; + auto module_offset() const -> size_t; +}; + class Trap : public Ref { public: Trap() = delete; @@ -593,6 +609,8 @@ public: auto copy() const -> own; auto message() const -> Message; + auto origin() const -> own; // may be null + auto trace() const -> vec; // may be empty, origin first }; diff --git a/src/wasm-c.cc b/src/wasm-c.cc index e330366..01f081e 100644 --- a/src/wasm-c.cc +++ b/src/wasm-c.cc @@ -668,6 +668,31 @@ void wasm_val_copy(wasm_val_t* out, const wasm_val_t* v) { /////////////////////////////////////////////////////////////////////////////// // Runtime Objects +// Frames + +WASM_DEFINE_OWN(frame, Frame) +WASM_DEFINE_VEC(frame, Frame, *) + +wasm_frame_t* wasm_frame_copy(const wasm_frame_t* frame) { + return release(frame->copy()); +} + +wasm_instance_t* wasm_frame_instance(const wasm_frame_t* frame); +// Defined below along with wasm_instance_t. + +uint32_t wasm_frame_func_index(const wasm_frame_t* frame) { + return reveal(frame)->func_index(); +} + +size_t wasm_frame_func_offset(const wasm_frame_t* frame) { + return reveal(frame)->func_offset(); +} + +size_t wasm_frame_module_offset(const wasm_frame_t* frame) { + return reveal(frame)->module_offset(); +} + + // Traps WASM_DEFINE_REF(trap, Trap) @@ -681,6 +706,14 @@ void wasm_trap_message(const wasm_trap_t* trap, wasm_message_t* out) { *out = release(reveal(trap)->message()); } +wasm_frame_t* wasm_trap_origin(const wasm_trap_t* trap) { + return release(reveal(trap)->origin()); +} + +void wasm_trap_trace(const wasm_trap_t* trap, wasm_frame_vec_t* out) { + *out = release(reveal(trap)->trace()); +} + // Foreign Objects @@ -982,4 +1015,9 @@ void wasm_instance_exports( *out = release(instance->exports()); } + +wasm_instance_t* wasm_frame_instance(const wasm_frame_t* frame) { + return hide(reveal(frame)->instance()); +} + } // extern "C" diff --git a/src/wasm-v8.cc b/src/wasm-v8.cc index 70b85be..c46ff09 100644 --- a/src/wasm-v8.cc +++ b/src/wasm-v8.cc @@ -23,6 +23,7 @@ namespace v8 { extern bool FLAG_experimental_wasm_mv; extern bool FLAG_experimental_wasm_anyref; extern bool FLAG_experimental_wasm_bulk_memory; + extern bool FLAG_experimental_wasm_return_call; } } @@ -68,7 +69,7 @@ auto seal(const typename implement ::type* x) -> const C* { struct Stats { enum category_t { - BYTE, CONFIG, ENGINE, STORE, + BYTE, CONFIG, ENGINE, STORE, FRAME, VALTYPE, FUNCTYPE, GLOBALTYPE, TABLETYPE, MEMORYTYPE, EXTERNTYPE, IMPORTTYPE, EXPORTTYPE, VAL, REF, TRAP, @@ -176,7 +177,7 @@ struct Stats { #ifdef DEBUG const char* Stats::name[STRONG_COUNT] = { - "byte_t", "Config", "Engine", "Store", + "byte_t", "Config", "Engine", "Store", "Frame", "ValType", "FuncType", "GlobalType", "TableType", "MemoryType", "ExternType", "ImportType", "ExportType", "Val", "Ref", "Trap", @@ -210,6 +211,7 @@ Stats stats; } DEFINE_VEC(byte_t, BYTE) +DEFINE_VEC(Frame*, FRAME) DEFINE_VEC(ValType*, VALTYPE) DEFINE_VEC(FuncType*, FUNCTYPE) DEFINE_VEC(GlobalType*, GLOBALTYPE) @@ -295,8 +297,9 @@ auto Engine::make(own&& config) -> own { v8::internal::FLAG_expose_gc = true; v8::internal::FLAG_experimental_wasm_bigint = true; v8::internal::FLAG_experimental_wasm_mv = true; - // v8::internal::FLAG_experimental_wasm_anyref = true; - // v8::internal::FLAG_experimental_wasm_bulk_memory = true; + v8::internal::FLAG_experimental_wasm_anyref = true; + v8::internal::FLAG_experimental_wasm_bulk_memory = true; + v8::internal::FLAG_experimental_wasm_return_call = true; // v8::V8::SetFlagsFromCommandLine(&argc, const_cast(argv), false); auto engine = new(std::nothrow) EngineImpl; if (!engine) return own(); @@ -1217,6 +1220,64 @@ void Ref::set_host_info(void* info, void (*finalizer)(void*)) { /////////////////////////////////////////////////////////////////////////////// // Runtime Objects +// Frames + +struct FrameImpl { + FrameImpl( + own&& instance, uint32_t func_index, + size_t func_offset, size_t module_offset + ) : + instance(std::move(instance)), + func_index(func_index), + func_offset(func_offset), + module_offset(module_offset) + { + stats.make(Stats::FRAME, this); + } + + ~FrameImpl() { stats.free(Stats::FRAME, this); } + + own instance; + uint32_t func_index; + size_t func_offset; + size_t module_offset; +}; + +template<> struct implement { using type = FrameImpl; }; + + +Frame::~Frame() { + impl(this)->~FrameImpl(); +} + +void Frame::operator delete(void *p) { + ::operator delete(p); +} + +auto Frame::copy() const -> own { + auto self = impl(this); + return own(seal(new(std::nothrow) FrameImpl( + self->instance->copy(), self->func_index, self->func_offset, + self->module_offset))); +} + +auto Frame::instance() const -> Instance* { + return impl(this)->instance.get(); +} + +auto Frame::func_index() const -> uint32_t { + return impl(this)->func_index; +} + +auto Frame::func_offset() const -> size_t { + return impl(this)->func_offset; +} + +auto Frame::module_offset() const -> size_t { + return impl(this)->module_offset; +} + + // Traps template<> struct implement { using type = RefImpl; }; @@ -1249,6 +1310,16 @@ auto Trap::message() const -> Message { return vec::make(std::string(*string)); } +auto Trap::origin() const -> own { + // TODO(v8): implement + return own(nullptr); +} + +auto Trap::trace() const -> vec { + // TODO(v8): implement + return vec::make(); +} + // Foreign Objects