[wasm] Share code of js-to-wasm wrappers
Instead of creating a separate code object per exported function, we can share the code per signature, and load the function index from the {WasmExportedFunction} object which is being passed as an argument anyway. This greatly reduces instantiation time for modules with a lot of exports. As a next step, we could even share the code across instances, or (with more work) across isolates. R=mstarzinger@chromium.org Bug: chromium:860491 Change-Id: I6438065b2de0df59dce980fb52408a0f475144b3 Reviewed-on: https://chromium-review.googlesource.com/1127660 Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#54299}
This commit is contained in:
parent
fa067fb94c
commit
815485244f
@ -39,6 +39,7 @@
|
|||||||
#include "src/trap-handler/trap-handler.h"
|
#include "src/trap-handler/trap-handler.h"
|
||||||
#include "src/wasm/function-body-decoder.h"
|
#include "src/wasm/function-body-decoder.h"
|
||||||
#include "src/wasm/function-compiler.h"
|
#include "src/wasm/function-compiler.h"
|
||||||
|
#include "src/wasm/jump-table-assembler.h"
|
||||||
#include "src/wasm/memory-tracing.h"
|
#include "src/wasm/memory-tracing.h"
|
||||||
#include "src/wasm/wasm-code-manager.h"
|
#include "src/wasm/wasm-code-manager.h"
|
||||||
#include "src/wasm/wasm-limits.h"
|
#include "src/wasm/wasm-limits.h"
|
||||||
@ -2590,13 +2591,45 @@ Node* WasmGraphBuilder::BuildImportWasmCall(wasm::FunctionSig* sig, Node** args,
|
|||||||
LOAD_INSTANCE_FIELD(ImportedFunctionTargets, MachineType::Pointer());
|
LOAD_INSTANCE_FIELD(ImportedFunctionTargets, MachineType::Pointer());
|
||||||
Node* target_node = graph()->NewNode(
|
Node* target_node = graph()->NewNode(
|
||||||
mcgraph()->machine()->Load(MachineType::Pointer()), imported_targets,
|
mcgraph()->machine()->Load(MachineType::Pointer()), imported_targets,
|
||||||
mcgraph()->Int32Constant(func_index * sizeof(Address)),
|
mcgraph()->Int32Constant(func_index * kPointerSize),
|
||||||
mcgraph()->graph()->start(), mcgraph()->graph()->start());
|
mcgraph()->graph()->start(), mcgraph()->graph()->start());
|
||||||
args[0] = target_node;
|
args[0] = target_node;
|
||||||
return BuildWasmCall(sig, args, rets, position, instance_node,
|
return BuildWasmCall(sig, args, rets, position, instance_node,
|
||||||
untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline);
|
untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node* WasmGraphBuilder::BuildImportWasmCall(wasm::FunctionSig* sig, Node** args,
|
||||||
|
Node*** rets,
|
||||||
|
wasm::WasmCodePosition position,
|
||||||
|
Node* func_index) {
|
||||||
|
// Load the instance from the imported_instances array.
|
||||||
|
Node* imported_instances = LOAD_INSTANCE_FIELD(ImportedFunctionInstances,
|
||||||
|
MachineType::TaggedPointer());
|
||||||
|
// Access fixed array at {header_size - tag + func_index * kPointerSize}.
|
||||||
|
Node* imported_instances_data =
|
||||||
|
graph()->NewNode(mcgraph()->machine()->IntAdd(), imported_instances,
|
||||||
|
mcgraph()->IntPtrConstant(FixedArrayOffsetMinusTag(0)));
|
||||||
|
Node* func_index_times_pointersize = graph()->NewNode(
|
||||||
|
mcgraph()->machine()->IntMul(), Uint32ToUintptr(func_index),
|
||||||
|
mcgraph()->Int32Constant(kPointerSize));
|
||||||
|
Node* instance_node =
|
||||||
|
graph()->NewNode(mcgraph()->machine()->Load(MachineType::TaggedPointer()),
|
||||||
|
imported_instances_data, func_index_times_pointersize,
|
||||||
|
*effect_, *control_);
|
||||||
|
|
||||||
|
// Load the target from the imported_targets array at the offset of
|
||||||
|
// {func_index}.
|
||||||
|
Node* imported_targets =
|
||||||
|
LOAD_INSTANCE_FIELD(ImportedFunctionTargets, MachineType::Pointer());
|
||||||
|
Node* target_node = graph()->NewNode(
|
||||||
|
mcgraph()->machine()->Load(MachineType::Pointer()), imported_targets,
|
||||||
|
func_index_times_pointersize, mcgraph()->graph()->start(),
|
||||||
|
mcgraph()->graph()->start());
|
||||||
|
args[0] = target_node;
|
||||||
|
return BuildWasmCall(sig, args, rets, position, instance_node,
|
||||||
|
untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline);
|
||||||
|
}
|
||||||
|
|
||||||
Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets,
|
Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets,
|
||||||
wasm::WasmCodePosition position) {
|
wasm::WasmCodePosition position) {
|
||||||
DCHECK_NULL(args[0]);
|
DCHECK_NULL(args[0]);
|
||||||
@ -2929,10 +2962,8 @@ void WasmGraphBuilder::GetGlobalBaseAndOffset(MachineType mem_type,
|
|||||||
|
|
||||||
if (mem_type == MachineType::Simd128() && global.offset != 0) {
|
if (mem_type == MachineType::Simd128() && global.offset != 0) {
|
||||||
// TODO(titzer,bbudge): code generation for SIMD memory offsets is broken.
|
// TODO(titzer,bbudge): code generation for SIMD memory offsets is broken.
|
||||||
*base_node =
|
*base_node = graph()->NewNode(mcgraph()->machine()->IntAdd(), *base_node,
|
||||||
graph()->NewNode(kPointerSize == 4 ? mcgraph()->machine()->Int32Add()
|
*offset_node);
|
||||||
: mcgraph()->machine()->Int64Add(),
|
|
||||||
*base_node, *offset_node);
|
|
||||||
*offset_node = mcgraph()->Int32Constant(0);
|
*offset_node = mcgraph()->Int32Constant(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4326,7 +4357,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
&sig, graph()->NewNode(mcgraph()->common()->ExternalConstant(ref)));
|
&sig, graph()->NewNode(mcgraph()->common()->ExternalConstant(ref)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* BuildLoadInstanceFromExportedFunction(Node* closure) {
|
Node* BuildLoadFunctionDataFromExportedFunction(Node* closure) {
|
||||||
Node* shared = *effect_ = graph()->NewNode(
|
Node* shared = *effect_ = graph()->NewNode(
|
||||||
jsgraph()->machine()->Load(MachineType::AnyTagged()), closure,
|
jsgraph()->machine()->Load(MachineType::AnyTagged()), closure,
|
||||||
jsgraph()->Int32Constant(JSFunction::kSharedFunctionInfoOffset -
|
jsgraph()->Int32Constant(JSFunction::kSharedFunctionInfoOffset -
|
||||||
@ -4337,6 +4368,10 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
jsgraph()->Int32Constant(SharedFunctionInfo::kFunctionDataOffset -
|
jsgraph()->Int32Constant(SharedFunctionInfo::kFunctionDataOffset -
|
||||||
kHeapObjectTag),
|
kHeapObjectTag),
|
||||||
*effect_, *control_);
|
*effect_, *control_);
|
||||||
|
return function_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* BuildLoadInstanceFromExportedFunctionData(Node* function_data) {
|
||||||
Node* instance = *effect_ = graph()->NewNode(
|
Node* instance = *effect_ = graph()->NewNode(
|
||||||
jsgraph()->machine()->Load(MachineType::AnyTagged()), function_data,
|
jsgraph()->machine()->Load(MachineType::AnyTagged()), function_data,
|
||||||
jsgraph()->Int32Constant(WasmExportedFunctionData::kInstanceOffset -
|
jsgraph()->Int32Constant(WasmExportedFunctionData::kInstanceOffset -
|
||||||
@ -4345,7 +4380,18 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildJSToWasmWrapper(uint32_t wasm_func_index, Address call_target) {
|
Node* BuildLoadFunctionIndexFromExportedFunctionData(Node* function_data) {
|
||||||
|
Node* function_index_smi = *effect_ = graph()->NewNode(
|
||||||
|
jsgraph()->machine()->Load(MachineType::AnyTagged()), function_data,
|
||||||
|
jsgraph()->Int32Constant(
|
||||||
|
WasmExportedFunctionData::kFunctionIndexOffset - kHeapObjectTag),
|
||||||
|
*effect_, *control_);
|
||||||
|
Node* function_index = BuildChangeSmiToInt32(function_index_smi);
|
||||||
|
return function_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildJSToWasmWrapper(Address jump_table_start, bool is_import,
|
||||||
|
uint32_t num_imported_functions) {
|
||||||
const int wasm_count = static_cast<int>(sig_->parameter_count());
|
const int wasm_count = static_cast<int>(sig_->parameter_count());
|
||||||
|
|
||||||
// Build the start and the JS parameter nodes.
|
// Build the start and the JS parameter nodes.
|
||||||
@ -4363,12 +4409,13 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"),
|
Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"),
|
||||||
graph()->start());
|
graph()->start());
|
||||||
|
|
||||||
// Create the instance_node node to pass as parameter. It is loaded from the
|
// Create the instance_node node to pass as parameter. It is loaded from
|
||||||
// an actual reference to an instance or a placeholder reference,
|
// an actual reference to an instance or a placeholder reference,
|
||||||
// called {WasmExportedFunction} via the {WasmExportedFunctionData}
|
// called {WasmExportedFunction} via the {WasmExportedFunctionData}
|
||||||
// structure. since JSToWasm wrappers can be compiled at module compile time
|
// structure.
|
||||||
// and patched at instance build time.
|
Node* function_data = BuildLoadFunctionDataFromExportedFunction(js_closure);
|
||||||
instance_node_.set(BuildLoadInstanceFromExportedFunction(js_closure));
|
instance_node_.set(
|
||||||
|
BuildLoadInstanceFromExportedFunctionData(function_data));
|
||||||
|
|
||||||
if (!wasm::IsJSCompatibleSignature(sig_)) {
|
if (!wasm::IsJSCompatibleSignature(sig_)) {
|
||||||
// Throw a TypeError. Use the js_context of the calling javascript
|
// Throw a TypeError. Use the js_context of the calling javascript
|
||||||
@ -4394,16 +4441,32 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
// Set the ThreadInWasm flag before we do the actual call.
|
// Set the ThreadInWasm flag before we do the actual call.
|
||||||
BuildModifyThreadInWasmFlag(true);
|
BuildModifyThreadInWasmFlag(true);
|
||||||
|
|
||||||
if (env_ && wasm_func_index < env_->module->num_imported_functions) {
|
// Load function index from {WasmExportedFunctionData}.
|
||||||
|
Node* function_index =
|
||||||
|
BuildLoadFunctionIndexFromExportedFunctionData(function_data);
|
||||||
|
|
||||||
|
if (is_import) {
|
||||||
// Call to an imported function.
|
// Call to an imported function.
|
||||||
DCHECK_EQ(kNullAddress, call_target);
|
|
||||||
BuildImportWasmCall(sig_, args, &rets, wasm::kNoCodePosition,
|
BuildImportWasmCall(sig_, args, &rets, wasm::kNoCodePosition,
|
||||||
wasm_func_index);
|
function_index);
|
||||||
} else {
|
} else {
|
||||||
// Call to a wasm function defined in this module.
|
// Call to a wasm function defined in this module.
|
||||||
DCHECK_NE(kNullAddress, call_target);
|
// The call target is the jump table slot for that function. This is
|
||||||
args[0] = mcgraph()->RelocatableIntPtrConstant(
|
// {jump_table + (func_index - num_imports) * kJumpTableSlotSize}.
|
||||||
call_target, RelocInfo::JS_TO_WASM_CALL);
|
// Compute as
|
||||||
|
// jump_table_adjusted (static) := jump_table - num_imports * kJTSS.
|
||||||
|
// call_target := jump_table_adjusted + func_index * kJTSS.
|
||||||
|
Node* jump_table_adjusted = mcgraph()->IntPtrConstant(
|
||||||
|
jump_table_start - num_imported_functions *
|
||||||
|
wasm::JumpTableAssembler::kJumpTableSlotSize);
|
||||||
|
Node* jump_table_offset = graph()->NewNode(
|
||||||
|
mcgraph()->machine()->IntMul(), Uint32ToUintptr(function_index),
|
||||||
|
mcgraph()->IntPtrConstant(
|
||||||
|
wasm::JumpTableAssembler::kJumpTableSlotSize));
|
||||||
|
Node* jump_table_slot =
|
||||||
|
graph()->NewNode(mcgraph()->machine()->IntAdd(), jump_table_adjusted,
|
||||||
|
jump_table_offset);
|
||||||
|
args[0] = jump_table_slot;
|
||||||
|
|
||||||
BuildWasmCall(sig_, args, &rets, wasm::kNoCodePosition, nullptr,
|
BuildWasmCall(sig_, args, &rets, wasm::kNoCodePosition, nullptr,
|
||||||
kNoRetpoline);
|
kNoRetpoline);
|
||||||
@ -4726,12 +4789,13 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
MaybeHandle<Code> CompileJSToWasmWrapper(
|
MaybeHandle<Code> CompileJSToWasmWrapper(
|
||||||
Isolate* isolate, const wasm::WasmModule* module, Address call_target,
|
Isolate* isolate, const wasm::NativeModule* native_module,
|
||||||
uint32_t index, wasm::UseTrapHandler use_trap_handler) {
|
wasm::FunctionSig* sig, bool is_import,
|
||||||
const wasm::WasmFunction* func = &module->functions[index];
|
wasm::UseTrapHandler use_trap_handler) {
|
||||||
|
const wasm::WasmModule* module = native_module->module();
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// Create the Graph
|
// Create the Graph.
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
Zone zone(isolate->allocator(), ZONE_NAME);
|
Zone zone(isolate->allocator(), ZONE_NAME);
|
||||||
Graph graph(&zone);
|
Graph graph(&zone);
|
||||||
@ -4746,11 +4810,12 @@ MaybeHandle<Code> CompileJSToWasmWrapper(
|
|||||||
Node* effect = nullptr;
|
Node* effect = nullptr;
|
||||||
|
|
||||||
wasm::ModuleEnv env(module, use_trap_handler, wasm::kRuntimeExceptionSupport);
|
wasm::ModuleEnv env(module, use_trap_handler, wasm::kRuntimeExceptionSupport);
|
||||||
WasmWrapperGraphBuilder builder(&zone, &env, &jsgraph, func->sig, nullptr,
|
WasmWrapperGraphBuilder builder(&zone, &env, &jsgraph, sig, nullptr,
|
||||||
StubCallMode::kCallOnHeapBuiltin);
|
StubCallMode::kCallOnHeapBuiltin);
|
||||||
builder.set_control_ptr(&control);
|
builder.set_control_ptr(&control);
|
||||||
builder.set_effect_ptr(&effect);
|
builder.set_effect_ptr(&effect);
|
||||||
builder.BuildJSToWasmWrapper(index, call_target);
|
builder.BuildJSToWasmWrapper(native_module->jump_table_start(), is_import,
|
||||||
|
module->num_imported_functions);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// Run the compilation pipeline.
|
// Run the compilation pipeline.
|
||||||
@ -4771,8 +4836,7 @@ MaybeHandle<Code> CompileJSToWasmWrapper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Schedule and compile to machine code.
|
// Schedule and compile to machine code.
|
||||||
int params =
|
int params = static_cast<int>(sig->parameter_count());
|
||||||
static_cast<int>(module->functions[index].sig->parameter_count());
|
|
||||||
CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
|
CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
|
||||||
&zone, false, params + 1, CallDescriptor::kNoFlags);
|
&zone, false, params + 1, CallDescriptor::kNoFlags);
|
||||||
|
|
||||||
|
@ -114,10 +114,11 @@ MaybeHandle<Code> CompileWasmToJSWrapper(Isolate*, Handle<JSReceiver> target,
|
|||||||
wasm::ModuleOrigin,
|
wasm::ModuleOrigin,
|
||||||
wasm::UseTrapHandler);
|
wasm::UseTrapHandler);
|
||||||
|
|
||||||
// Wraps a given wasm code object, producing a code object.
|
// Creates a code object calling a wasm function with the given signature,
|
||||||
|
// callable from JS.
|
||||||
V8_EXPORT_PRIVATE MaybeHandle<Code> CompileJSToWasmWrapper(
|
V8_EXPORT_PRIVATE MaybeHandle<Code> CompileJSToWasmWrapper(
|
||||||
Isolate*, const wasm::WasmModule*, Address call_target, uint32_t index,
|
Isolate*, const wasm::NativeModule*, wasm::FunctionSig*, bool is_import,
|
||||||
wasm::UseTrapHandler);
|
wasm::UseTrapHandler use_trap_handler);
|
||||||
|
|
||||||
// Compiles a stub that redirects a call to a wasm function to the wasm
|
// Compiles a stub that redirects a call to a wasm function to the wasm
|
||||||
// interpreter. It's ABI compatible with the compiled wasm function.
|
// interpreter. It's ABI compatible with the compiled wasm function.
|
||||||
@ -393,6 +394,8 @@ class WasmGraphBuilder {
|
|||||||
UseRetpoline use_retpoline);
|
UseRetpoline use_retpoline);
|
||||||
Node* BuildImportWasmCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
|
Node* BuildImportWasmCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
|
||||||
wasm::WasmCodePosition position, int func_index);
|
wasm::WasmCodePosition position, int func_index);
|
||||||
|
Node* BuildImportWasmCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
|
||||||
|
wasm::WasmCodePosition position, Node* func_index);
|
||||||
|
|
||||||
Node* BuildF32CopySign(Node* left, Node* right);
|
Node* BuildF32CopySign(Node* left, Node* right);
|
||||||
Node* BuildF64CopySign(Node* left, Node* right);
|
Node* BuildF64CopySign(Node* left, Node* right);
|
||||||
|
@ -171,46 +171,35 @@ namespace {
|
|||||||
|
|
||||||
class JSToWasmWrapperCache {
|
class JSToWasmWrapperCache {
|
||||||
public:
|
public:
|
||||||
Handle<Code> CloneOrCompileJSToWasmWrapper(
|
Handle<Code> GetOrCompileJSToWasmWrapper(
|
||||||
Isolate* isolate, const wasm::WasmModule* module, Address call_target,
|
Isolate* isolate, const wasm::NativeModule* native_module,
|
||||||
uint32_t index, wasm::UseTrapHandler use_trap_handler) {
|
uint32_t func_index, wasm::UseTrapHandler use_trap_handler) {
|
||||||
const bool is_import = index < module->num_imported_functions;
|
const wasm::WasmModule* module = native_module->module();
|
||||||
DCHECK_EQ(is_import, call_target == kNullAddress);
|
const wasm::WasmFunction* func = &module->functions[func_index];
|
||||||
const wasm::WasmFunction* func = &module->functions[index];
|
bool is_import = func_index < module->num_imported_functions;
|
||||||
// We cannot cache js-to-wasm wrappers for imports, as they hard-code the
|
auto& cache = cache_[is_import ? 1 : 0];
|
||||||
// function index.
|
int cached_idx = cache.sig_map.Find(func->sig);
|
||||||
if (!is_import) {
|
if (cached_idx >= 0) return cache.code_cache[cached_idx];
|
||||||
int cached_idx = sig_map_.Find(func->sig);
|
|
||||||
if (cached_idx >= 0) {
|
|
||||||
Handle<Code> code =
|
|
||||||
isolate->factory()->CopyCode(code_cache_[cached_idx]);
|
|
||||||
// Now patch the call to wasm code.
|
|
||||||
RelocIterator it(*code,
|
|
||||||
RelocInfo::ModeMask(RelocInfo::JS_TO_WASM_CALL));
|
|
||||||
// If there is no reloc info, then it's an incompatible signature or
|
|
||||||
// calls an import.
|
|
||||||
if (!it.done()) it.rinfo()->set_js_to_wasm_address(call_target);
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle<Code> code =
|
Handle<Code> code =
|
||||||
compiler::CompileJSToWasmWrapper(isolate, module, call_target, index,
|
compiler::CompileJSToWasmWrapper(isolate, native_module, func->sig,
|
||||||
use_trap_handler)
|
is_import, use_trap_handler)
|
||||||
.ToHandleChecked();
|
.ToHandleChecked();
|
||||||
if (!is_import) {
|
uint32_t new_cache_idx = cache.sig_map.FindOrInsert(func->sig);
|
||||||
uint32_t new_cache_idx = sig_map_.FindOrInsert(func->sig);
|
DCHECK_EQ(cache.code_cache.size(), new_cache_idx);
|
||||||
DCHECK_EQ(code_cache_.size(), new_cache_idx);
|
USE(new_cache_idx);
|
||||||
USE(new_cache_idx);
|
cache.code_cache.push_back(code);
|
||||||
code_cache_.push_back(code);
|
|
||||||
}
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// sig_map_ maps signatures to an index in code_cache_.
|
// We generate different code for calling imports than calling wasm functions
|
||||||
wasm::SignatureMap sig_map_;
|
// in this module. Both are cached separately.
|
||||||
std::vector<Handle<Code>> code_cache_;
|
// [0] for non-imports, [1] for imports.
|
||||||
|
struct Cache {
|
||||||
|
wasm::SignatureMap sig_map;
|
||||||
|
std::vector<Handle<Code>> code_cache;
|
||||||
|
} cache_[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
// A helper class to simplify instantiating a module from a module object.
|
// A helper class to simplify instantiating a module from a module object.
|
||||||
@ -1254,13 +1243,9 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
|
|||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
if (module_->start_function_index >= 0) {
|
if (module_->start_function_index >= 0) {
|
||||||
int start_index = module_->start_function_index;
|
int start_index = module_->start_function_index;
|
||||||
Address start_call_address =
|
|
||||||
static_cast<uint32_t>(start_index) < module_->num_imported_functions
|
|
||||||
? kNullAddress
|
|
||||||
: native_module->GetCallTargetForFunction(start_index);
|
|
||||||
FunctionSig* sig = module_->functions[start_index].sig;
|
FunctionSig* sig = module_->functions[start_index].sig;
|
||||||
Handle<Code> wrapper_code = js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
|
Handle<Code> wrapper_code = js_to_wasm_cache_.GetOrCompileJSToWasmWrapper(
|
||||||
isolate_, module_, start_call_address, start_index, use_trap_handler());
|
isolate_, native_module, start_index, use_trap_handler());
|
||||||
// TODO(clemensh): Don't generate an exported function for the start
|
// TODO(clemensh): Don't generate an exported function for the start
|
||||||
// function. Use CWasmEntry instead.
|
// function. Use CWasmEntry instead.
|
||||||
start_function_ = WasmExportedFunction::New(
|
start_function_ = WasmExportedFunction::New(
|
||||||
@ -2135,9 +2120,8 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
|
|||||||
// at module compile time and cached instead.
|
// at module compile time and cached instead.
|
||||||
|
|
||||||
Handle<Code> wrapper_code =
|
Handle<Code> wrapper_code =
|
||||||
js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
|
js_to_wasm_cache_.GetOrCompileJSToWasmWrapper(
|
||||||
isolate_, module_, is_import ? kNullAddress : call_target,
|
isolate_, native_module, func_index, use_trap_handler());
|
||||||
func_index, use_trap_handler());
|
|
||||||
MaybeHandle<String> func_name;
|
MaybeHandle<String> func_name;
|
||||||
if (module_->origin == kAsmJsOrigin) {
|
if (module_->origin == kAsmJsOrigin) {
|
||||||
// For modules arising from asm.js, honor the names section.
|
// For modules arising from asm.js, honor the names section.
|
||||||
@ -3050,15 +3034,11 @@ void CompileJsToWasmWrappers(Isolate* isolate,
|
|||||||
NativeModule* native_module = module_object->native_module();
|
NativeModule* native_module = module_object->native_module();
|
||||||
wasm::UseTrapHandler use_trap_handler =
|
wasm::UseTrapHandler use_trap_handler =
|
||||||
native_module->use_trap_handler() ? kUseTrapHandler : kNoTrapHandler;
|
native_module->use_trap_handler() ? kUseTrapHandler : kNoTrapHandler;
|
||||||
const WasmModule* module = module_object->module();
|
const WasmModule* module = native_module->module();
|
||||||
for (auto exp : module->export_table) {
|
for (auto exp : module->export_table) {
|
||||||
if (exp.kind != kExternalFunction) continue;
|
if (exp.kind != kExternalFunction) continue;
|
||||||
Address call_target =
|
Handle<Code> wrapper_code = js_to_wasm_cache.GetOrCompileJSToWasmWrapper(
|
||||||
exp.index < module->num_imported_functions
|
isolate, native_module, exp.index, use_trap_handler);
|
||||||
? kNullAddress
|
|
||||||
: native_module->GetCallTargetForFunction(exp.index);
|
|
||||||
Handle<Code> wrapper_code = js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(
|
|
||||||
isolate, module, call_target, exp.index, use_trap_handler);
|
|
||||||
export_wrappers->set(wrapper_index, *wrapper_code);
|
export_wrappers->set(wrapper_index, *wrapper_code);
|
||||||
RecordStats(*wrapper_code, isolate->counters());
|
RecordStats(*wrapper_code, isolate->counters());
|
||||||
++wrapper_index;
|
++wrapper_index;
|
||||||
|
@ -279,6 +279,10 @@ class V8_EXPORT_PRIVATE NativeModule final {
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Address jump_table_start() const {
|
||||||
|
return jump_table_ ? jump_table_->instruction_start() : kNullAddress;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_jump_table_slot(Address address) const {
|
bool is_jump_table_slot(Address address) const {
|
||||||
return jump_table_->contains(address);
|
return jump_table_->contains(address);
|
||||||
}
|
}
|
||||||
|
@ -501,10 +501,10 @@ class WasmExportedFunctionData : public Struct {
|
|||||||
DECL_VERIFIER(WasmExportedFunctionData)
|
DECL_VERIFIER(WasmExportedFunctionData)
|
||||||
|
|
||||||
// Layout description.
|
// Layout description.
|
||||||
#define WASM_EXPORTED_FUNCTION_DATA_FIELDS(V) \
|
#define WASM_EXPORTED_FUNCTION_DATA_FIELDS(V) \
|
||||||
V(kWrapperCodeOffset, kPointerSize) \
|
V(kWrapperCodeOffset, kPointerSize) \
|
||||||
V(kInstanceOffset, kPointerSize) \
|
V(kInstanceOffset, kPointerSize) \
|
||||||
V(kFunctionIndexOffset, kPointerSize) \
|
V(kFunctionIndexOffset, kPointerSize) /* Smi */ \
|
||||||
V(kSize, 0)
|
V(kSize, 0)
|
||||||
|
|
||||||
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
|
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
|
||||||
|
@ -122,15 +122,14 @@ uint32_t TestingModuleBuilder::AddFunction(FunctionSig* sig, const char* name,
|
|||||||
Handle<JSFunction> TestingModuleBuilder::WrapCode(uint32_t index) {
|
Handle<JSFunction> TestingModuleBuilder::WrapCode(uint32_t index) {
|
||||||
// Wrap the code so it can be called as a JS function.
|
// Wrap the code so it can be called as a JS function.
|
||||||
Link();
|
Link();
|
||||||
Address target = native_module_->GetCallTargetForFunction(index);
|
FunctionSig* sig = test_module_->functions[index].sig;
|
||||||
MaybeHandle<Code> maybe_ret_code = compiler::CompileJSToWasmWrapper(
|
MaybeHandle<Code> maybe_ret_code = compiler::CompileJSToWasmWrapper(
|
||||||
isolate_, test_module_ptr_, target, index,
|
isolate_, native_module_, sig, false,
|
||||||
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler);
|
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler);
|
||||||
Handle<Code> ret_code = maybe_ret_code.ToHandleChecked();
|
Handle<Code> ret_code = maybe_ret_code.ToHandleChecked();
|
||||||
Handle<JSFunction> ret = WasmExportedFunction::New(
|
Handle<JSFunction> ret = WasmExportedFunction::New(
|
||||||
isolate_, instance_object(), MaybeHandle<String>(),
|
isolate_, instance_object(), MaybeHandle<String>(),
|
||||||
static_cast<int>(index),
|
static_cast<int>(index), static_cast<int>(sig->parameter_count()),
|
||||||
static_cast<int>(test_module_->functions[index].sig->parameter_count()),
|
|
||||||
ret_code);
|
ret_code);
|
||||||
|
|
||||||
// Add reference to the exported wrapper code.
|
// Add reference to the exported wrapper code.
|
||||||
|
Loading…
Reference in New Issue
Block a user