Git Product home page Git Product logo

wasm-c-api's Introduction

WebAssembly C and C++ API

Work in progress! No docs yet.

Design Goals

  • Provide a "black box" API for embedding a Wasm engine in other C/C++ applications.

    • Be completely agnostic to VM specifics.

    • Non-goal: "white box" interoperability with embedder (such as combined GC instead of mere finalisation) -- much more difficult to achieve.

  • Allow creation of bindings for other languages through typical C foreign function interfaces.

    • Support a plain C API.

    • Stick to mostly manual memory management of interface objects.

  • Avoid language features that raise barrier to use.

    • E.g., no exceptions or post-C++11 features in C++ API.

    • E.g., no passing of structs by-value or post-C99 features in C API.

  • Achieve link-time compatibility between different implementations.

    • All implementation-dependent API classes are abstract and can be instantiated through factory methods only.

Interfaces

  • C++ API:

    • See include/wasm.hh for interface.

    • See example/*.cc for example usages.

  • C API:

    • See include/wasm.h for interface.

    • See example/*.c for example usages.

Some random explanations:

  • The VM must be initialised by creating an instance of an engine (wasm::Engine/wasm_engine_t) and is shut down by deleting it. Such an instance may only be created once per process.

  • All runtime objects are tied to a specific store (wasm::Store/wasm_store_t). Multiple stores can be created, but their objects cannot interact. Every store and its objects must only be accessed in a single thread.

  • To exchange module objects between threads, create a shared module (wasm::Shared<Module>/wasm_shared_module_t). Other objects cannot be shared in current Wasm.

  • Vector structures (wasm::vec<X>/wasm_x_vec_t) are lightweight abstractions of a pair of a plain array and its length. The C++ API does not use std::vector because that does not support adopting pre-existing arrays.

  • References point to runtime objects, but may involve internal indirections, which may or may not be cached. Thus, pointer equality on Ref* or subclasses cannot be used to compare identity of the underlying objects (Ref::eq may be added later). However, nullptr/NULL uniquely represents null references.

  • The API already encompasses current proposals like multiple return values and reference types, but not yet threads.

Prototype Implementation

  • This repo contains a prototype implementation based on V8 is in src.

    • Note that this requires adding a module to V8, so it patches V8's build file.
  • The C API is implemented on top of the C++ API.

  • See Makefile for build recipe. Canonical steps to run examples:

    1. make v8-checkout
    2. make v8
    3. make all

Limitations

V8 implementation:

  • Currently requires patching V8 by adding a module.

  • Host functions (Func::make) create a JavaScript function internally, since V8 cannot handle raw C imports yet.

  • As a consequence, does not support multiple results in external calls or host functions.

  • Host functions and host globals are created through auxiliary modules constructed on the fly, to work around limitations in JS API.

  • Shared<Module> is currently implemented via serialisation, since V8 does not currently have direct support for cross-isolate sharing.

Other Implementations

Currently, known implementations of this API are included in

  • V8 natively (both C and C++)
  • Wabt (only C?)
  • Wasmtime (only C?)
  • Wasmer (only C, C++ coming soon)

TODO

Possible API tweaks:

  • Add Ref::eq (or better, a subclass EqRef::eq) for reference equality?

  • Add a way to return error messages from Module::make and Module::validate.

  • Use restrict in C API?

  • Find a way to perform C callbacks through C++ without extra wrapper?

  • Add iterators to vec class?

wasm-c-api's People

Contributors

andrewscheidecker avatar ashtonmeuser avatar billti avatar brianchin avatar danbev avatar dio avatar ggreif avatar hishamhm avatar hywan avatar jakobkummerow avatar lostman avatar lukasforst avatar markmccaskey avatar newproggie avatar nlewycky avatar nomeata avatar rossberg avatar sbc100 avatar sunfishcode avatar syrusakbary avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wasm-c-api's Issues

Programmatic import resolution

In the proposed API, the creating of an instance (Instance::make()) takes an array of imports. Presumably, this array positionally corresponds to the imports declared for a module. As such, the declared module and import names within the module would be ignored. I think we should change this API to allow the instantiator to supply an implementation of class that does import resolution, something along the lines of (roughly):

class ImportResolver {
const Memory* resolveMemory(const char* module_name, const char* import_name);
const Func* resolveFunc(const char* module_name, const char* import_name);
. . .
}

Reproducible build instructions

I couldn't build any of the recent versions of this repository. After poking around I traced the issue back to these two lines in the Makefile:

echo >>${V8_OUT}/args.gn use_custom_libcxx = false
echo >>${V8_OUT}/args.gn use_custom_libcxx_for_host = false

Before these were added I was able to build the repository and examples using the included Dockerfile. After these were added the build fails due to issues related to libc++ linking.

I encountered same libc++ linking issues when trying to build the library and examples using the included Makefile.

Can we work out fully reproducible build steps?

@rossberg if you're working with V8 master branch, can you describe how do you build it?

I would also like to add automatic testing but V8 looks too big to build on Travis. It would probably be better to build on our Jenkins server.

Should re-exported functions preserve identity?

Consider a module that imports a function and exports it again:

(module
  (func (import "" "f") (export ("f"))
)

and host code that triggers this round trip:

own<Func> f1 = Func::make(...);
auto instance = Instance::make(..., {f1.get()});
auto exports = instance->exports();
Func* f2 = exports[...]->func();

which leads to the question: should f1 and f2 have the same identity?

In other words: should f1->same(f2) return true or false? In yet other words, if host data was stored on f1 using f1->set_host_info(...), should f2->get_host_info() return that host data?

I think reasonable arguments can be made both ways, and I think it mostly boils down to what one assumes about knowledge of host and module about each other.

(A) If one assumes that the host knows what the module does, then intuitively it makes sense that round-tripping preserves identity: if I pass in a thing and get the same thing handed back out to me, then of course it should be the exact same thing!

(B) If one assumes that the module is a "black box" from the host's point of view, then it makes sense for the host to assume that each export is a unique object, and assumptions about shared identities are inherently unsafe. After all, the module could be doing (or in a new version be changed to doing) this instead:

(func $f (import "" "f"))
(func (export "f") (call logging) (call $f))

which would provide the same interface to the host, but break the assumption about identity.

Implementation-wise, both possible behaviors are doable. V8's current implementation just so happens to do case (B) above, but that should not be a deciding factor here.

My own opinion at this time is that I'm leaning towards (B), because I think the "black box" assumption is more likely in actual deployment scenarios (the decoupling of module and host is kind of the point of running Wasm modules in the first place), and the white-box scenario where (A) would make more sense probably mostly shows up in small artificial testcases. That said, I could be convinced otherwise.

Either way, I think it would be good to specify the expected behavior, or alternatively at least document officially that it is unspecified :-)

(Unrelated side note: I still find it a surprising footgun that instance->exports()[0]->func() leads to a crash; but I'm not sure what to do about it.)

Consider C++17/20

It's unfortunate that the API has chosen very old C++ standard. With C++20 you can construct a module from, say, std::span<const std::byte> and there is no need to reinvent the wheel. Please consider bumping the C++ version.

An API which automatically validates its inputs

It appears wasm_module_new / Module::make does not perform validation. The API provides wasm_module_validate / Module::validate which can be used to explicitly validate, however it's easy to forget to use these.

It would make the API safer if wasm_module_new / Module::make performed validation, and there were additional functions with evocative names, such as wasm_module_new_unchecked / Module::make_unchecked, for creating a module without validation.

Configurable resource limitations

This is a post-MVP feature request.

In some contexts, it may make sense to limit the amount of resources available to Wasm modules and perhaps also their size. In particular, for some applications where Wasm will be the scripting mechanism and embedding a Wasm engine via this API, it may make sense to require modules to be "small" and "not use much memory."

The JS API embedding defines a set of standard resource limitations (https://github.com/WebAssembly/spec/blob/master/document/js-api/index.bs#L1059) on modules. This set of configurable parameters is a good start for what an embedder may want to provide when creating an engine.

Expose bounds-checked memory access API

The API currently exposes the contents of a memory as:

byte_t* wasm_memory_data(wasm_memory_t*);
size_t wasm_memory_data_size(const wasm_memory_t*);

This effectively delegates the bounds checking to the API client. The problem is that this doesn't expose a race-free way to bounds check a memory access in the case of shared memories, and even in the single-threaded case can be hard for the client to get right.

An API that would make it easy for API clients to do the right thing is:

bool wasm_memory_lock_range(wasm_memory_t*, size_t offset, size_t size, byte_t** out_range_base);
void wasm_memory_unlock_range(wasm_memory_t*, size_t offset, size_t size);

This shouldn't involve any actual locking as long as the VM is single-threaded, or knows the memory can't shrink, unmap/protect pages, etc. If the VM is multi-threaded and supports shrinking/unmapping/protecting pages, then I imagine you'd use a rwlock to serialize these range-locks with those operations that mutate the bounds-checking state.

What is `wasm_val_ptr` used for?

In include/wasm.h, what is the expected use for wasm_val_init_ptr and wasm_val_ptr? It isn't obvious what the use for passing host pointer values into wasm is.

Invert C/C++ API layering

The current C API is implemented in terms of the C++ API, but I think it would be better to invert that layering:

  • The C API is the only interface defined between users and runtimes.
  • Define a C++ header-only library that wraps the C API.

This means that users can use a C++-style API if they like, but runtimes only need to implement the C API.

Binaries?

Are the binaries for this published anywhere?

sigsegv when trying to access exported memory

  own<Trap> trap;
  auto instance = Instance::make(store.get(), module.get(), imports, &trap);
  if (trap) {
    PrintTrap(trap);
    return 1;
  }

  auto memory = instance.get()->exports()[0]->memory();
  assert(memory->kind() == wasm::EXTERN_MEMORY); // SIGSEGV here

backtrace:

(lldb) bt
* thread #1, name = 'weed8', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
  * frame #0: 0x0000555556859158 weed8`v8::internal::FullObjectSlot::operator*() const at slots-inl.h:32:64
    frame #1: 0x000055555686e3bd weed8`v8::internal::Handle<v8::internal::JSReceiver> const v8::internal::Handle<v8::internal::JSReceiver>::cast<v8::internal::JSReceiver>(v8::internal::Handle<v8::internal::JSReceiver>) at handles-inl.h:28:11
    frame #2: 0x000055555684fd50 weed8`wasm::RefImpl<wasm::Extern, v8::internal::JSReceiver>::v8_object() const at c-api.cc:761:48
    frame #3: 0x00005555568423ed weed8`wasm::Extern::kind() const at c-api.cc:1116:46
    frame #4: 0x0000555556838bac weed8`weed8::run(char const*) at weed8.cc:134:3

module is

(module
  (import "wasi_unstable" "fd_write" (func $fd_write (param i32) (param i32) (param i32) (result i32)))

  (memory (export "memory") 1)

  (data (i32.const 16)
    "Hello, World"
  )

  (func $start
    (i32.store (i32.const 0) (i32.const 12)) ;; length of data at 16
    (i32.store (i32.const 4) (i32.const 16)) ;; pointer to data at 16
    (call $fd_write (i32.const 1) (i32.const 0) (i32.const 1))
    (drop)
  )

  (export "start" (func $start))
)

Avoid union to represent wasm::val

There are two problems with using a union to represent different Wasm values (especially in arrays):

  1. it wastes space,
  2. binary backwards-compatibility breaks the moment we need to add a wider value type (e.g. SIMD).

The latter could be circumvented by requiring an indirection for passing types wider than i64 or pointers, though that raises additional memory management questions.

If that's not an option that the latter might be a showstopper. For example, it might prevent Apple from officially supporting the API, because they have strict backwards-compatibility policies.

To address these issues, function arguments and results should not be passed as a homogeneous array-of-union, but as a heterogeneous list/tuple/struct.

Possible alternatives considered:

  • Use varargs. For example:

    auto Func::call(...) const -> own<Trap*>;
    

    The ... would be instantiated with the sequence of values with types corresponding to the function's parameters, followed by a sequence of out pointers corresponding to its results.
    Problems: (1) would not allow types with destructors, which we need to safely handle reference values in the C++ API; (2) varargs are out of reach for most FFI layers, so not a suitable option for the C API.

  • Use std::tuple. For example:

    template<class... T, class... R>
    auto Func::call(std::tuple<T...> args, std::tuple<R&...> results) const -> own<Trap*>;
    

    Problems: (1) does not address C API; (2) cannot be wrapped into C without copying.

  • A custom variant of tuple that supports standard layout. For example:

    template<class... T, class... R>
    auto Func::call(wasm::seq<T...> args, wasm::seq<R&...> results) const -> own<Trap*>;
    

    This would allow casting from and to a struct defined in C.
    Problems: (1) on the C side, may need to declare auxiliary structs per call site/type; (2) may be difficult for FFIs.

  • Pack into byte array. For example:

    auto Func::call(const byte* args, byte* results) const -> own<Trap*>;
    

    Problems: (1) does not safely handle types with destructors, e.g. reference values; (2) requires manual handling of alignment, not clear how in a platform-agnostic manner; (3) tedious to use.

  • Other solutions?

Avoid relying on host floating-point

include/wasm.h:

typedef float float32_t;
typedef double float64_t;

For maximum portability, it'd be best to use int32_t and int64_t here. wasm-c-api itself doesn't need to do any floating-point computation; it just needs to be able to pass values around verbatim.

Request for clarification: why only one engine?

The readme states:

The VM must be initialised by creating an instance of an engine (wasm::Engine/wasm_engine_t) and is shut down by deleting it. Such an instance may only be created once per process.

I removed the block. Then spun an engine up and down, then another up. But when creating a store, it crashed. Backtraces point into v8. Looks like there is some kind of history effect.

So is this restriction a self imposed one to avoid the necessity to deal with a buggy v8, or is there some fundamental reason that no subsequent engines can be created?

Motivation: I have tests that would profit from the ability to toggle the creation of engines many times in the scope of a linux process.

Exposing "regular" C/C++ functions?

I was wondering whether there was any appetite for exposing "regular" C/C++ functions to WebAssembly, e.g.

int function_I_have_anyway(int32_t a, int64_t b, double c, float d);

(as opposed to functions specifically coded against the (void* env, Val args[], Val results[]) API).

This would obviously have to be limited to functions whose signatures are a subset of valid Wasm signatures.

The primary benefit would be performance. Calling such functions directly would avoid one layer of indirection (=copying parameters and return values back and forth) -- on the assumption that such a function is where the real work happens anyway, and with the current state of things it would have to be wrapped into Val[] args, Val[] returns style.

Another benefit would be convenience, because it would no longer be necessary to write such a wrapper.
For the C++ version of the API, we might even be able to use template magic to derive the signature automatically; for the C version I don't think that is possible, so the signature would still have to be specified manually.

A drawback I can see is that this would make it difficult to support features like multiple return values and traps/exceptions. The former should not be an issue, if the envisioned use case is to expose existing functions to Wasm -- they only return one value anyway. I'm not sure how much of a problem the latter is.

I don't see a way for such functions to retain a ::call method, for lack of a way of specifying it. Functionality-wise that's probably be fine, because they can always be called directly; but this means that a separate type (as in: not Func) would probably have to be introduced for them.

WDYT? Are lower-overhead calls from WebAssembly into C/C++ worth the effort of exploring this direction? Or would the cases where this actually helps be too narrow to be useful?

Where are the source code of example/*.wasm?

I guess the example/hello.c is compiled to binary out/example/hello-c which is used to load out/example/hello.wasm and I guess the hello-c do some interaction with hello.wasm such as callback.

I'm trying to learn the c-api of this project but it's difficult for me to learn it without the source code of example/*.wasm.
For example I'm confused how the hello.wasm call the hello_callback defined in hello.c, should I need the source code ?

CMake Example doesn't work

ExternalProject_Add creates a target which builds at build time, find_library happens at configure time, I don't see how it's supposed to ever work to begin with.

V8 fails to build due to wasm-v8-lowlevel.cc

The full log:

==== Building V8 branch-heads/6.8 x64.release ====
(cd v8/v8; PATH=/code/wasm-c-api/v8/depot_tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin tools/dev/v8gen.py x64.release)
echo >>v8/v8/out.gn/x64.release/args.gn is_component_build = false
echo >>v8/v8/out.gn/x64.release/args.gn v8_static_library = true
echo >>v8/v8/out.gn/x64.release/args.gn use_custom_libcxx = false
echo >>v8/v8/out.gn/x64.release/args.gn use_custom_libcxx_for_host = false
(cd v8/v8; PATH=/code/wasm-c-api/v8/depot_tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ninja -C out.gn/x64.release)
ninja: Entering directory `out.gn/x64.release'
[1/1758] ACTION //:d8_js2c(//build/toolchain/linux:clang_x64)
[2/1758] CXX obj/v8_libbase/division-by-constant.o
[3/1758] STAMP obj/d8_js2c.stamp
[4/1758] CXX obj/v8_libbase/file-utils.o
[5/1758] ACTION //:js2c(//build/toolchain/linux:clang_x64)
[6/1758] STAMP obj/js2c.stamp
[7/1758] CXX obj/v8_libbase/functional.o
[8/1758] CXX obj/v8_libbase/ieee754.o
[9/1758] ACTION //:js2c_experimental_extras(//build/toolchain/linux:clang_x64)
[10/1758] STAMP obj/js2c_experimental_extras.stamp
[11/1758] ACTION //:js2c_extras(//build/toolchain/linux:clang_x64)
[12/1758] STAMP obj/js2c_extras.stamp
[13/1758] ACTION //:postmortem-metadata(//build/toolchain/linux:clang_x64)
[14/1758] ACTION //:natives_blob(//build/toolchain/linux:clang_x64)
[15/1758] STAMP obj/natives_blob.stamp
[16/1758] STAMP obj/postmortem-metadata.stamp
[17/1758] CXX obj/v8_libbase/once.o
[18/1758] CXX obj/v8_libbase/logging.o
[19/1758] CXX obj/v8_libbase/page-allocator.o
[20/1758] CXX obj/v8_libbase/condition-variable.o
[21/1758] CXX obj/v8_libbase/mutex.o
[22/1758] CXX obj/v8_libbase/semaphore.o
[23/1758] CXX obj/v8_libbase/time.o
[24/1758] CXX obj/v8_libbase/sys-info.o
[25/1758] CXX obj/v8_libbase/random-number-generator.o
[26/1758] CXX obj/v8_libbase/platform-posix-time.o
[27/1758] CXX obj/v8_libbase/platform-posix.o
[28/1758] CXX obj/v8_libbase/stack_trace_posix.o
[29/1758] STAMP obj/build/config/sanitizers/deps.stamp
[30/1758] CXX obj/build/config/sanitizers/options_sources/sanitizer_options.o
[31/1758] ACTION //:v8_dump_build_config(//build/toolchain/linux:clang_x64)
[32/1758] STAMP obj/v8_dump_build_config.stamp
[33/1758] CXX obj/v8_libbase/platform-linux.o
[34/1758] CXX obj/v8_libplatform/task-queue.o
[35/1758] CXX obj/torque/TorqueBaseVisitor.o
[36/1758] CXX obj/torque/TorqueLexer.o
[37/1758] CXX obj/torque/TorqueVisitor.o
[38/1758] CXX obj/torque/declarable.o
[39/1758] CXX obj/torque/ast-generator.o
[40/1758] CXX obj/torque/declaration-visitor.o
[41/1758] CXX obj/torque/file-visitor.o
[42/1758] CXX obj/torque/declarations.o
[43/1758] CXX obj/torque/scope.o
[44/1758] CXX obj/torque/TorqueParser.o
[45/1758] CXX obj/torque/torque.o
[46/1758] CXX obj/torque/types.o
[47/1758] CXX obj/torque/implementation-visitor.o
[48/1758] CXX obj/torque/utils.o
[49/1758] CXX obj/v8_libplatform/default-foreground-task-runner.o
[50/1758] CXX obj/v8_libplatform/default-platform.o
[51/1758] CXX obj/v8_libplatform/default-worker-threads-task-runner.o
[52/1758] CXX obj/v8_libplatform/trace-config.o
[53/1758] CXX obj/v8_libplatform/trace-object.o
[54/1758] CXX obj/v8_libplatform/trace-buffer.o
[55/1758] CXX obj/v8_libplatform/worker-thread.o
[56/1758] CXX obj/v8_libplatform/trace-writer.o
[57/1758] CXX obj/v8_libplatform/tracing-controller.o
[58/1758] CXX obj/v8_libbase/bits.o
[59/1758] CXX obj/v8_libbase/cpu.o
[60/1758] STAMP obj/v8_version.stamp
[61/1758] STAMP obj/v8_headers.stamp
[62/1758] STAMP obj/build/config/posix/posix.stamp
[63/1758] STAMP obj/build/config/linux/linux.stamp
[64/1758] STAMP obj/build/win/default_exe_manifest.stamp
[65/1758] CXX obj/v8_libsampler/sampler.o
[66/1758] CXX obj/v8_libbase/stack_trace.o
[67/1758] CXX obj/buildtools/third_party/libc++/libc++/any.o
[68/1758] CXX obj/buildtools/third_party/libc++/libc++/bind.o
[69/1758] CXX obj/buildtools/third_party/libc++/libc++/chrono.o
[70/1758] CXX obj/buildtools/third_party/libc++/libc++/condition_variable.o
[71/1758] CXX obj/buildtools/third_party/libc++/libc++/debug.o
[72/1758] CXX obj/buildtools/third_party/libc++/libc++/exception.o
[73/1758] CXX obj/buildtools/third_party/libc++/libc++/algorithm.o
[74/1758] CXX obj/buildtools/third_party/libc++/libc++/functional.o
[75/1758] CXX obj/buildtools/third_party/libc++/libc++/hash.o
[76/1758] CXX obj/buildtools/third_party/libc++/libc++/future.o
[77/1758] CXX obj/buildtools/third_party/libc++/libc++/iostream.o
[78/1758] AR obj/build/config/sanitizers/liboptions_sources.a
[79/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_personality.o
[80/1758] CXX obj/buildtools/third_party/libc++/libc++/ios.o
[81/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_virtual.o
[82/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/fallback_malloc.o
[83/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/private_typeinfo.o
[84/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/stdlib_exception.o
[85/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/stdlib_stdexcept.o
[86/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/stdlib_typeinfo.o
[87/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_unexpected.o
[88/1758] CXX obj/buildtools/third_party/libc++abi/cxa_demangle_stub/cxa_demangle_stub.o
[89/1758] STAMP obj/buildtools/third_party/libc++abi/cxa_demangle_stub.stamp
[90/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/abort_message.o
[91/1758] CXX obj/buildtools/third_party/libc++/libc++/memory.o
[92/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_demangle.o
[93/1758] CXX obj/buildtools/third_party/libc++/libc++/mutex.o
[94/1758] CXX obj/buildtools/third_party/libc++/libc++/new.o
[95/1758] CXX obj/buildtools/third_party/libc++/libc++/optional.o
[96/1758] CXX obj/buildtools/third_party/libc++/libc++/random.o
[97/1758] CXX obj/buildtools/third_party/libc++/libc++/regex.o
[98/1758] CXX obj/buildtools/third_party/libc++/libc++/shared_mutex.o
[99/1758] CXX obj/buildtools/third_party/libc++/libc++/stdexcept.o
[100/1758] CXX obj/buildtools/third_party/libc++/libc++/strstream.o
[101/1758] CXX obj/buildtools/third_party/libc++/libc++/system_error.o
[102/1758] CXX obj/buildtools/third_party/libc++/libc++/locale.o
[103/1758] CXX obj/buildtools/third_party/libc++/libc++/typeinfo.o
[104/1758] CXX obj/buildtools/third_party/libc++/libc++/thread.o
[105/1758] CXX obj/buildtools/third_party/libc++/libc++/utility.o
[106/1758] CXX obj/buildtools/third_party/libc++/libc++/variant.o
[107/1758] CXX obj/buildtools/third_party/libc++/libc++/string.o
[108/1758] CXX obj/buildtools/third_party/libc++/libc++/valarray.o
[109/1758] CXX obj/buildtools/third_party/libc++/libc++/vector.o
[110/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_aux_runtime.o
[111/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_exception.o
[112/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_default_handlers.o
[113/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_guard.o
[114/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_exception_storage.o
[115/1758] ACTION //src/inspector:protocol_compatibility(//build/toolchain/linux:clang_x64)
[116/1758] STAMP obj/src/inspector/protocol_compatibility.stamp
[117/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_handlers.o
[118/1758] ACTION //src/inspector:inspector_injected_script(//build/toolchain/linux:clang_x64)
[119/1758] CXX obj/buildtools/third_party/libc++abi/libc++abi/cxa_vector.o
[120/1758] STAMP obj/buildtools/third_party/libc++abi/libc++abi.stamp
[121/1758] STAMP obj/buildtools/third_party/libc++/libc++.stamp
[122/1758] STAMP obj/build/config/exe_and_shlib_deps.stamp
[123/1758] AR obj/libv8_libbase.a
[124/1758] AR obj/libv8_libplatform.a
[125/1758] STAMP obj/v8_libsampler.stamp
[126/1758] STAMP obj/src/inspector/inspector_injected_script.stamp
[127/1758] CXX obj/testing/gtest/gtest/empty.o
[128/1758] ACTION //test/cctest:resources(//build/toolchain/linux:clang_x64)
[129/1758] STAMP obj/test/cctest/resources.stamp
[130/1758] ACTION //src/inspector:protocol_generated_sources(//build/toolchain/linux:clang_x64)
[131/1758] STAMP obj/src/inspector/protocol_generated_sources.stamp
[132/1758] STAMP obj/src/inspector/inspector.inputdeps.stamp
[133/1758] CXX obj/third_party/antlr4/antlr4/Exceptions.o
[134/1758] CXX obj/third_party/antlr4/antlr4/BufferedTokenStream.o
[135/1758] CXX obj/src/inspector/inspector/Schema.o
[136/1758] CXX obj/src/inspector/inspector/Profiler.o
[137/1758] CXX obj/src/inspector/inspector/remote-object-id.o
[138/1758] CXX obj/src/inspector/inspector/inspected-context.o
[139/1758] CXX obj/src/inspector/inspector/injected-script.o
[140/1758] CXX obj/src/inspector/inspector/string-16.o
[141/1758] CXX obj/src/inspector/inspector/string-util.o
[142/1758] CXX obj/src/inspector/inspector/search-util.o
[143/1758] CXX obj/src/inspector/inspector/v8-console-agent-impl.o
[144/1758] CXX obj/src/inspector/inspector/test-interface.o
[145/1758] CXX obj/src/inspector/inspector/v8-console-message.o
[146/1758] CXX obj/src/inspector/inspector/Console.o
[147/1758] CXX obj/src/inspector/inspector/HeapProfiler.o
[148/1758] CXX obj/src/inspector/inspector/Protocol.o
[149/1758] CXX obj/src/inspector/inspector/Debugger.o
[150/1758] CXX obj/src/inspector/inspector/Runtime.o
[151/1758] CXX obj/src/inspector/inspector/v8-debugger-script.o
[152/1758] CXX obj/src/inspector/inspector/v8-console.o
[153/1758] CXX obj/src/inspector/inspector/v8-function-call.o
[154/1758] CXX obj/src/inspector/inspector/v8-debugger-agent-impl.o
[155/1758] CXX obj/src/inspector/inspector/v8-heap-profiler-agent-impl.o
[156/1758] CXX obj/src/inspector/inspector/v8-debugger.o
[157/1758] CXX obj/src/inspector/inspector/v8-injected-script-host.o
[158/1758] CXX obj/src/inspector/inspector/v8-internal-value-type.o
[159/1758] CXX obj/src/inspector/inspector/v8-inspector-session-impl.o
[160/1758] CXX obj/src/inspector/inspector/v8-inspector-impl.o
[161/1758] CXX obj/src/inspector/inspector/v8-regex.o
[162/1758] CXX obj/src/inspector/inspector/v8-profiler-agent-impl.o
[163/1758] CXX obj/src/inspector/inspector/v8-schema-agent-impl.o
[164/1758] CXX obj/src/inspector/inspector/v8-runtime-agent-impl.o
[165/1758] CXX obj/src/inspector/inspector/v8-value-utils.o
[166/1758] CXX obj/src/inspector/inspector/v8-stack-trace-impl.o
[167/1758] CXX obj/third_party/antlr4/antlr4/CommonTokenFactory.o
[168/1758] CXX obj/third_party/antlr4/antlr4/CommonToken.o
[169/1758] CXX obj/third_party/antlr4/antlr4/ConsoleErrorListener.o
[170/1758] CXX obj/third_party/antlr4/antlr4/CommonTokenStream.o
[171/1758] CXX obj/src/inspector/inspector/wasm-translation.o
[172/1758] STAMP obj/src/inspector/inspector.stamp
[173/1758] CXX obj/third_party/antlr4/antlr4/DefaultErrorStrategy.o
[174/1758] CXX obj/third_party/antlr4/antlr4/DiagnosticErrorListener.o
[175/1758] CXX obj/third_party/antlr4/antlr4/CharStream.o
[176/1758] CXX obj/third_party/antlr4/antlr4/IntStream.o
[177/1758] CXX obj/third_party/antlr4/antlr4/ANTLRErrorStrategy.o
[178/1758] CXX obj/third_party/antlr4/antlr4/ANTLRErrorListener.o
[179/1758] CXX obj/third_party/antlr4/antlr4/ANTLRFileStream.o
[180/1758] CXX obj/third_party/antlr4/antlr4/BailErrorStrategy.o
[181/1758] CXX obj/third_party/antlr4/antlr4/ANTLRInputStream.o
[182/1758] CXX obj/third_party/antlr4/antlr4/BaseErrorListener.o
[183/1758] CXX obj/third_party/antlr4/antlr4/TokenSource.o
[184/1758] CXX obj/third_party/antlr4/antlr4/TokenStream.o
[185/1758] CXX obj/third_party/antlr4/antlr4/UnbufferedCharStream.o
[186/1758] CXX obj/third_party/antlr4/antlr4/UnbufferedTokenStream.o
[187/1758] CXX obj/third_party/antlr4/antlr4/TokenStreamRewriter.o
[188/1758] CXX obj/third_party/antlr4/antlr4/WritableToken.o
[189/1758] CXX obj/third_party/antlr4/antlr4/ATNDeserializationOptions.o
[190/1758] CXX obj/third_party/antlr4/antlr4/ATN.o
[191/1758] CXX obj/third_party/antlr4/antlr4/ATNConfig.o
[192/1758] CXX obj/third_party/antlr4/antlr4/AbstractPredicateTransition.o
[193/1758] CXX obj/third_party/antlr4/antlr4/ATNConfigSet.o
[194/1758] CXX obj/third_party/antlr4/antlr4/ATNSimulator.o
[195/1758] CXX obj/third_party/antlr4/antlr4/ATNSerializer.o
[196/1758] CXX obj/third_party/antlr4/antlr4/ATNDeserializer.o
[197/1758] CXX obj/third_party/antlr4/antlr4/ATNState.o
[198/1758] CXX obj/third_party/antlr4/antlr4/ActionTransition.o
[199/1758] CXX obj/third_party/antlr4/antlr4/LexerIndexedCustomAction.o
[200/1758] CXX obj/third_party/antlr4/antlr4/AmbiguityInfo.o
[201/1758] CXX obj/third_party/antlr4/antlr4/AtomTransition.o
[202/1758] CXX obj/third_party/antlr4/antlr4/ArrayPredictionContext.o
[203/1758] CXX obj/third_party/antlr4/antlr4/BasicBlockStartState.o
[204/1758] CXX obj/third_party/antlr4/antlr4/BasicState.o
[205/1758] CXX obj/third_party/antlr4/antlr4/BlockStartState.o
[206/1758] CXX obj/third_party/antlr4/antlr4/BlockEndState.o
[207/1758] CXX obj/third_party/antlr4/antlr4/ContextSensitivityInfo.o
[208/1758] CXX obj/third_party/antlr4/antlr4/DecisionEventInfo.o
[209/1758] CXX obj/third_party/antlr4/antlr4/DecisionInfo.o
[210/1758] CXX obj/third_party/antlr4/antlr4/DecisionState.o
[211/1758] CXX obj/third_party/antlr4/antlr4/FailedPredicateException.o
[212/1758] CXX obj/third_party/antlr4/antlr4/InputMismatchException.o
[213/1758] CXX obj/third_party/antlr4/antlr4/InterpreterRuleContext.o
[214/1758] CXX obj/third_party/antlr4/antlr4/Lexer.o
[215/1758] CXX obj/third_party/antlr4/antlr4/Parser.o
[216/1758] CXX obj/third_party/antlr4/antlr4/LexerInterpreter.o
[217/1758] CXX obj/third_party/antlr4/antlr4/LexerNoViableAltException.o
[218/1758] CXX obj/third_party/antlr4/antlr4/ListTokenSource.o
[219/1758] CXX obj/third_party/antlr4/antlr4/NoViableAltException.o
[220/1758] CXX obj/third_party/antlr4/antlr4/Recognizer.o
[221/1758] CXX obj/third_party/antlr4/antlr4/ParserRuleContext.o
[222/1758] CXX obj/third_party/antlr4/antlr4/ParserInterpreter.o
[223/1758] CXX obj/third_party/antlr4/antlr4/ProxyErrorListener.o
[224/1758] CXX obj/third_party/antlr4/antlr4/RecognitionException.o
[225/1758] CXX obj/third_party/antlr4/antlr4/Token.o
[226/1758] CXX obj/third_party/antlr4/antlr4/RuleContextWithAltNum.o
[227/1758] CXX obj/third_party/antlr4/antlr4/RuleContext.o
[228/1758] CXX obj/third_party/antlr4/antlr4/RuntimeMetaData.o
[229/1758] CXX obj/third_party/antlr4/antlr4/EmptyPredictionContext.o
[230/1758] CXX obj/third_party/antlr4/antlr4/Vocabulary.o
[231/1758] CXX obj/third_party/antlr4/antlr4/EpsilonTransition.o
[232/1758] CXX obj/third_party/antlr4/antlr4/ErrorInfo.o
[233/1758] CXX obj/third_party/antlr4/antlr4/LexerATNConfig.o
[234/1758] CXX obj/third_party/antlr4/antlr4/LL1Analyzer.o
[235/1758] CXX obj/third_party/antlr4/antlr4/LexerAction.o
[236/1758] CXX obj/third_party/antlr4/antlr4/LexerActionExecutor.o
[237/1758] CXX obj/third_party/antlr4/antlr4/LexerChannelAction.o
[238/1758] CXX obj/third_party/antlr4/antlr4/LexerATNSimulator.o
[239/1758] CXX obj/third_party/antlr4/antlr4/PrecedencePredicateTransition.o
[240/1758] CXX obj/third_party/antlr4/antlr4/LexerCustomAction.o
[241/1758] CXX obj/third_party/antlr4/antlr4/LexerModeAction.o
[242/1758] CXX obj/third_party/antlr4/antlr4/LexerPopModeAction.o
[243/1758] CXX obj/third_party/antlr4/antlr4/LexerPushModeAction.o
[244/1758] CXX obj/third_party/antlr4/antlr4/LexerMoreAction.o
[245/1758] CXX obj/third_party/antlr4/antlr4/LexerSkipAction.o
[246/1758] CXX obj/third_party/antlr4/antlr4/LexerTypeAction.o
[247/1758] CXX obj/third_party/antlr4/antlr4/LookaheadEventInfo.o
[248/1758] CXX obj/third_party/antlr4/antlr4/LoopEndState.o
[249/1758] CXX obj/third_party/antlr4/antlr4/OrderedATNConfigSet.o
[250/1758] CXX obj/third_party/antlr4/antlr4/NotSetTransition.o
[251/1758] CXX obj/third_party/antlr4/antlr4/ParseInfo.o
[252/1758] CXX obj/third_party/antlr4/antlr4/PlusBlockStartState.o
[253/1758] CXX obj/third_party/antlr4/antlr4/PlusLoopbackState.o
[254/1758] CXX obj/third_party/antlr4/antlr4/SingletonPredictionContext.o
[255/1758] CXX obj/third_party/antlr4/antlr4/PredicateEvalInfo.o
[256/1758] CXX obj/third_party/antlr4/antlr4/PredicateTransition.o
[257/1758] CXX obj/third_party/antlr4/antlr4/ParserATNSimulator.o
[258/1758] CXX obj/third_party/antlr4/antlr4/PredictionMode.o
[259/1758] CXX obj/third_party/antlr4/antlr4/ProfilingATNSimulator.o
[260/1758] CXX obj/third_party/antlr4/antlr4/RangeTransition.o
[261/1758] CXX obj/third_party/antlr4/antlr4/PredictionContext.o
[262/1758] CXX obj/third_party/antlr4/antlr4/RuleStartState.o
[263/1758] CXX obj/third_party/antlr4/antlr4/RuleStopState.o
[264/1758] CXX obj/third_party/antlr4/antlr4/RuleTransition.o
[265/1758] CXX obj/third_party/antlr4/antlr4/SetTransition.o
[266/1758] CXX obj/third_party/antlr4/antlr4/StarBlockStartState.o
[267/1758] CXX obj/third_party/antlr4/antlr4/SemanticContext.o
[268/1758] CXX obj/third_party/antlr4/antlr4/DFA.o
[269/1758] CXX obj/third_party/antlr4/antlr4/StarLoopbackState.o
[270/1758] CXX obj/third_party/antlr4/antlr4/StarLoopEntryState.o
[271/1758] CXX obj/third_party/antlr4/antlr4/TokensStartState.o
[272/1758] CXX obj/third_party/antlr4/antlr4/WildcardTransition.o
[273/1758] CXX obj/third_party/antlr4/antlr4/Transition.o
[274/1758] CXX obj/third_party/antlr4/antlr4/IterativeParseTreeWalker.o
[275/1758] CXX obj/third_party/antlr4/antlr4/DFASerializer.o
[276/1758] CXX obj/third_party/antlr4/antlr4/LexerDFASerializer.o
[277/1758] CXX obj/third_party/antlr4/antlr4/DFAState.o
[278/1758] CXX obj/third_party/antlr4/antlr4/Interval.o
[279/1758] CXX obj/third_party/antlr4/antlr4/InterpreterDataReader.o
[280/1758] CXX obj/third_party/antlr4/antlr4/MurmurHash.o
[281/1758] CXX obj/third_party/antlr4/antlr4/IntervalSet.o
[282/1758] CXX obj/third_party/antlr4/antlr4/Predicate.o
[283/1758] CXX obj/third_party/antlr4/antlr4/Any.o
[284/1758] CXX obj/third_party/antlr4/antlr4/Arrays.o
[285/1758] CXX obj/third_party/antlr4/antlr4/StringUtils.o
[286/1758] CXX obj/third_party/antlr4/antlr4/guid.o
[287/1758] CXX obj/third_party/antlr4/antlr4/CPPUtils.o
[288/1758] CXX obj/third_party/antlr4/antlr4/ErrorNode.o
[289/1758] CXX obj/third_party/antlr4/antlr4/ErrorNodeImpl.o
[290/1758] CXX obj/third_party/antlr4/antlr4/ParseTree.o
[291/1758] CXX obj/third_party/antlr4/antlr4/ParseTreeListener.o
[292/1758] CXX obj/third_party/antlr4/antlr4/Trees.o
[293/1758] CXX obj/third_party/antlr4/antlr4/ParseTreeVisitor.o
[294/1758] CXX obj/third_party/antlr4/antlr4/ParseTreeWalker.o
[295/1758] CXX obj/third_party/antlr4/antlr4/TerminalNodeImpl.o
[296/1758] CXX obj/third_party/antlr4/antlr4/TerminalNode.o
[297/1758] CXX obj/third_party/antlr4/antlr4/Chunk.o
[298/1758] CXX obj/third_party/antlr4/antlr4/ParseTreeMatch.o
[299/1758] CXX obj/third_party/antlr4/antlr4/ParseTreePattern.o
[300/1758] CXX obj/third_party/antlr4/antlr4/XPathLexerErrorListener.o
[301/1758] CXX obj/third_party/antlr4/antlr4/RuleTagToken.o
[302/1758] CXX obj/third_party/antlr4/antlr4/TagChunk.o
[303/1758] CXX obj/third_party/antlr4/antlr4/ParseTreePatternMatcher.o
[304/1758] CXX obj/third_party/antlr4/antlr4/TextChunk.o
[305/1758] CXX obj/third_party/antlr4/antlr4/TokenTagToken.o
[306/1758] CXX obj/third_party/antlr4/antlr4/XPathElement.o
[307/1758] CXX obj/third_party/antlr4/antlr4/XPath.o
[308/1758] CXX obj/third_party/antlr4/antlr4/XPathRuleAnywhereElement.o
[309/1758] CXX obj/third_party/antlr4/antlr4/XPathRuleElement.o
[310/1758] CXX obj/third_party/antlr4/antlr4/XPathLexer.o
[311/1758] CXX obj/third_party/antlr4/antlr4/XPathTokenAnywhereElement.o
[312/1758] CXX obj/third_party/antlr4/antlr4/XPathWildcardAnywhereElement.o
[313/1758] CXX obj/third_party/antlr4/antlr4/XPathTokenElement.o
[314/1758] CXX obj/third_party/antlr4/antlr4/XPathWildcardElement.o
[315/1758] STAMP obj/third_party/antlr4/antlr4.stamp
[316/1758] LINK ./torque
[317/1758] ACTION //:run_torque(//build/toolchain/linux:clang_x64)
[318/1758] STAMP obj/run_torque.stamp
[319/1758] STAMP obj/lib_wasm_fuzzer_common.inputdeps.stamp
[320/1758] CXX obj/third_party/googletest/gmock/gmock-cardinalities.o
[321/1758] STAMP obj/torque_generated_initializers.inputdeps.stamp
[322/1758] CXX obj/third_party/googletest/gmock/gmock-internal-utils.o
[323/1758] CXX obj/lib_wasm_fuzzer_common/wasm-fuzzer-common.o
[324/1758] CXX obj/torque_generated_initializers/builtins-test-from-dsl-gen.o
[325/1758] CXX obj/torque_generated_initializers/builtins-typed-array-from-dsl-gen.o
[326/1758] STAMP obj/torque_generated_core.stamp
[327/1758] STAMP obj/lib_wasm_fuzzer_common.stamp
[328/1758] STAMP obj/wasm_module_runner.inputdeps.stamp
[329/1758] CXX obj/torque_generated_initializers/builtins-base-from-dsl-gen.o
[330/1758] CXX obj/wasm_module_runner/wasm-module-runner.o
[331/1758] STAMP obj/wasm_module_runner.stamp
[332/1758] CXX obj/torque_generated_initializers/builtins-array-from-dsl-gen.o
[333/1758] STAMP obj/torque_generated_initializers.stamp
[334/1758] CXX obj/third_party/googletest/gmock/gmock.o
[335/1758] CXX obj/third_party/googletest/gtest/gtest-port.o
[336/1758] CXX obj/third_party/googletest/gtest/gtest-death-test.o
[337/1758] CXX obj/third_party/googletest/gtest/gtest-filepath.o
[338/1758] CXX obj/third_party/googletest/gmock_main/gmock_main.o
[339/1758] CXX obj/third_party/googletest/gtest/gtest-printers.o
[340/1758] CXX obj/third_party/googletest/gtest/gtest-test-part.o
[341/1758] CXX obj/third_party/googletest/gtest/gtest-typed-test.o
[342/1758] COPY ../../third_party/icu/common/icudtl.dat icudtl.dat
[343/1758] STAMP obj/third_party/icu/icudata.stamp
[344/1758] STAMP obj/d8.inputdeps.stamp
[345/1758] CXX obj/v8_simple_wasm_imports_section_fuzzer/fuzzer.o
[346/1758] CXX obj/third_party/googletest/gtest_main/gtest_main.o
[347/1758] CXX obj/d8/d8-js.o
[348/1758] CXX obj/d8/d8-console.o
[349/1758] CXX obj/third_party/googletest/gtest/gtest.o
[350/1758] CXX obj/d8/d8-posix.o
[351/1758] CXX obj/mksnapshot/mksnapshot.o
[352/1758] CXX obj/json_fuzzer/json.o
[353/1758] STAMP obj/fuzzer_support.inputdeps.stamp
[354/1758] CXX obj/fuzzer_support/fuzzer-support.o
[355/1758] STAMP obj/regexp_builtins_fuzzer.inputdeps.stamp
[356/1758] CXX obj/parser_fuzzer/parser.o
[357/1758] CXX obj/d8/d8.o
[358/1758] CXX obj/regexp_fuzzer/regexp.o
[359/1758] CXX obj/v8_simple_wasm_fuzzer/fuzzer.o
[360/1758] STAMP obj/v8_base.inputdeps.stamp
[361/1758] CXX obj/regexp_builtins_fuzzer/regexp-builtins.o
[362/1758] CXX obj/v8_base/builtins-promise.o
[363/1758] CXX obj/multi_return_fuzzer/multi-return.o
[364/1758] CXX obj/v8_base/builtins-reflect.o
[365/1758] CXX obj/v8_base/builtins-sharedarraybuffer.o
[366/1758] CXX obj/v8_base/builtins-regexp.o
[367/1758] CXX obj/v8_base/builtins-string.o
[368/1758] CXX obj/v8_base/builtins-typed-array.o
[369/1758] CXX obj/v8_base/builtins-symbol.o
[370/1758] CXX obj/v8_base/builtins.o
[371/1758] CXX obj/v8_base/deoptimize-reason.o
[372/1758] CXX obj/v8_base/constants-table-builder.o
[373/1758] CXX obj/v8_base/liveedit.o
[374/1758] CXX obj/v8_base/diy-fp.o
[375/1758] CXX obj/v8_base/cached-powers.o
[376/1758] CXX obj/v8_base/disassembler.o
[377/1758] CXX obj/v8_base/char-predicates.o
[378/1758] CXX obj/v8_base/cancelable-task.o
[379/1758] CXX obj/v8_base/deoptimizer.o
[380/1758] CXX obj/v8_base/code-factory.o
[381/1758] CXX obj/v8_base/code-reference.o
[382/1758] CXX obj/v8_base/codegen.o
[383/1758] CXX obj/v8_base/compilation-cache.o
[384/1758] CXX obj/v8_base/code-stubs.o
[385/1758] CXX obj/v8_base/compilation-statistics.o
[386/1758] CXX obj/v8_base/compiler-dispatcher-job.o
[387/1758] CXX obj/v8_base/compilation-dependencies.o
[388/1758] CXX obj/v8_base/compiler-dispatcher-tracer.o
[389/1758] CXX obj/v8_base/code-stub-assembler.o
[390/1758] CXX obj/v8_base/optimizing-compile-dispatcher.o
[391/1758] CXX obj/v8_base/compiler-dispatcher.o
[392/1758] CXX obj/v8_base/access-builder.o
[393/1758] CXX obj/v8_base/unoptimized-compile-job.o
[394/1758] CXX obj/v8_base/all-nodes.o
[395/1758] CXX obj/v8_base/compiler.o
[396/1758] CXX obj/v8_base/branch-elimination.o
[397/1758] CXX obj/v8_base/access-info.o
[398/1758] CXX obj/v8_base/basic-block-instrumentor.o
[399/1758] CXX obj/v8_base/bytecode-liveness-map.o
[400/1758] CXX obj/v8_base/bytecode-analysis.o
[401/1758] CXX obj/v8_base/allocation.o
[402/1758] CXX obj/v8_base/c-linkage.o
[403/1758] CXX obj/v8_base/bytecode-graph-builder.o
[404/1758] CXX obj/v8_base/api-natives.o
[405/1758] CXX obj/v8_base/wasm-v8-lowlevel.o
FAILED: obj/v8_base/wasm-v8-lowlevel.o
../../third_party/llvm-build/Release+Asserts/bin/clang++ -MMD -MF obj/v8_base/wasm-v8-lowlevel.o.d -DV8_DEPRECATION_WARNINGS -DUSE_UDEV -DUSE_AURA=1 -DUSE_GLIB=1 -DUSE_NSS_CERTS=1 -DUSE_X11=1 -DFULL_SAFE_BROWSING -DSAFE_BROWSING_CSD -DSAFE_BROWSING_DB_LOCAL -DCHROMIUM_BUILD -DFIELDTRIAL_TESTING_ENABLED -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -DCR_CLANG_REVISION=\"332838-1\" -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS -DCR_LIBCXX_REVISION=332543 -DCR_LIBCXXABI_REVISION=331450 -DCR_SYSROOT_HASH=4e7db513b0faeea8fb410f70c9909e8736f5c0ab -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -DV8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=64 -DENABLE_GDB_JIT_INTERFACE -DENABLE_MINOR_MC -DV8_INTL_SUPPORT -DV8_USE_SNAPSHOT -DV8_USE_EXTERNAL_STARTUP_DATA -DV8_CONCURRENT_MARKING -DV8_MULTI_SNAPSHOTS -DV8_TARGET_ARCH_X64 -DU_USING_ICU_NAMESPACE=0 -DU_ENABLE_DYLOAD=0 -DU_STATIC_IMPLEMENTATION -DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE -DUCHAR_TYPE=uint16_t -I../.. -Igen -I../.. -Igen -I../../third_party/icu/source/common -I../../third_party/icu/source/i18n -I../../include -fno-strict-aliasing --param=ssp-buffer-size=4 -fstack-protector -Wno-builtin-macro-redefined -D__DATE__= -D__TIME__= -D__TIMESTAMP__= -funwind-tables -fPIC -pipe -B../../third_party/binutils/Linux_x64/Release/bin -pthread -fcolor-diagnostics -fmerge-all-constants -Xclang -mllvm -Xclang -instcombine-lower-dbg-declare=0 -no-canonical-prefixes -m64 -march=x86-64 -Wall -Werror -Wextra -Wimplicit-fallthrough -Wthread-safety -Wno-missing-field-initializers -Wno-unused-parameter -Wno-c++11-narrowing -Wno-covered-switch-default -Wno-unneeded-internal-declaration -Wno-undefined-var-template -Wno-nonportable-include-path -Wno-address-of-packed-member -Wno-unused-lambda-capture -Wno-user-defined-warnings -Wno-enum-compare-switch -Wno-null-pointer-arithmetic -Wno-ignored-pragma-optimize -fno-omit-frame-pointer -g0 -fvisibility=hidden -Wheader-hygiene -Wstring-conversion -Wtautological-overlap-compare -Wmissing-field-initializers -Winconsistent-missing-override -Wunreachable-code -Wshorten-64-to-32 -O3 -fno-ident -fdata-sections -ffunction-sections -std=gnu++14 -fno-exceptions -fno-rtti -nostdinc++ -isystem../../buildtools/third_party/libc++/trunk/include -isystem../../buildtools/third_party/libc++abi/trunk/include --sysroot=../../build/linux/debian_sid_amd64-sysroot -fvisibility-inlines-hidden -c ../../src/wasm-v8-lowlevel.cc -o obj/v8_base/wasm-v8-lowlevel.o
../../src/wasm-v8-lowlevel.cc:66:1: error: control may reach end of non-void function [-Werror,-Wreturn-type]
}
^
../../src/wasm-v8-lowlevel.cc:181:1: error: control may reach end of non-void function [-Werror,-Wreturn-type]
}
^
2 errors generated.
[406/1758] CXX obj/v8_base/arguments.o
[407/1758] CXX obj/v8_base/api.o
ninja: build stopped: subcommand failed.
make: *** [v8] Error 1
Makefile:102: recipe for target 'v8' failed
The command '/bin/sh -c make v8-checkout && make -j v8' returned a non-zero code: 2

Add ability to pause/resume execution.

This might be V8 specific, but the current API seems to be designed around short-lived and non-overlapping Stores, where v8::Isolate is Enter()'ed upon creation, and Exit()'ed during destruction.

For long-lived Stores (e.g. WASM extensions in HTTP proxies), which can be created and destroyed at arbitrary times, this means jumping between Stores without explicit context switching (which might be safe?) and Enter() / Exit() calls in no particular order, e.g.:

auto store1 = wasm::Store::make(engine.get());  // store1->isolate()->Enter();
auto store2 = wasm::Store::make(engine.get());  // store2->isolate()->Enter();
store1.reset();                                 // store1->isolate()->Exit();

which trigger this DCHECK when V8 is built with is_debug=true:

DCHECK(CurrentPerIsolateThreadData()->isolate_ == this);

@jakobkummerow suggested wasm::Store::pause() and wasm::Store::resume() as possible APIs.

If we don't want to expose this at the API level, then we could do explicit Enter() / Exit() on each function call inside the library, but that sounds expensive.

Any thoughts, @rossberg?

Header guard uses a reserved identifier

lex.name/3.1:

Each identifier that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.

The header guard should not use __WASM_HH.

Build v8 error: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found

make v8:

[root@iZrj9d82e7n0tt9r616mvxZ wasm-c-api]# make v8
if ! grep wasm-v8-lowlevel v8/v8/BUILD.gn; then \
  cp v8/v8/BUILD.gn v8/v8/BUILD.gn.save; \
  cd v8/v8; \
  patch < ../../patch/0001-BUILD.gn-add-wasm-v8-lowlevel.patch; \
fi
patching file BUILD.gn
Hunk #1 succeeded at 1555 with fuzz 2 (offset 431 lines).
Hunk #2 succeeded at 1606 with fuzz 2 (offset 455 lines).
Hunk #3 succeeded at 1622 with fuzz 2 (offset 456 lines).
==== Building V8 branch-heads/7.4 x64.release ====
(cd v8/v8; PATH=/root/code/wasmer-c-api/wasm-c-api/v8/depot_tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin tools/dev/v8gen.py x64.release -- is_component_build=false v8_static_library=true v8_monolithic=true v8_use_external_startup_data=false v8_enable_i18n_support=false use_custom_libcxx=false use_custom_libcxx_for_host=false)
(cd v8/v8; PATH=/root/code/wasmer-c-api/wasm-c-api/v8/depot_tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin ninja -C out.gn/x64.release)
ninja: Entering directory `out.gn/x64.release'
[1/1] Regenerating ninja files
[1/1] Regenerating ninja files
[1/1] Regenerating ninja files
[1/1] Regenerating ninja files
[89/1211] ACTION //:generate_bytecode_builtins_list(//build/toolchain/linux:clang_x64)
FAILED: gen/builtins-generated/bytecodes-builtins-list.h 
python ../../tools/run.py ./bytecode_builtins_list_generator gen/builtins-generated/bytecodes-builtins-list.h
./bytecode_builtins_list_generator: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./bytecode_builtins_list_generator)
[94/1211] CXX obj/torque_base/torque-parser.o
ninja: build stopped: subcommand failed.
make: *** [v8-build] Error 1

It seem's that bytecode_builtins_list_generator is compiled by --sysroot=../../build/linux/debian_sid_amd64-sysroot which contain the newer so but I'm not prettey sure. How to make it work on my Centos7.2 ?

System information:

[root@iZrj9d82e7n0tt9r616mvxZ wasm-c-api]# uname -a
Linux iZrj9d82e7n0tt9r616mvxZ 3.10.0-514.26.2.el7.x86_64 #1 SMP Tue Jul 4 15:04:05 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

[root@iZrj9d82e7n0tt9r616mvxZ wasm-c-api]# gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


[root@iZrj9d82e7n0tt9r616mvxZ wasm-c-api]# strings /lib64/libstdc++.so.6 | grep GLIB
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19
GLIBC_2.3
GLIBC_2.2.5
GLIBC_2.14
GLIBC_2.4
GLIBC_2.3.2
GLIBCXX_DEBUG_MESSAGE_LENGTH

Threading example broken

Works here:
3a103e8

But crashes here:
0eab50a

Backtrace from lldb:

* thread #2, name = 'threads', stop reason = signal SIGILL: illegal instruction operand
  * frame #0: 0x00007ffff77a97e2 libwasm_v8.so`v8::base::OS::Abort() + 18
    frame #1: 0x00007ffff722222a libwasm_v8.so`v8::internal::LookupIterator::GetRootForNonJSReceiver(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, unsigned int) + 218
    frame #2: 0x00007ffff701f37a libwasm_v8.so`v8::internal::LookupIterator::LookupIterator(v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Name>, v8::internal::LookupIterator::Configuration) + 90
    frame #3: 0x00007ffff72219fd libwasm_v8.so`v8::internal::LookupIterator::PropertyOrElement(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, bool*, v8::internal::LookupIterator::Configuration) + 589
    frame #4: 0x00007ffff735d6ec libwasm_v8.so`v8::internal::Runtime::GetObjectProperty(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, bool*) + 76
    frame #5: 0x00007ffff6fe0402 libwasm_v8.so`v8::Object::Get(v8::Local<v8::Context>, v8::Local<v8::Value>) + 466
    frame #6: 0x00007ffff6fb9978 libwasm_v8.so`wasm::(anonymous namespace)::make_func(wasm::Store*, wasm::FuncData*) + 2232
    frame #7: 0x00007ffff6fba1f0 libwasm_v8.so`wasm::Func::make(wasm::Store*, wasm::FuncType const*, wasm::Result (*)(void*, wasm::vec<wasm::Val> const&), void*, void (*)(void*)) + 160
    frame #8: 0x00007ffff6fa151a libwasm_v8.so`wasm_func_new + 122
    frame #9: 0x0000000000401397 threads`run + 183
    frame #10: 0x00007ffff6c8d6db libpthread.so.0`start_thread + 219
    frame #11: 0x00007ffff69b688f libc.so.6`clone + 63

Unsized imports array in wasm_instance_new.

Currently wasm_instance_new has the signature:

own wasm_instance_t* wasm_instance_new(
  wasm_store_t*,
  const wasm_module_t*,
  const wasm_extern_t* const imports[],
  own wasm_trap_t**
);

The imports array is unsized (i.e. there is no corresponding parameter to denote the length of the array). This means that if the length of the imports for the module being instantiated does not match the length of the given imports array, a runtime has no way of failing the instantiation other than undefined behavior (e.g. a segfault).

A runtime needs to blindly index into the imports parameter based on the imports in the module being instantiated. If an imports_length parameter were added to wasm_instance_new, a runtime would be able to detect the mismatch and potentially return a trap result instead of invoking undefined behavior.

Alternatively, wasm_module_imports could be called to get the module's imports and ensure the count is correct prior to instantiating, but it's likely pretty easy for the runtime implementation to check the internal representation of the module's import length against a parameter than forcing users of the C API to alloc a vec of imports just to perform this check.

C++ opaque handle implementation is based on undefined behaviour

basic.lval/11:

If a program attempts to access the stored value of an object through a glvalue whose type is not similar ([conv.qual]) to one of the following types the behavior is undefined:52

  • the dynamic type of the object,
  • a type that is the signed or unsigned type corresponding to the dynamic type of the object, or
  • a char, unsigned char, or std​::​byte type.

The implementation of opaque handles dynamically allocates an object of one type and casts it to an unrelated type. Accessing the object through a pointer to one of the API types (e.g. in order to call copy or kind) is then undefined behaviour.

Is there documentation somewhere which outlines the use of this strategy as opposed to inheritence- or composition-based ones which don't break this rule? I realise that it may work on compilers which this has been tested with, but it seems somewhat risky to mandate UB through the interface, as implementations may change, or this may trigger sanitizer fails.

Unconditional move of forwarding reference

In vec::make:

  template<class... Ts>
  static auto make(Ts&&... args) -> vec {
    T data[] = { std::move(args)... };
    return make(sizeof...(Ts), data);
  }

The std::move(args)... should be std::forward<Args>(args)..., otherwise it will move from non-const lvalue reference arguments.

What are Foreigns good for?

The current definition of Foreign seems very minimal:

class Foreign : public Ref {
public:
  Foreign() = delete;
  ~Foreign();

  static auto make(Store*) -> own<Foreign*>;
  auto copy() const -> own<Foreign*>;
};

And there are no examples using them. What are they useful for? Are they supposed to wrap a value of some sort? Are they a work in progress and will be expanded later?

A mechanism for flags initialization

The API currently has no way to set the underlying engine's command-line arguments. These arguments are useful to enable/disable different performance, debugging and tracing options, such as the tiering strategy, trace output, etc.

The V8 API has the following:

  static void SetFlagsFromCommandLine(int* argc,
                                      char** argv,
                                      bool remove_flags);

While of course being engine-specific, this can still be useful.

Add support for `v128`

As I was working on bytecodealliance/wasmtime#330 I ran into some build issues due to the lack of v128 support in this library. I do have changes ready for supporting this new type but thought it best to discuss in an issue before opening a PR.

To add support for v128, my changes to wasm.h would consist of:

  • adding typedef __uint128_t v128_t; (it is debatable whether __uint128_t is the right type to use here)
  • adding a v128_t v128 field to the wasm_val_t union for storing the v128 bytes (any concerns with endianness?)
  • adding WASM_V128 to the wasm_valkind_enum for identifying the new type

Would this be sufficient to add the v128 type?

Use clang-format to format API code

This would make it much easier for collaborators to ensure their changes have formatting that is consistent with the rest of the repo.

I'm locally using a .clang-format that just contains BasedOnStyle: Chromium, which is reasonably close to the existing code, but not perfect. Ideally @rossberg could add a .clang-format based on his preferences, and apply it to the existing code.

A simple way to expose some C lib to wasm?

I'd like to be able to expose some C lib to wasm.
It looks like I have to write a callback for every C function I want to expose.
Is there some automated process for that?
Or are there at least some rules, how to write these for general function arguments?

How to run wasm file compiled from C/C++

The wasm examples under exapmle/seem are written by s-expression(wat). I try to load a wasm file compiled from C but fail to load it.
C source code

#include <stdio.h>

int nonce(int argc, char ** argv)
{
        printf("hello text\n");
        return 0;
}
emcc 1.c "EXPORTED_FUNCTIONS=['_nonce']" -o 1.wasm

load fail (1c.c refers the exapmle/hello.c and load 1.wasm)

    #0 0x55e0cec40ba4 in wasm::Instance::make(wasm::Store*, wasm::Module const*, wasm::Extern const* const*) src/wasm-v8.cc:2147
    #1 0x55e0cec415ef in wasm_instance_new src/wasm-c.cc:1008
    #2 0x55e0cec038da in main /root/v8/wasm-c-api/1c.c:46
    #3 0x7f8559348b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #4 0x55e0cec03579 in _start (/root/v8/wasm-c-api/1-c+0x9f579)

I follow the source wasm::Instance::make code and find the wasm file (1.wasm) compiled from C needs a lot of import even the C source is just a simple function.

Is there such a possibility to load a wasm file compiled from C/C++ whose functions (glibc functions or the custom functions) are defined at the host env ?

For me, I just want some dangerous logic run in virtual machine(V8) for not populating the host env but this logic code may use the function(symbol) from the host env.

Why -fsanitize=address is needed

I find I have to use -fsanitize=address when building this project otherwise some link error will be outputted like this :

root/v8/wasm-c-api/src/wasm-c.cc:674: undefined reference to `__asan_report_load8'
/root/v8/wasm-c-api/src/wasm-c.cc:674: undefined reference to `__asan_report_load8'

I have successfully embedded wasm-c-api into Nginx as a binary but Nginx does not clean memory it have already alloced if it tend to exit certainly like doing -s reload.
Something error will be outputted like this:

=================================================================
==585==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 1024 byte(s) in 1 object(s) allocated from:
    #0 0x7f304b9947a0 in posix_memalign (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdf7a0)
    #1 0x5651983ae4d0 in ngx_memalign src/os/unix/ngx_alloc.c:76

SUMMARY: AddressSanitizer: 1024 byte(s) leaked in 1 allocation(s).

All in all, how could I disable -fsanitize=addres ? I think it's ungraceful output for some operation.

make v8 error

Seems make v8-checkout is successful while make v8 not.

make v8-checkout:

root@iZrj97ibqurmwnu9mj5htdZ:~/v8/wasm-c-api# make v8-checkout
==== Checking out V8 branch-heads/7.4 ====
(cd v8/v8; git checkout -f master)
Previous HEAD position was 8a28642518 Version 7.4.288.28
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
(cd v8/v8; git pull)
Already up to date.
(cd v8/v8; git checkout branch-heads/7.4)
Note: checking out 'branch-heads/7.4'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 8a28642518 Version 7.4.288.28
(cd v8/v8; PATH=/root/v8/wasm-c-api/v8/depot_tools:/root/wasm/emsdk:/root/wasm/emsdk/fastcomp/emscripten:/root/wasm/emsdk/node/8.9.1_64bit/bin:/root/.wasmer/bin:/root/.wasmer/globals/wapm_packages/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/root/llvm/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04/bin:/root/wavm/WAVM/bin:/root/bin gclient sync)
Running depot tools as root is sad.
Syncing projects: 100% (24/24), done.

WARNING: 'v8/third_party/perfetto' is no longer part of this client.
It is recommended that you manually remove it or use 'gclient sync -D' next time.

WARNING: 'v8/third_party/protobuf' is no longer part of this client.
It is recommended that you manually remove it or use 'gclient sync -D' next time.
mkdir -p v8/v8/out.gn/x64.release
echo >v8/v8/out.gn/x64.release/version branch-heads/7.4

make v8:

root@iZrj97ibqurmwnu9mj5htdZ:~/v8/wasm-c-api# make v8
if ! grep wasm-v8-lowlevel v8/v8/BUILD.gn; then \
  cp v8/v8/BUILD.gn v8/v8/BUILD.gn.save; \
  cd v8/v8; \
  patch < ../../patch/0001-BUILD.gn-add-wasm-v8-lowlevel.patch; \
fi
patching file BUILD.gn
Hunk #1 succeeded at 1555 with fuzz 2 (offset 431 lines).
Hunk #2 succeeded at 1606 with fuzz 2 (offset 455 lines).
Hunk #3 succeeded at 1622 with fuzz 2 (offset 456 lines).
==== Building V8 branch-heads/7.4 x64.release ====
(cd v8/v8; PATH=/root/v8/wasm-c-api/v8/depot_tools:/root/wasm/emsdk:/root/wasm/emsdk/fastcomp/emscripten:/root/wasm/emsdk/node/8.9.1_64bit/bin:/root/.wasmer/bin:/root/.wasmer/globals/wapm_packages/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/root/llvm/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04/bin:/root/wavm/WAVM/bin:/root/bin tools/dev/v8gen.py x64.release -- is_component_build=false v8_static_library=true v8_monolithic=true v8_use_external_startup_data=false v8_enable_i18n_support=false use_custom_libcxx=false use_custom_libcxx_for_host=false)

Hint: You can raise verbosity (-vv) to see the output of failed commands.

Traceback (most recent call last):
  File "tools/dev/v8gen.py", line 307, in <module>
    sys.exit(gen.main())
  File "tools/dev/v8gen.py", line 301, in main
    return self._options.func()
  File "tools/dev/v8gen.py", line 169, in cmd_gen
    gn_outdir,
  File "tools/dev/v8gen.py", line 211, in _call_cmd
    stderr=subprocess.STDOUT,
  File "/usr/lib/python2.7/subprocess.py", line 223, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['/usr/bin/python', '-u', 'tools/mb/mb.py', 'gen', '-f', 'infra/mb/mb_config.pyl', '-m', 'developer_default', '-b', 'x64.release', 'out.gn/x64.release']' returned non-zero exit status 1
Makefile:204: recipe for target 'v8-build' failed
make: *** [v8-build] Error 1
root@iZrj97ibqurmwnu9mj5htdZ:~/v8/wasm-c-api#

ENV:

root@iZrj97ibqurmwnu9mj5htdZ:~/v8/wasm-c-api# python --version
Python 2.7.15rc1
root@iZrj97ibqurmwnu9mj5htdZ:~/v8/wasm-c-api#
root@iZrj97ibqurmwnu9mj5htdZ:~/v8/wasm-c-api# clang --version
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
root@iZrj97ibqurmwnu9mj5htdZ:~/v8/wasm-c-api# cat /etc/issue
Ubuntu 18.04.2 LTS \n \l

root@iZrj97ibqurmwnu9mj5htdZ:~/v8/wasm-c-api#

Expose bounds checking failure for wasm_table_get

The API for getting a table element doesn't directly expose the possibility for the access to fail due to bounds checking:

own wasm_ref_t* wasm_table_get(const wasm_table_t*, wasm_table_size_t index);

Perhaps it should be something like this:

bool wasm_table_get(const wasm_table_t*, wasm_table_size_t index, own wasm_ref_t** out);

Memory leaks in examples

When compiled with -fsanitize=address:

==== C hello ====
Initializing...
Loading binary...
Compiling module...
Creating callback...
Instantiating module...
Extracting export...
Calling export...
Calling back...
> Hello World!
Shutting down...
Done.

=================================================================
==2955==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 24 byte(s) in 1 object(s) allocated from:
    #0 0x518610  (/stuff/dfinity/wasm-c-api/out/example/hello-c+0x518610)
    #1 0x547487  (/stuff/dfinity/wasm-c-api/out/example/hello-c+0x547487)
    #2 0x530f12  (/stuff/dfinity/wasm-c-api/out/example/hello-c+0x530f12)
    #3 0x53134f  (/stuff/dfinity/wasm-c-api/out/example/hello-c+0x53134f)

Indirect leak of 48 byte(s) in 1 object(s) allocated from:
    #0 0x518980  (/stuff/dfinity/wasm-c-api/out/example/hello-c+0x518980)
    #1 0x52c507  (/stuff/dfinity/wasm-c-api/out/example/hello-c+0x52c507)
    #2 0x548a6e  (/stuff/dfinity/wasm-c-api/out/example/hello-c+0x548a6e)

Indirect leak of 40 byte(s) in 1 object(s) allocated from:
    #0 0x518610  (/stuff/dfinity/wasm-c-api/out/example/hello-c+0x518610)
    #1 0x5312f4  (/stuff/dfinity/wasm-c-api/out/example/hello-c+0x5312f4)

SUMMARY: AddressSanitizer: 112 byte(s) leaked in 3 allocation(s).
Makefile:104: recipe for target 'run-hello-c' failed
make: *** [run-hello-c] Error 1
rm out/example/hello-c.o

It's not obvious where the leak is coming from or how to clean it up.

Lifetime of `wasm_memory_data` pointer

The wasm_memory_data function:

byte_t* wasm_memory_data(wasm_memory_t*);

returns a pointer to the linear memory. However, if a memory.grow or wasm_memory_grow occurs while this pointer remains live, it could cause this pointer to dangle.

Would it be reasonable to add functions such as wasm_memory_load and wasm_memory_store to the API? There would be some parallels to wasm_table_get and wasm_table_set.

Separately, there's the question of whether you'd further want to remote wasm_memory_data altogether. On one hand, you can't eliminate all possibility of undefined behavior when using the C API, but on the other, this is a case where there is a non-obvious corner case which likely to be rare in practice, but not impossible.

Does wasm_instance_new need the wasm_store_t parameter?

Currently wasm_instance_new takes a wasm_store_t parameter as its first argument, but the second wasm_module_t argument was already created within a store and presumably this parameter could be inferred. Is this intended, though, to perhaps put instance cached data in one place and module cached data in another place?

Expose wasm_instance_new's potential to trap

The current API doesn't expose the possibility that instantiation will trap while initializing the active segments or invoking the module's start function:

own wasm_instance_t* wasm_instance_new(
  wasm_store_t*, const wasm_module_t*, const wasm_extern_t* const imports[]);

Perhaps the API should be:

own wasm_trap_t* wasm_instance_new(
  wasm_store_t*, const wasm_module_t*, const wasm_extern_t* const imports[], own wasm_instance_t** out);

Why the Extern hierarchy?

It just doesn't add anything. And only feels like oop for the sake of oop.

User code will want to grab the underlying type directly. And forcing everyone through a generic exports() accessor will just hurt performance and usability.

Most of your examples already expose a helper function for it that take hardcoded magic indices for what they need. If the order of exports ever change then they will fail.

Add option to configure garbage collection on VM shutdown.

Please add an option to configure garbage collection on VM shutdown at the API level, separately from #ifdef DEBUG.

Currently, garbage collection in V8 is forced to run in ~StoreImpl() only when built with -DDEBUG, and leaks memory otherwise. Ideally, it should always run, to avoid any memory leaks, but I understand that this is waste of CPU cycles if the process is going to be terminated anyway.

This could be exposed in the API as:

Store(bool fast_shutdown = false);

cc @jakobkummerow @rossberg

Importing a runtime's WASI implementation

Have we given any thought to an API for instantiating a module with imports from a runtime's WASI implementation, if one is available?

As an example, Wasmtime has a WASI implementation and also implements the C API. For embedders of Wasmtime using the C API, it would be nice to tell the runtime to automatically import WASI when instantiating a module.

This would preclude the need for an embedder to roll their own WASI implementation when the runtime might already implement one.

Ditch wasm::vec for plain arrays?

The main purposes of wasm::vec are:

  • bundle an arrays and its size,
  • handle ownership of the elements (and the array),
  • allow casting from and to plain C arrays without copying.

The latter point is e.g. relevant to enable implementing the C API in terms of the C++ one, where vectors need to be passed back and forth in both directions. In contrast, adopting and casting from a C array is not possible with e.g. std::vector (also, std::vector implies exceptions).

Yet, the vec abstraction is fairly complex, and may not carry its own weight. A (safe) alternative would be to use unique_ptr<unique_ptr<T>[]>. However, that would require to reinterpret_cast between this type and plain T[] -- which works on all compilers I have checked, but has the UB smell to it.

Import/export matching by array position

The current API matches imported externs to wasm_importtype_t, and exported externs to wasm_exporttype_t by position within an array:

own wasm_instance_t* wasm_instance_new(
  wasm_store_t*, const wasm_module_t*, const wasm_extern_t* const imports[]);

void wasm_instance_exports(const wasm_instance_t*, own wasm_extern_vec_t* out);

WAVM's "native" API takes a separate vector of imports for each extern kind. This would be hard to make forward compatible with new extern kinds, so it's probably not suitable for this API.

V8 instantiation seems to expect a two-level dictionary indexed by module+name in the form of an object.

WAVM currently only exposes looking up an instance export by name. V8 seems to do the same.

Maybe wasm_instance_new should take a vector of module+name+extern tuples, and wasm_instance_exports should return a vector of name+extern tuples?

Allow wasm_module_t be created not from wasm bytecode.

(generalized from #122)

The wasm_module_t is used as a container for metadata: set of definitions for its functions, memory, etc. It will be nice to allow non-wasm module to be used in wasm-c-api environment.

The WASI usage is a good example: a host might select to mix different implementations of wasm-c-api and wasi (from different libraries). It will be nice to provide a mechanism to emit a module, that describes desired interface, and controls its instantiation via wasm_instance_new. The alternative is: to construct a wasm_instance_t at the same time as a wasm_module_t. Neither is possible at this moment.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.