Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add stacktrace API #70

Merged
merged 1 commit into from
May 16, 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
31 changes: 31 additions & 0 deletions example/trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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);
}
Expand Down
26 changes: 26 additions & 0 deletions example/trap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
14 changes: 14 additions & 0 deletions include/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,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
Expand All @@ -353,6 +365,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
Expand Down
18 changes: 18 additions & 0 deletions include/wasm.hh
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,22 @@ template<> inline auto Val::get<uint64_t>() const -> uint64_t {

using Message = vec<byte_t>; // null terminated

class Instance;

class Frame {
public:
Frame() = delete;
~Frame();
void operator delete(void*);

auto copy() const -> own<Frame*>;

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;
Expand All @@ -592,6 +608,8 @@ public:
auto copy() const -> own<Trap*>;

auto message() const -> Message;
auto origin() const -> own<Frame*>; // may be null
auto trace() const -> vec<Frame*>; // may be empty, origin first
};


Expand Down
38 changes: 38 additions & 0 deletions src/wasm-c.cc
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,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)
Expand All @@ -677,6 +702,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

Expand Down Expand Up @@ -978,4 +1011,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"
79 changes: 75 additions & 4 deletions src/wasm-v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -68,7 +69,7 @@ auto seal(const typename implement <C>::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,
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -295,8 +297,9 @@ auto Engine::make(own<Config*>&& config) -> own<Engine*> {
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<char**>(argv), false);
auto engine = new(std::nothrow) EngineImpl;
if (!engine) return own<Engine*>();
Expand Down Expand Up @@ -1212,6 +1215,64 @@ void Ref::set_host_info(void* info, void (*finalizer)(void*)) {
///////////////////////////////////////////////////////////////////////////////
// Runtime Objects

// Frames

struct FrameImpl {
FrameImpl(
own<Instance*>&& 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*> instance;
uint32_t func_index;
size_t func_offset;
size_t module_offset;
};

template<> struct implement<Frame> { using type = FrameImpl; };


Frame::~Frame() {
impl(this)->~FrameImpl();
}

void Frame::operator delete(void *p) {
::operator delete(p);
}

auto Frame::copy() const -> own<Frame*> {
auto self = impl(this);
return own<Frame*>(seal<Frame>(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<Trap> { using type = RefImpl<Trap>; };
Expand Down Expand Up @@ -1244,6 +1305,16 @@ auto Trap::message() const -> Message {
return vec<byte_t>::make(std::string(*string));
}

auto Trap::origin() const -> own<Frame*> {
// TODO(v8): implement
return own<Frame*>(nullptr);
}

auto Trap::trace() const -> vec<Frame*> {
// TODO(v8): implement
return vec<Frame*>::make();
}


// Foreign Objects

Expand Down