// Copyright 2018 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #if !V8_ENABLE_WEBASSEMBLY #error This header should only be included if WebAssembly is enabled. #endif // !V8_ENABLE_WEBASSEMBLY #ifndef V8_WASM_JUMP_TABLE_ASSEMBLER_H_ #define V8_WASM_JUMP_TABLE_ASSEMBLER_H_ #include "src/codegen/flush-instruction-cache.h" #include "src/codegen/macro-assembler.h" namespace v8 { namespace internal { namespace wasm { // The jump table is the central dispatch point for all (direct and indirect) // invocations in WebAssembly. It holds one slot per function in a module, with // each slot containing a dispatch to the currently published {WasmCode} that // corresponds to the function. // // Additionally to this main jump table, there exist special jump tables for // other purposes: // - the far stub table contains one entry per wasm runtime stub (see // {WasmCode::RuntimeStubId}, which jumps to the corresponding embedded // builtin, plus (if not the full address space can be reached via the jump // table) one entry per wasm function. // - the lazy compile table contains one entry per wasm function which jumps to // the common {WasmCompileLazy} builtin and passes the function index that was // invoked. // // The main jump table is split into lines of fixed size, with lines laid out // consecutively within the executable memory of the {NativeModule}. The slots // in turn are consecutive within a line, but do not cross line boundaries. // // +- L1 -------------------+ +- L2 -------------------+ +- L3 ... // | S1 | S2 | ... | Sn | x | | S1 | S2 | ... | Sn | x | | S1 ... // +------------------------+ +------------------------+ +---- ... // // The above illustrates jump table lines {Li} containing slots {Si} with each // line containing {n} slots and some padding {x} for alignment purposes. // Other jump tables are just consecutive. // // The main jump table will be patched concurrently while other threads execute // it. The code at the new target might also have been emitted concurrently, so // we need to ensure that there is proper synchronization between code emission, // jump table patching and code execution. // On Intel platforms, this all works out of the box because there is cache // coherency between i-cache and d-cache. // On ARM, it is safe because the i-cache flush after code emission executes an // "ic ivau" (Instruction Cache line Invalidate by Virtual Address to Point of // Unification), which broadcasts to all cores. A core which sees the jump table // update thus also sees the new code. Since the other core does not explicitly // execute an "isb" (Instruction Synchronization Barrier), it might still // execute the old code afterwards, which is no problem, since that code remains // available until it is garbage collected. Garbage collection itself is a // synchronization barrier though. class V8_EXPORT_PRIVATE JumpTableAssembler : public MacroAssembler { … }; } // namespace wasm } // namespace internal } // namespace v8 #endif // V8_WASM_JUMP_TABLE_ASSEMBLER_H_