Skip to content

Commit

Permalink
Add Hermes wasm2c compilation
Browse files Browse the repository at this point in the history
Summary:
Add the ability to compile Hermes with the C-API to wasm, and the
resulting wasm to C. Check in the generated artefact for a release and
debug build of Hermes, making it easier to build and develop with.

Reviewed By: avp

Differential Revision: D47065258

fbshipit-source-id: 0de6bc047a6ebc1fdac91a460fefcbf880c4e4b3
  • Loading branch information
neildhar authored and facebook-github-bot committed Jan 13, 2024
1 parent c24dd3c commit 879eab8
Show file tree
Hide file tree
Showing 13 changed files with 2,527,509 additions and 0 deletions.
1 change: 1 addition & 0 deletions API/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@

add_subdirectory(hermes)
add_subdirectory(hermes_abi)
add_subdirectory(hermes_sandbox)
13 changes: 13 additions & 0 deletions API/hermes_sandbox/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

if (EMSCRIPTEN)
set(WASM_LINKER_ARGS "-sEXPORTED_FUNCTIONS=[_get_hermes_abi_vtable, _malloc, _realloc, _free, stackSave, stackRestore, stackAlloc]" -sSTANDALONE_WASM --no-entry -sALLOW_TABLE_GROWTH=1)

# Define a target that builds the Hermes library as a wasm executable.
add_executable(hermesSandboxImpl hermes_sandbox_impl.cpp )
target_link_libraries(hermesSandboxImpl PRIVATE hermesabi)
target_link_options(hermesSandboxImpl PRIVATE ${WASM_LINKER_ARGS})
endif()
47 changes: 47 additions & 0 deletions API/hermes_sandbox/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Hermes Sandboxed Runtime implementation

This directory contains a sandboxed version of Hermes that is produced by compiling Hermes to wasm, and then compiling the resulting wasm to C using wasm2c. The sandboxed code exposes Hermes' C-API, and JSI is re-implemented on top of it.

The generated C is pre-generated and checked in to simplify the build. It will need to be periodically updated to incorporate bug fixes, and especially when there are changes to JSI or the bytecode version.

## Re-generating the sandbox

Install `emsdk` by following the instructions [here](https://github.com/emscripten-core/emsdk). Then [download wasm2c from wabt](https://github.com/WebAssembly/wabt/releases).

Build `hermesc` for the host platform, in order to generate bytecode that is used by the Hermes build. The commands below use `build_host` to refer to this host build.


Generate the debug build with the following command. Note that it is built with O2 and without slow asserts to avoid slowing down execution too dramatically, since the generated C code for the debug build is then typically built without optimisations.
```
cmake -S <path to hermes> -B build_wasm_dbg \
-DCMAKE_TOOLCHAIN_FILE=<path to emsdk>/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
-DIMPORT_HERMESC=build_host/ImportHermesc.cmake \
-DCMAKE_BUILD_TYPE=Debug -DHERMES_UNICODE_LITE=ON \
-DCMAKE_CXX_FLAGS=-O2 -DCMAKE_C_FLAGS=-O2 \
-DCMAKE_EXE_LINKER_FLAGS="-sALLOW_MEMORY_GROWTH=1 -sSTACK_SIZE=256KB" \
-DHERMES_ENABLE_DEBUGGER=OFF -DHERMES_SLOW_DEBUG=OFF \
-G Ninja
```

Then generate the C artefact by running the following:
```
cmake --build build_wasm_dbg --target hermesSandboxImpl \
&& wasm2c build_wasm_dbg/API/hermes_sandbox/hermesSandboxImpl.wasm -n hermes \
-o <path to hermes>/API/hermes_sandbox/external/hermes_sandbox_impl_dbg_compiled.c
```

Likewise for the release build. Note that the release build is still built with `-g2` to preserve function names. Since the generated C is going to be compiled anyway, this doesn't have any effect on the final size of release builds.
```
cmake -S <path to hermes> -B build_wasm_opt \
-DCMAKE_TOOLCHAIN_FILE=<path to emsdk>/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
-DIMPORT_HERMESC=build_host/ImportHermesc.cmake \
-DCMAKE_BUILD_TYPE=Release -DHERMES_UNICODE_LITE=ON \
-DCMAKE_EXE_LINKER_FLAGS="-sALLOW_MEMORY_GROWTH=1 -sSTACK_SIZE=256KB -g2" \
-DHERMES_ENABLE_DEBUGGER=OFF -G Ninja
cmake --build build_wasm_opt --target hermesSandboxImpl \
&& wasm2c build_wasm_opt/API/hermes_sandbox/hermesSandboxImpl.wasm -n hermes \
-o <path to hermes>/API/hermes_sandbox/external/hermes_sandbox_impl_opt_compiled.c
```

The currently generated artefact was generated using **emsdk 3.1.39**, and **wasm2c 1.0.33**. Note that using a newer wasm2c will also require updating the checked in wasm-rt files in the `external` directory, which provide the runtime library for the generated code.
12 changes: 12 additions & 0 deletions API/hermes_sandbox/external/hermes_sandbox_impl_compiled.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#ifdef NDEBUG
#include "hermes_sandbox_impl_opt_compiled.c"
#else
#include "hermes_sandbox_impl_dbg_compiled.c"
#endif
12 changes: 12 additions & 0 deletions API/hermes_sandbox/external/hermes_sandbox_impl_compiled.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#ifdef NDEBUG
#include "hermes_sandbox_impl_opt_compiled.h"
#else
#include "hermes_sandbox_impl_dbg_compiled.h"
#endif
Loading

0 comments on commit 879eab8

Please sign in to comment.