From 4b0d6083a3fb2f3fb7c4e27b8d3c076fc0da63f3 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 7 Sep 2021 11:39:57 +0800 Subject: [PATCH] Enable lazy Orc JIT feature (#732) The feature is disabled by default, to enable it, please use `cmake -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1` to build iwasm. --- build-scripts/config_common.cmake | 8 + core/config.h | 9 +- core/iwasm/aot/aot_loader.c | 54 +++++ core/iwasm/compilation/aot_llvm.c | 231 +++++++++++++++++++- core/iwasm/compilation/aot_llvm.h | 22 ++ core/iwasm/compilation/aot_llvm_lazyjit.cpp | 128 +++++++++++ core/iwasm/compilation/aot_llvm_lazyjit.h | 77 +++++++ doc/build_wamr.md | 10 +- product-mini/platforms/linux/build_jit.sh | 2 + 9 files changed, 535 insertions(+), 6 deletions(-) create mode 100644 core/iwasm/compilation/aot_llvm_lazyjit.cpp create mode 100644 core/iwasm/compilation/aot_llvm_lazyjit.h diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index e08027137..15d47a00b 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -83,6 +83,9 @@ endif () if (WAMR_BUILD_JIT EQUAL 1) if (WAMR_BUILD_AOT EQUAL 1) add_definitions("-DWASM_ENABLE_JIT=1") + if (WAMR_BUILD_LAZY_JIT EQUAL 1) + add_definitions("-DWASM_ENABLE_LAZY_JIT=1") + endif () if (NOT DEFINED LLVM_DIR) set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build") @@ -122,6 +125,11 @@ else () endif () if (WAMR_BUILD_JIT EQUAL 1) message (" WAMR JIT enabled") + if (WAMR_BUILD_LAZY_JIT EQUAL 1) + message (" WAMR LazyJIT enabled") + else () + message (" WAMR LazyJIT disabled") + endif () else () message (" WAMR JIT disabled") endif () diff --git a/core/config.h b/core/config.h index 6659d62ba..5abb7e6b1 100644 --- a/core/config.h +++ b/core/config.h @@ -75,10 +75,17 @@ #define WASM_ENABLE_JIT 0 #endif +#ifndef WASM_ENABLE_LAZY_JIT +#define WASM_ENABLE_LAZY_JIT 0 +#endif + #if (WASM_ENABLE_AOT == 0) && (WASM_ENABLE_JIT != 0) -/* JIT can only be enabled when AOT is enabled */ +/* LazyJIT or MCJIT can only be enabled when AOT is enabled */ #undef WASM_ENABLE_JIT #define WASM_ENABLE_JIT 0 + +#undef WASM_ENABLE_LAZY_JIT +#define WASM_ENABLE_LAZY_JIT 0 #endif #ifndef WASM_ENABLE_WAMR_COMPILER diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 599af2d24..10907e850 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -2535,6 +2535,13 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, char func_name[32]; AOTModule *module; +#if WASM_ENABLE_LAZY_JIT != 0 + LLVMOrcThreadSafeModuleRef ts_module; + LLVMOrcJITDylibRef main_dylib; + LLVMErrorRef error; + LLVMOrcJITTargetAddress func_addr = 0; +#endif + /* Allocate memory for module */ if (!(module = loader_malloc(sizeof(AOTModule), error_buf, error_buf_size))) { @@ -2597,6 +2604,47 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, goto fail2; } +#if WASM_ENABLE_LAZY_JIT != 0 + bh_assert(comp_ctx->lazy_orcjit); + + main_dylib = LLVMOrcLLLazyJITGetMainJITDylib(comp_ctx->lazy_orcjit); + if (!main_dylib) { + set_error_buf(error_buf, error_buf_size, + "failed to get dynmaic library reference"); + goto fail3; + } + + ts_module = LLVMOrcCreateNewThreadSafeModule(comp_ctx->module, + comp_ctx->ts_context); + if (!ts_module) { + set_error_buf(error_buf, error_buf_size, + "failed to create thread safe module"); + goto fail3; + } + + if ((error = LLVMOrcLLLazyJITAddLLVMIRModule(comp_ctx->lazy_orcjit, + main_dylib, ts_module))) { + /* + * If adding the ThreadSafeModule fails then we need to clean it up + * ourselves. If adding it succeeds the JIT will manage the memory. + */ + aot_handle_llvm_errmsg(error_buf, error_buf_size, + "failed to addIRModule: ", error); + goto fail4; + } + + for (i = 0; i < comp_data->func_count; i++) { + snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i); + if ((error = LLVMOrcLLLazyJITLookup(comp_ctx->lazy_orcjit, + &func_addr, func_name))) { + aot_handle_llvm_errmsg(error_buf, error_buf_size, + "cannot lookup: ", error); + goto fail3; + } + module->func_ptrs[i] = (void *)func_addr; + func_addr = 0; + } +#else /* Resolve function addresses */ bh_assert(comp_ctx->exec_engine); for (i = 0; i < comp_data->func_count; i++) { @@ -2609,6 +2657,7 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, goto fail3; } } +#endif /* WASM_ENABLE_LAZY_JIT != 0 */ /* Allocation memory for function type indexes */ size = (uint64)module->func_count * sizeof(uint32); @@ -2662,6 +2711,11 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, return module; +#if WASM_ENABLE_LAZY_JIT != 0 +fail4: + LLVMOrcDisposeThreadSafeModule(ts_module); +#endif + fail3: if (module->func_ptrs) wasm_runtime_free(module->func_ptrs); diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index e56fe614f..1a87c412d 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -1207,13 +1207,174 @@ WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); +#if WASM_ENABLE_LAZY_JIT != 0 +void +aot_handle_llvm_errmsg(char *error_buf, + uint32 error_buf_size, + const char *string, + LLVMErrorRef error) +{ + char *err_msg = LLVMGetErrorMessage(error); + if (error_buf != NULL) { + snprintf(error_buf, error_buf_size, + "%s: %s", string, err_msg); + } + LLVMDisposeErrorMessage(err_msg); +} + +static bool +llvm_orcjit_create(AOTCompContext *comp_ctx) +{ + char *err_msg = NULL; + char *cpu = NULL; + char *features = NULL; + char *llvm_triple = NULL; + char buf[128] = {0}; + + LLVMErrorRef error; + LLVMTargetRef llvm_targetref = NULL; + LLVMTargetMachineRef tm_opt = NULL; + LLVMTargetMachineRef tm_opt2 = NULL; + LLVMOrcLLLazyJITRef lazy_orcjit = NULL; + LLVMOrcJITTargetMachineBuilderRef tm_builder = NULL; + LLVMOrcLLLazyJITBuilderRef lazy_orcjit_builder = NULL; +#if LLVM_VERSION_MAJOR < 12 + LLVMOrcJITDylibDefinitionGeneratorRef main_gen = NULL; +#else + LLVMOrcDefinitionGeneratorRef main_gen = NULL; +#endif + + llvm_triple = LLVMGetDefaultTargetTriple(); + if (llvm_triple == NULL) { + snprintf(buf, sizeof(buf), "failed to get default target triple."); + goto fail; + } + + if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &err_msg) != 0) { + snprintf(buf, sizeof(buf), + "failed to get target reference from triple %s.", err_msg); + LLVMDisposeMessage(err_msg); + goto fail; + } + + if (!LLVMTargetHasJIT(llvm_targetref)) { + snprintf(buf, sizeof(buf), "unspported JIT on this platform."); + goto fail; + } + + cpu = LLVMGetHostCPUName(); + if (cpu == NULL) { + snprintf(buf, sizeof(buf), "failed to get host cpu information."); + goto fail; + } + + features = LLVMGetHostCPUFeatures(); + if (features == NULL) { + snprintf(buf, sizeof(buf), "failed to get host cpu features."); + goto fail; + } + + LOG_VERBOSE("LLVM ORCJIT detected CPU \"%s\", with features \"%s\"\n", + cpu, features); + + tm_opt = LLVMCreateTargetMachine(llvm_targetref, llvm_triple, + cpu, features, + LLVMCodeGenLevelAggressive, + LLVMRelocDefault, + LLVMCodeModelJITDefault); + if (!tm_opt) { + snprintf(buf, sizeof(buf), "failed to create target machine."); + goto fail; + } + + tm_opt2 = LLVMCreateTargetMachine(llvm_targetref, llvm_triple, + cpu, features, + LLVMCodeGenLevelAggressive, + LLVMRelocDefault, + LLVMCodeModelJITDefault); + if (!tm_opt2) { + snprintf(buf, sizeof(buf), "failed to create target machine2."); + goto fail; + } + + /* if success, it will dispose tm_opt2 memory. */ + tm_builder = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm_opt2); + if (!tm_builder) { + snprintf(buf, sizeof(buf), "failed to create target machine builder."); + goto fail; + } + tm_opt2 = NULL; + + lazy_orcjit_builder = LLVMOrcCreateLLLazyJITBuilder(); + if (!lazy_orcjit_builder) { + snprintf(buf, sizeof(buf), "failed to create lazy jit builder."); + goto fail; + } + + LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(lazy_orcjit_builder, + tm_builder); + + /* if success, it will dispose lazy_orcjit_builder memory */ + error = LLVMOrcCreateLLLazyJIT(&lazy_orcjit, lazy_orcjit_builder); + if (error) { + aot_handle_llvm_errmsg(buf, sizeof(buf), + "failed to create llvm lazy orcjit instance", + error); + goto fail; + } + lazy_orcjit_builder = NULL; + + error = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess( + &main_gen, LLVMOrcLLLazyJITGetGlobalPrefix(lazy_orcjit), + 0, NULL); + if (error) { + aot_handle_llvm_errmsg(buf, sizeof(buf), + "failed to create dynmaic library search generator", error); + goto fail; + } + + LLVMOrcJITDylibAddGenerator(LLVMOrcLLLazyJITGetMainJITDylib(lazy_orcjit), + main_gen); + + comp_ctx->lazy_orcjit = lazy_orcjit; + comp_ctx->target_machine = tm_opt; + comp_ctx->tm_builder = tm_builder; + LLVMDisposeMessage(llvm_triple); + LLVMDisposeMessage(cpu); + LLVMDisposeMessage(features); + return true; + +fail: + if (lazy_orcjit) + LLVMOrcDisposeLLLazyJIT(lazy_orcjit); + if (tm_builder) + LLVMOrcDisposeJITTargetMachineBuilder(tm_builder); + if (lazy_orcjit_builder) + LLVMOrcDisposeLLLazyJITBuilder(lazy_orcjit_builder); + if (tm_opt2) + LLVMDisposeTargetMachine(tm_opt2); + if (tm_opt) + LLVMDisposeTargetMachine(tm_opt); + if (features) + LLVMDisposeMessage(features); + if (cpu) + LLVMDisposeMessage(cpu); + if (llvm_triple) + LLVMDisposeMessage(llvm_triple); + aot_set_last_error(buf); + return false; +} +#endif /* WASM_ENABLE_LAZY_JIT != 0 */ + AOTCompContext * aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) { AOTCompContext *comp_ctx, *ret = NULL; - /*LLVMTypeRef elem_types[8];*/ +#if WASM_ENABLE_LAZY_JIT == 0 struct LLVMMCJITCompilerOptions jit_options; +#endif + LLVMTargetRef target; char *triple = NULL, *triple_norm, *arch, *abi; char *cpu = NULL, *features, buf[128]; @@ -1225,11 +1386,18 @@ aot_create_comp_context(AOTCompData *comp_data, LLVMTargetDataRef target_data_ref; /* Initialize LLVM environment */ +#if WASM_ENABLE_LAZY_JIT != 0 + LLVMInitializeCore(LLVMGetGlobalPassRegistry()); + LLVMInitializeNativeTarget(); + LLVMInitializeNativeAsmPrinter(); + LLVMInitializeNativeAsmParser(); +#else LLVMInitializeAllTargetInfos(); LLVMInitializeAllTargets(); LLVMInitializeAllTargetMCs(); LLVMInitializeAllAsmPrinters(); LLVMLinkInMCJIT(); +#endif /* Allocate memory */ if (!(comp_ctx = wasm_runtime_malloc(sizeof(AOTCompContext)))) { @@ -1241,10 +1409,24 @@ aot_create_comp_context(AOTCompData *comp_data, comp_ctx->comp_data = comp_data; /* Create LLVM context, module and builder */ +#if WASM_ENABLE_LAZY_JIT != 0 + comp_ctx->ts_context = LLVMOrcCreateNewThreadSafeContext(); + if (!comp_ctx->ts_context) { + aot_set_last_error("create LLVM ThreadSafeContext failed."); + return NULL; + } + /* Get a reference to the underlying LLVMContext */ + if (!(comp_ctx->context = + LLVMOrcThreadSafeContextGetContext(comp_ctx->ts_context))) { + aot_set_last_error("get context from LLVM ThreadSafeContext failed."); + goto fail; + } +#else if (!(comp_ctx->context = LLVMContextCreate())) { aot_set_last_error("create LLVM context failed."); goto fail; } +#endif if (!(comp_ctx->builder = LLVMCreateBuilderInContext(comp_ctx->context))) { aot_set_last_error("create LLVM builder failed."); @@ -1288,6 +1470,14 @@ aot_create_comp_context(AOTCompData *comp_data, if (option->is_jit_mode) { char *triple_jit = NULL; +#if WASM_ENABLE_LAZY_JIT != 0 + /* Create LLLazyJIT Instance */ + if (!llvm_orcjit_create(comp_ctx)) { + aot_set_last_error("create LLVM Lazy JIT Compiler failed."); + goto fail; + } + +#else /* Create LLVM execution engine */ LLVMInitializeMCJITCompilerOptions(&jit_options, sizeof(jit_options)); jit_options.OptLevel = LLVMCodeGenLevelAggressive; @@ -1303,15 +1493,28 @@ aot_create_comp_context(AOTCompData *comp_data, aot_set_last_error("create LLVM JIT compiler failed."); goto fail; } - comp_ctx->is_jit_mode = true; comp_ctx->target_machine = LLVMGetExecutionEngineTargetMachine(comp_ctx->exec_engine); +#endif + comp_ctx->is_jit_mode = true; + #ifndef OS_ENABLE_HW_BOUND_CHECK comp_ctx->enable_bound_check = true; #else comp_ctx->enable_bound_check = false; #endif +#if WASM_ENABLE_LAZY_JIT != 0 + if (!(triple_jit = + (char *)LLVMOrcLLLazyJITGetTripleString(comp_ctx->lazy_orcjit))) { + aot_set_last_error("can not get triple from the target machine"); + goto fail; + } + + /* Save target arch */ + get_target_arch_from_triple(triple_jit, comp_ctx->target_arch, + sizeof(comp_ctx->target_arch)); +#else if (!(triple_jit = LLVMGetTargetMachineTriple(comp_ctx->target_machine))) { aot_set_last_error("can not get triple from the target machine"); @@ -1322,6 +1525,7 @@ aot_create_comp_context(AOTCompData *comp_data, get_target_arch_from_triple(triple_jit, comp_ctx->target_arch, sizeof(comp_ctx->target_arch)); LLVMDisposeMessage(triple_jit); +#endif } else { /* Create LLVM target machine */ @@ -1706,9 +1910,29 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx) if (!comp_ctx) return; - if (comp_ctx->pass_mgr) + if (comp_ctx->pass_mgr) { + LLVMFinalizeFunctionPassManager(comp_ctx->pass_mgr); LLVMDisposePassManager(comp_ctx->pass_mgr); + } +#if WASM_ENABLE_LAZY_JIT != 0 + if (comp_ctx->target_machine && comp_ctx->is_jit_mode) + LLVMDisposeTargetMachine(comp_ctx->target_machine); + + if (comp_ctx->builder) + LLVMDisposeBuilder(comp_ctx->builder); + + if (comp_ctx->lazy_orcjit) + LLVMOrcDisposeLLLazyJIT(comp_ctx->lazy_orcjit); + + if (comp_ctx->ts_context) + LLVMOrcDisposeThreadSafeContext(comp_ctx->ts_context); + + if (comp_ctx->tm_builder) + LLVMOrcDisposeJITTargetMachineBuilder(comp_ctx->tm_builder); + + LLVMShutdown(); +#else if (comp_ctx->target_machine && !comp_ctx->is_jit_mode) LLVMDisposeTargetMachine(comp_ctx->target_machine); @@ -1725,6 +1949,7 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx) if (comp_ctx->context) LLVMContextDispose(comp_ctx->context); +#endif if (comp_ctx->func_ctxes) aot_destroy_func_contexts(comp_ctx->func_ctxes, diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 2eade1a00..052f41cfa 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -18,6 +18,14 @@ #include "llvm-c/Transforms/Scalar.h" #include "llvm-c/Transforms/Vectorize.h" +#if WASM_ENABLE_LAZY_JIT != 0 +#include "aot_llvm_lazyjit.h" +#include "llvm-c/Orc.h" +#include "llvm-c/Error.h" +#include "llvm-c/Initialization.h" +#include "llvm-c/Support.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -227,7 +235,13 @@ typedef struct AOTCompContext { uint64 flags[8]; /* LLVM execution engine required by JIT */ +#if WASM_ENABLE_LAZY_JIT != 0 + LLVMOrcLLLazyJITRef lazy_orcjit; + LLVMOrcThreadSafeContextRef ts_context; + LLVMOrcJITTargetMachineBuilderRef tm_builder; +#else LLVMExecutionEngineRef exec_engine; +#endif bool is_jit_mode; /* AOT indirect mode flag & symbol list */ @@ -403,6 +417,14 @@ aot_get_func_from_table(const AOTCompContext *comp_ctx, bool aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str); +#if WASM_ENABLE_LAZY_JIT != 0 +void +aot_handle_llvm_errmsg(char *error_buf, + uint32 error_buf_size, + const char *string, + LLVMErrorRef error); +#endif + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/compilation/aot_llvm_lazyjit.cpp b/core/iwasm/compilation/aot_llvm_lazyjit.cpp new file mode 100644 index 000000000..b74e91a7b --- /dev/null +++ b/core/iwasm/compilation/aot_llvm_lazyjit.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_llvm_lazyjit.h" + +LLVMOrcJITTargetMachineBuilderRef +LLVMOrcJITTargetMachineBuilderFromTargetMachine(LLVMTargetMachineRef TM); + +LLVMOrcLLJITBuilderRef +LLVMOrcCreateLLJITBuilder(void); + +void +LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder); + +LLVMErrorRef +LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result, + LLVMOrcLLJITBuilderRef Builder); + +LLVMErrorRef +LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J); + +LLVMOrcJITDylibRef +LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J); + +const char * +LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J); + +char +LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J); + +LLVMErrorRef +LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J, + LLVMOrcJITDylibRef JD, + LLVMOrcThreadSafeModuleRef TSM); + +LLVMErrorRef +LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, + LLVMOrcJITTargetAddress *Result, + const char *Name); + +const char * +LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J); + +void +LLVMOrcLLJITBuilderSetJITTargetMachineBuilder( + LLVMOrcLLJITBuilderRef Builder, + LLVMOrcJITTargetMachineBuilderRef JTMB); + +char +LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J); + +#if LLVM_VERSION_MAJOR < 12 +LLVMOrcJITTargetMachineBuilderRef +LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM) +{ + return LLVMOrcJITTargetMachineBuilderFromTargetMachine(TM); +} +#endif + +LLVMOrcJITDylibRef +LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J) +{ + return LLVMOrcLLJITGetMainJITDylib(J); +} + +LLVMOrcLLLazyJITBuilderRef +LLVMOrcCreateLLLazyJITBuilder(void) +{ + return LLVMOrcCreateLLJITBuilder(); +} + +void +LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder) +{ + return LLVMOrcDisposeLLJITBuilder(Builder); +} + +LLVMErrorRef +LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result, + LLVMOrcLLLazyJITBuilderRef Builder) +{ + return LLVMOrcCreateLLJIT(Result, Builder); +} + +LLVMErrorRef +LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J) +{ + return LLVMOrcDisposeLLJIT(J); +} + +LLVMErrorRef +LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J, + LLVMOrcJITDylibRef JD, + LLVMOrcThreadSafeModuleRef TSM) +{ + return LLVMOrcLLJITAddLLVMIRModule(J, JD, TSM); +} + +LLVMErrorRef +LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J, + LLVMOrcJITTargetAddress *Result, + const char *Name) +{ + return LLVMOrcLLJITLookup(J, Result, Name); +} + +const char * +LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J) +{ + return LLVMOrcLLJITGetTripleString(J); +} + +void +LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder( + LLVMOrcLLLazyJITBuilderRef Builder, + LLVMOrcJITTargetMachineBuilderRef JTMB) +{ + return LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(Builder, JTMB); +} + +char +LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J) +{ + return LLVMOrcLLJITGetGlobalPrefix(J); +} + diff --git a/core/iwasm/compilation/aot_llvm_lazyjit.h b/core/iwasm/compilation/aot_llvm_lazyjit.h new file mode 100644 index 000000000..92d14b675 --- /dev/null +++ b/core/iwasm/compilation/aot_llvm_lazyjit.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef AOT_LLVM_LAZYJIT_H +#define AOT_LLVM_LAZYJIT_H + +#include "llvm-c/Error.h" +#include "llvm-c/Orc.h" +#include "llvm-c/TargetMachine.h" +#include "llvm-c/Types.h" +#if LLVM_VERSION_MAJOR >= 12 +#include "llvm-c/LLJIT.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef LLVMOrcLLJITBuilderRef LLVMOrcLLLazyJITBuilderRef; + +typedef LLVMOrcLLJITRef LLVMOrcLLLazyJITRef; + +LLVMOrcJITTargetMachineBuilderRef +LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM); + +LLVMOrcLLLazyJITBuilderRef +LLVMOrcCreateLLLazyJITBuilder(void); + +void +LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder); + +LLVMErrorRef +LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result, + LLVMOrcLLLazyJITBuilderRef Builder); + +LLVMErrorRef +LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J); + +LLVMOrcJITDylibRef +LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J); + +const char * +LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J); + +char +LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J); + +LLVMErrorRef +LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J, + LLVMOrcJITDylibRef JD, + LLVMOrcThreadSafeModuleRef TSM); + +LLVMErrorRef +LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J, + LLVMOrcJITTargetAddress *Result, + const char *Name); + +const char * +LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J); + +void +LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder( + LLVMOrcLLLazyJITBuilderRef Builder, + LLVMOrcJITTargetMachineBuilderRef JTMB); + +char +LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J); + +#ifdef __cplusplus +} +#endif + +#endif /* end of AOT_LLVM_LAZYJIT_H */ + diff --git a/doc/build_wamr.md b/doc/build_wamr.md index b0d418a67..8f7277e05 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -41,6 +41,7 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM - **WAMR_BUILD_AOT**=1/0, default to enable if not set - **WAMR_BUILD_JIT**=1/0, default to disable if not set +- **WAMR_BUILD_LAZY_JIT**=1/0, default to disable if not set #### **Configure LIBC** @@ -198,8 +199,8 @@ make ``` -By default in Linux, the interpreter, AOT and WASI are enabled, and JIT is disabled. And the build target is -set to X86_64 or X86_32 depending on the platform's bitwidth. +By default in Linux, the interpreter, AOT and WASI are enabled, and JIT and LazyJIT are disabled. +And the build target is set to X86_64 or X86_32 depending on the platform's bitwidth. To enable WASM JIT, firstly we should build LLVM: @@ -217,6 +218,11 @@ cmake .. -DWAMR_BUILD_JIT=1 make ``` +Moreover, pass arguments `-DWAMR_BUILD_JIT=1` and `-DWAMR_BUILD_LAZY_JIT=1` together to cmake to enable WASM Lazy JIT. +If Lazy JIT is enabled, then jit function bodies in the module will not be compiled until they are first called, +so compile time reduces significantly. + + Linux SGX (Intel Software Guard Extension) ------------------------- diff --git a/product-mini/platforms/linux/build_jit.sh b/product-mini/platforms/linux/build_jit.sh index 908d1560c..8cfdb7369 100755 --- a/product-mini/platforms/linux/build_jit.sh +++ b/product-mini/platforms/linux/build_jit.sh @@ -5,6 +5,8 @@ rm -fr build && mkdir build cd build +# Build With LazyJIT +# cmake .. -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1 cmake .. -DWAMR_BUILD_JIT=1 make cd ..