Commit 9635e1a3 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Move wire bytes to the NativeModule

The wire bytes are currently stored as {SeqOneByteString} on the JS
heap. In order to make the {NativeModule} isolate independent, and to
ensure fast access to the wire bytes, they should move to the native
heap.

R=titzer@chromium.org

Bug: chromium:854794, v8:7868, v8:7424
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: I36811ec87f780c5b1f6863cd6de89a165aa0b7d5
Reviewed-on: https://chromium-review.googlesource.com/1108208
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53977}
parent ada64800
......@@ -4371,7 +4371,9 @@ class V8_EXPORT WasmCompiledModule : public Object {
/**
* Get the wasm-encoded bytes that were used to compile this module.
*/
Local<String> GetWasmWireBytes();
BufferReference GetWasmWireBytesRef();
V8_DEPRECATE_SOON("Use GetWasmWireBytesRef version.",
Local<String> GetWasmWireBytes());
/**
* Serialize the compiled module. The serialized data does not include the
......
......@@ -7450,11 +7450,19 @@ MaybeLocal<Proxy> Proxy::New(Local<Context> context, Local<Object> local_target,
RETURN_ESCAPED(result);
}
Local<String> WasmCompiledModule::GetWasmWireBytes() {
WasmCompiledModule::BufferReference WasmCompiledModule::GetWasmWireBytesRef() {
i::Handle<i::WasmModuleObject> obj =
i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this));
i::Handle<i::String> wire_bytes(obj->module_bytes(), obj->GetIsolate());
return Local<String>::Cast(Utils::ToLocal(wire_bytes));
i::Vector<const uint8_t> bytes_vec = obj->native_module()->wire_bytes();
return {bytes_vec.start(), bytes_vec.size()};
}
Local<String> WasmCompiledModule::GetWasmWireBytes() {
BufferReference ref = GetWasmWireBytesRef();
CHECK_LE(ref.size, String::kMaxLength);
return String::NewFromOneByte(GetIsolate(), ref.start, NewStringType::kNormal,
static_cast<int>(ref.size))
.ToLocalChecked();
}
// Currently, wasm modules are bound, both to Isolate and to
......@@ -7466,16 +7474,13 @@ WasmCompiledModule::GetTransferrableModule() {
i::DisallowHeapAllocation no_gc;
WasmCompiledModule::SerializedModule compiled_part = Serialize();
Local<String> wire_bytes = GetWasmWireBytes();
size_t wire_size = static_cast<size_t>(wire_bytes->Length());
uint8_t* bytes = new uint8_t[wire_size];
wire_bytes->WriteOneByte(bytes, 0, wire_bytes->Length());
BufferReference wire_bytes_ref = GetWasmWireBytesRef();
size_t wire_size = wire_bytes_ref.size;
std::unique_ptr<uint8_t[]> wire_bytes_copy(new uint8_t[wire_size]);
memcpy(wire_bytes_copy.get(), wire_bytes_ref.start, wire_size);
return TransferrableModule(
std::move(compiled_part),
std::make_pair(
std::unique_ptr<const uint8_t[]>(const_cast<const uint8_t*>(bytes)),
wire_size));
return TransferrableModule(std::move(compiled_part),
{std::move(wire_bytes_copy), wire_size});
}
MaybeLocal<WasmCompiledModule> WasmCompiledModule::FromTransferrableModule(
......@@ -9491,9 +9496,8 @@ uint32_t debug::WasmScript::GetFunctionHash(int function_index) {
DCHECK_LE(0, function_index);
DCHECK_GT(module->functions.size(), function_index);
i::wasm::WasmFunction& func = module->functions[function_index];
i::SeqOneByteString* module_bytes = module_object->module_bytes();
i::wasm::ModuleWireBytes wire_bytes(
module_bytes->GetFlatContent().ToOneByteVector());
module_object->native_module()->wire_bytes());
i::Vector<const i::byte> function_bytes = wire_bytes.GetFunctionBytes(&func);
// TODO(herhut): Maybe also take module, name and signature into account.
return i::StringHasher::HashSequentialString(function_bytes.start(),
......
......@@ -1594,7 +1594,6 @@ void WasmModuleObject::WasmModuleObjectVerify(Isolate* isolate) {
VerifyObjectField(kExportWrappersOffset);
VerifyObjectField(kManagedModuleOffset);
CHECK(managed_module()->IsForeign());
VerifyObjectField(kModuleBytesOffset);
VerifyObjectField(kScriptOffset);
VerifyObjectField(kAsmJsOffsetTableOffset);
VerifyObjectField(kBreakPointInfosOffset);
......
......@@ -1770,7 +1770,6 @@ void WasmModuleObject::WasmModuleObjectPrint(std::ostream& os) { // NOLINT
os << "\n - module: " << module();
os << "\n - native module: " << native_module();
os << "\n - export wrappers: " << Brief(export_wrappers());
os << "\n - module bytes: " << Brief(module_bytes());
os << "\n - script: " << Brief(script());
os << "\n - asm_js_offset_table: " << Brief(asm_js_offset_table());
os << "\n - breakpoint_infos: " << Brief(breakpoint_infos());
......
......@@ -60,7 +60,7 @@ bool IsWasmInstantiateAllowed(v8::Isolate* isolate,
}
v8::Local<v8::WasmCompiledModule> module =
v8::Local<v8::WasmCompiledModule>::Cast(module_or_bytes);
return static_cast<uint32_t>(module->GetWasmWireBytes()->Length()) <=
return static_cast<uint32_t>(module->GetWasmWireBytesRef().size) <=
ctrls.MaxWasmBufferSize;
}
......
......@@ -879,15 +879,14 @@ Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) {
WriteTag(SerializationTag::kWasmModule);
WriteRawBytes(&encoding_tag, sizeof(encoding_tag));
Handle<String> wire_bytes(object->module_bytes(), isolate_);
int wire_bytes_length = wire_bytes->length();
WriteVarint<uint32_t>(wire_bytes_length);
wasm::NativeModule* native_module = object->native_module();
Vector<const uint8_t> wire_bytes = native_module->wire_bytes();
WriteVarint<uint32_t>(static_cast<uint32_t>(wire_bytes.size()));
uint8_t* destination;
if (ReserveRawBytes(wire_bytes_length).To(&destination)) {
String::WriteToFlat(*wire_bytes, destination, 0, wire_bytes_length);
if (ReserveRawBytes(wire_bytes.size()).To(&destination)) {
memcpy(destination, wire_bytes.start(), wire_bytes.size());
}
wasm::NativeModule* native_module = object->native_module();
size_t module_size =
wasm::GetSerializedNativeModuleSize(isolate_, native_module);
CHECK_GE(std::numeric_limits<uint32_t>::max(), module_size);
......
This diff is collapsed.
......@@ -139,7 +139,11 @@ class AsyncCompileJob {
Isolate* isolate_;
const std::shared_ptr<Counters> async_counters_;
// Copy of the module wire bytes, moved into the {native_module_} on it's
// creation.
std::unique_ptr<byte[]> bytes_copy_;
// Reference to the wire bytes (hold in {bytes_copy_} or as part of
// {native_module_}).
ModuleWireBytes wire_bytes_;
Handle<Context> context_;
std::unique_ptr<CompilationResultResolver> resolver_;
......
......@@ -678,6 +678,10 @@ Address NativeModule::AllocateForCode(size_t size) {
return mem.start;
}
const WasmModule* NativeModule::module() const {
return GetModuleEnv(compilation_state_.get())->module;
}
WasmCode* NativeModule::Lookup(Address pc) const {
if (owned_code_.empty()) return nullptr;
auto iter = std::upper_bound(owned_code_.begin(), owned_code_.end(), pc,
......
......@@ -324,6 +324,14 @@ class V8_EXPORT_PRIVATE NativeModule final {
bool use_trap_handler() const { return use_trap_handler_; }
void set_lazy_compile_frozen(bool frozen) { lazy_compile_frozen_ = frozen; }
bool lazy_compile_frozen() const { return lazy_compile_frozen_; }
Vector<const byte> wire_bytes() const {
return {wire_bytes_.get(), wire_bytes_len_};
}
void set_wire_bytes(std::unique_ptr<const byte[]> wire_bytes, size_t length) {
wire_bytes_ = std::move(wire_bytes);
wire_bytes_len_ = length;
}
const WasmModule* module() const;
WasmCode* Lookup(Address) const;
......@@ -381,6 +389,9 @@ class V8_EXPORT_PRIVATE NativeModule final {
uint32_t num_imported_functions_;
std::unique_ptr<WasmCode* []> code_table_;
size_t wire_bytes_len_;
std::unique_ptr<const byte[]> wire_bytes_;
WasmCode* runtime_stub_table_[WasmCode::kRuntimeStubCount] = {nullptr};
// Jump table used to easily redirect wasm function calls.
......
......@@ -46,9 +46,9 @@ class PatchDirectCallsHelper {
PatchDirectCallsHelper(NativeModule* native_module, const WasmCode* code)
: source_pos_it(code->source_positions()), decoder(nullptr, nullptr) {
uint32_t func_index = code->index();
WasmModuleObject* module_object = native_module->module_object();
func_bytes = module_object->module_bytes()->GetChars() +
module_object->module()->functions[func_index].code.offset();
const WasmModule* module = native_module->module();
func_bytes = native_module->wire_bytes().start() +
module->functions[func_index].code.offset();
}
SourcePositionTableIterator source_pos_it;
......
......@@ -133,9 +133,9 @@ class InterpreterHandle {
static Vector<const byte> GetBytes(WasmDebugInfo* debug_info) {
// Return raw pointer into heap. The WasmInterpreter will make its own copy
// of this data anyway, and there is no heap allocation in-between.
SeqOneByteString* bytes_str =
debug_info->wasm_instance()->module_object()->module_bytes();
return {bytes_str->GetChars(), static_cast<size_t>(bytes_str->length())};
NativeModule* native_module =
debug_info->wasm_instance()->module_object()->native_module();
return native_module->wire_bytes();
}
public:
......
......@@ -36,11 +36,11 @@ constexpr const char* WasmException::kRuntimeIdStr;
// static
constexpr const char* WasmException::kRuntimeValuesStr;
WireBytesRef WasmModule::LookupName(const ModuleWireBytes* wire_bytes,
WireBytesRef WasmModule::LookupName(const ModuleWireBytes& wire_bytes,
uint32_t function_index) const {
if (!names_) {
names_.reset(new std::unordered_map<uint32_t, WireBytesRef>());
wasm::DecodeFunctionNames(wire_bytes->start(), wire_bytes->end(),
wasm::DecodeFunctionNames(wire_bytes.start(), wire_bytes.end(),
names_.get());
}
auto it = names_->find(function_index);
......@@ -53,7 +53,7 @@ WireBytesRef WasmModule::LookupName(SeqOneByteString* wire_bytes,
DisallowHeapAllocation no_gc;
uint8_t* chars = wire_bytes->GetChars();
ModuleWireBytes module_wire_bytes(chars, chars + wire_bytes->length());
return LookupName(&module_wire_bytes, function_index);
return LookupName(module_wire_bytes, function_index);
}
void WasmModule::AddNameForTesting(int function_index, WireBytesRef name) {
......@@ -74,7 +74,7 @@ WasmName ModuleWireBytes::GetName(WireBytesRef ref) const {
// Get a string stored in the module bytes representing a function name.
WasmName ModuleWireBytes::GetName(const WasmFunction* function,
const WasmModule* module) const {
return GetName(module->LookupName(this, function->func_index));
return GetName(module->LookupName(*this, function->func_index));
}
// Get a string stored in the module bytes representing a name.
......@@ -88,7 +88,7 @@ WasmName ModuleWireBytes::GetNameOrNull(WireBytesRef ref) const {
// Get a string stored in the module bytes representing a function name.
WasmName ModuleWireBytes::GetNameOrNull(const WasmFunction* function,
const WasmModule* module) const {
return GetNameOrNull(module->LookupName(this, function->func_index));
return GetNameOrNull(module->LookupName(*this, function->func_index));
}
std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name) {
......@@ -258,16 +258,10 @@ Handle<JSArray> GetCustomSections(Isolate* isolate,
Handle<String> name, ErrorThrower* thrower) {
Factory* factory = isolate->factory();
std::vector<CustomSectionOffset> custom_sections;
{
DisallowHeapAllocation no_gc; // for raw access to string bytes.
Handle<SeqOneByteString> module_bytes(module_object->module_bytes(),
isolate);
const byte* start =
reinterpret_cast<const byte*>(module_bytes->GetCharsAddress());
const byte* end = start + module_bytes->length();
custom_sections = DecodeCustomSections(start, end);
}
Vector<const uint8_t> wire_bytes =
module_object->native_module()->wire_bytes();
std::vector<CustomSectionOffset> custom_sections =
DecodeCustomSections(wire_bytes.start(), wire_bytes.end());
std::vector<Handle<Object>> matching_sections;
......@@ -291,12 +285,8 @@ Handle<JSArray> GetCustomSections(Isolate* isolate,
Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
constexpr bool is_external = false;
JSArrayBuffer::Setup(buffer, isolate, is_external, memory, size);
DisallowHeapAllocation no_gc; // for raw access to string bytes.
Handle<SeqOneByteString> module_bytes(module_object->module_bytes(),
isolate);
const byte* start =
reinterpret_cast<const byte*>(module_bytes->GetCharsAddress());
memcpy(memory, start + section.payload.offset(), section.payload.length());
memcpy(memory, wire_bytes.start() + section.payload.offset(),
section.payload.length());
matching_sections.push_back(buffer);
}
......@@ -316,14 +306,10 @@ Handle<JSArray> GetCustomSections(Isolate* isolate,
Handle<FixedArray> DecodeLocalNames(Isolate* isolate,
Handle<WasmModuleObject> module_object) {
Handle<SeqOneByteString> wire_bytes(module_object->module_bytes(), isolate);
Vector<const uint8_t> wire_bytes =
module_object->native_module()->wire_bytes();
LocalNames decoded_locals;
{
DisallowHeapAllocation no_gc;
DecodeLocalNames(wire_bytes->GetChars(),
wire_bytes->GetChars() + wire_bytes->length(),
&decoded_locals);
}
DecodeLocalNames(wire_bytes.start(), wire_bytes.end(), &decoded_locals);
Handle<FixedArray> locals_names =
isolate->factory()->NewFixedArray(decoded_locals.max_function_index + 1);
for (LocalNamesPerFunction& func : decoded_locals.names) {
......
......@@ -172,7 +172,7 @@ struct V8_EXPORT_PRIVATE WasmModule {
WasmModule() : WasmModule(nullptr) {}
WasmModule(std::unique_ptr<Zone> owned);
WireBytesRef LookupName(const ModuleWireBytes* wire_bytes,
WireBytesRef LookupName(const ModuleWireBytes& wire_bytes,
uint32_t function_index) const;
WireBytesRef LookupName(SeqOneByteString* wire_bytes,
uint32_t function_index) const;
......
......@@ -56,7 +56,6 @@ ACCESSORS(WasmModuleObject, compiled_module, WasmCompiledModule,
ACCESSORS(WasmModuleObject, export_wrappers, FixedArray, kExportWrappersOffset)
ACCESSORS(WasmModuleObject, managed_module, Managed<wasm::WasmModule>,
kManagedModuleOffset)
ACCESSORS(WasmModuleObject, module_bytes, SeqOneByteString, kModuleBytesOffset)
ACCESSORS(WasmModuleObject, script, Script, kScriptOffset)
OPTIONAL_ACCESSORS(WasmModuleObject, asm_js_offset_table, ByteArray,
kAsmJsOffsetTableOffset)
......
......@@ -241,14 +241,13 @@ iterate_compiled_module_instance_chain(Isolate* isolate,
}
#ifdef DEBUG
bool IsBreakablePosition(WasmModuleObject* module_object, int func_index,
bool IsBreakablePosition(wasm::NativeModule* native_module, int func_index,
int offset_in_func) {
DisallowHeapAllocation no_gc;
AccountingAllocator alloc;
Zone tmp(&alloc, ZONE_NAME);
wasm::BodyLocalDecls locals(&tmp);
const byte* module_start = module_object->module_bytes()->GetChars();
WasmFunction& func = module_object->module()->functions[func_index];
const byte* module_start = native_module->wire_bytes().start();
const WasmFunction& func = native_module->module()->functions[func_index];
wasm::BytecodeIterator iterator(module_start + func.code.offset(),
module_start + func.code.end_offset(),
&locals);
......@@ -274,8 +273,8 @@ enum DispatchTableElements : int {
Handle<WasmModuleObject> WasmModuleObject::New(
Isolate* isolate, Handle<FixedArray> export_wrappers,
std::shared_ptr<wasm::WasmModule> shared_module, wasm::ModuleEnv& env,
Handle<SeqOneByteString> module_bytes, Handle<Script> script,
Handle<ByteArray> asm_js_offset_table) {
std::unique_ptr<const uint8_t[]> wire_bytes, size_t wire_bytes_len,
Handle<Script> script, Handle<ByteArray> asm_js_offset_table) {
WasmModule* module = shared_module.get();
DCHECK_EQ(module, env.module);
size_t module_size = EstimateWasmModuleSize(module);
......@@ -300,9 +299,6 @@ Handle<WasmModuleObject> WasmModuleObject::New(
script->set_wasm_module_object(*module_object);
}
module_object->set_managed_module(*managed_module);
if (!module_bytes.is_null()) {
module_object->set_module_bytes(*module_bytes);
}
if (!script.is_null()) {
module_object->set_script(*script);
}
......@@ -317,6 +313,7 @@ Handle<WasmModuleObject> WasmModuleObject::New(
auto native_module =
isolate->wasm_engine()->code_manager()->NewNativeModule(isolate, env);
native_module->SetModuleObject(module_object);
native_module->set_wire_bytes(std::move(wire_bytes), wire_bytes_len);
native_module->SetRuntimeStubs(isolate);
Handle<Managed<wasm::NativeModule>> managed_native_module =
Managed<wasm::NativeModule>::FromUniquePtr(isolate, memory_estimate,
......@@ -339,7 +336,8 @@ bool WasmModuleObject::SetBreakPoint(Handle<WasmModuleObject> module_object,
// According to the current design, we should only be called with valid
// breakable positions.
DCHECK(IsBreakablePosition(*module_object, func_index, offset_in_func));
DCHECK(IsBreakablePosition(module_object->native_module(), func_index,
offset_in_func));
// Insert new break point into break_positions of module object.
WasmModuleObject::AddBreakpoint(module_object, *position, break_point);
......@@ -611,14 +609,12 @@ v8::debug::WasmDisassembly WasmModuleObject::DisassembleFunction(
static_cast<uint32_t>(func_index) >= module()->functions.size())
return {};
SeqOneByteString* module_bytes_str = module_bytes();
Vector<const byte> module_bytes(module_bytes_str->GetChars(),
module_bytes_str->length());
Vector<const byte> wire_bytes = native_module()->wire_bytes();
std::ostringstream disassembly_os;
v8::debug::WasmDisassembly::OffsetTable offset_table;
PrintWasmText(module(), module_bytes, static_cast<uint32_t>(func_index),
PrintWasmText(module(), wire_bytes, static_cast<uint32_t>(func_index),
disassembly_os, &offset_table);
return {disassembly_os.str(), std::move(offset_table)};
......@@ -671,7 +667,7 @@ bool WasmModuleObject::GetPossibleBreakpoints(
AccountingAllocator alloc;
Zone tmp(&alloc, ZONE_NAME);
const byte* module_start = module_bytes()->GetChars();
const byte* module_start = native_module()->wire_bytes().start();
for (uint32_t func_idx = start_func_index; func_idx <= end_func_index;
++func_idx) {
......@@ -728,24 +724,20 @@ MaybeHandle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes(
Isolate* isolate, Handle<WasmModuleObject> module_object,
wasm::WireBytesRef ref) {
// TODO(wasm): cache strings from modules if it's a performance win.
Handle<SeqOneByteString> module_bytes(module_object->module_bytes(), isolate);
return ExtractUtf8StringFromModuleBytes(isolate, module_bytes, ref);
Vector<const uint8_t> wire_bytes =
module_object->native_module()->wire_bytes();
return ExtractUtf8StringFromModuleBytes(isolate, wire_bytes, ref);
}
MaybeHandle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes(
Isolate* isolate, Handle<SeqOneByteString> module_bytes,
Isolate* isolate, Vector<const uint8_t> wire_bytes,
wasm::WireBytesRef ref) {
DCHECK_GE(module_bytes->length(), ref.end_offset());
Vector<const uint8_t> name_vec = wire_bytes + ref.offset();
name_vec.Truncate(ref.length());
// UTF8 validation happens at decode time.
DCHECK(unibrow::Utf8::ValidateEncoding(
reinterpret_cast<const byte*>(module_bytes->GetCharsAddress() +
ref.offset()),
ref.length()));
DCHECK_GE(kMaxInt, ref.offset());
DCHECK_GE(kMaxInt, ref.length());
return isolate->factory()->NewStringFromUtf8SubString(
module_bytes, static_cast<int>(ref.offset()),
static_cast<int>(ref.length()));
DCHECK(unibrow::Utf8::ValidateEncoding(name_vec.start(), name_vec.length()));
return isolate->factory()->NewStringFromUtf8(
Vector<const char>::cast(name_vec));
}
MaybeHandle<String> WasmModuleObject::GetModuleNameOrNull(
......@@ -760,7 +752,8 @@ MaybeHandle<String> WasmModuleObject::GetFunctionNameOrNull(
uint32_t func_index) {
DCHECK_LT(func_index, module_object->module()->functions.size());
wasm::WireBytesRef name = module_object->module()->LookupName(
module_object->module_bytes(), func_index);
wasm::ModuleWireBytes(module_object->native_module()->wire_bytes()),
func_index);
if (!name.is_set()) return {};
return ExtractUtf8StringFromModuleBytes(isolate, module_object, name);
}
......@@ -777,12 +770,10 @@ Handle<String> WasmModuleObject::GetFunctionName(
Vector<const uint8_t> WasmModuleObject::GetRawFunctionName(
uint32_t func_index) {
DCHECK_GT(module()->functions.size(), func_index);
SeqOneByteString* bytes = module_bytes();
wasm::WireBytesRef name = module()->LookupName(bytes, func_index);
DCHECK_GE(bytes->length(), name.end_offset());
return Vector<const uint8_t>(
reinterpret_cast<uint8_t*>(bytes->GetCharsAddress() + name.offset()),
name.length());
wasm::ModuleWireBytes wire_bytes(native_module()->wire_bytes());
wasm::WireBytesRef name_ref = module()->LookupName(wire_bytes, func_index);
wasm::WasmName name = wire_bytes.GetName(name_ref);
return Vector<const uint8_t>::cast(name);
}
int WasmModuleObject::GetFunctionOffset(uint32_t func_index) {
......
......@@ -111,7 +111,6 @@ class WasmModuleObject : public JSObject {
DECL_ACCESSORS(export_wrappers, FixedArray)
DECL_ACCESSORS(managed_module, Managed<wasm::WasmModule>)
inline wasm::WasmModule* module() const;
DECL_ACCESSORS(module_bytes, SeqOneByteString)
DECL_ACCESSORS(script, Script)
DECL_OPTIONAL_ACCESSORS(asm_js_offset_table, ByteArray)
DECL_OPTIONAL_ACCESSORS(breakpoint_infos, FixedArray)
......@@ -127,7 +126,6 @@ class WasmModuleObject : public JSObject {
V(kCompiledModuleOffset, kPointerSize) \
V(kExportWrappersOffset, kPointerSize) \
V(kManagedModuleOffset, kPointerSize) \
V(kModuleBytesOffset, kPointerSize) \
V(kScriptOffset, kPointerSize) \
V(kAsmJsOffsetTableOffset, kPointerSize) \
V(kBreakPointInfosOffset, kPointerSize) \
......@@ -137,13 +135,11 @@ class WasmModuleObject : public JSObject {
WASM_MODULE_OBJECT_FIELDS)
#undef WASM_MODULE_OBJECT_FIELDS
static Handle<WasmModuleObject> New(Isolate* isolate,
Handle<FixedArray> export_wrappers,
std::shared_ptr<wasm::WasmModule> module,
wasm::ModuleEnv& env,
Handle<SeqOneByteString> module_bytes,
Handle<Script> script,
Handle<ByteArray> asm_js_offset_table);
static Handle<WasmModuleObject> New(
Isolate* isolate, Handle<FixedArray> export_wrappers,
std::shared_ptr<wasm::WasmModule> module, wasm::ModuleEnv& env,
std::unique_ptr<const uint8_t[]> wire_bytes, size_t wire_bytes_len,
Handle<Script> script, Handle<ByteArray> asm_js_offset_table);
// Set a breakpoint on the given byte position inside the given module.
// This will affect all live and future instances of the module.
......@@ -223,7 +219,7 @@ class WasmModuleObject : public JSObject {
static MaybeHandle<String> ExtractUtf8StringFromModuleBytes(
Isolate* isolate, Handle<WasmModuleObject>, wasm::WireBytesRef ref);
static MaybeHandle<String> ExtractUtf8StringFromModuleBytes(
Isolate* isolate, Handle<SeqOneByteString> module_bytes,
Isolate* isolate, Vector<const uint8_t> wire_byte,
wasm::WireBytesRef ref);
// Get a list of all possible breakpoints within a given range of this module.
......
......@@ -532,13 +532,6 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule(
if (!decode_result.ok()) return {};
CHECK_NOT_NULL(decode_result.val);
WasmModule* module = decode_result.val.get();
Handle<String> module_bytes =
isolate->factory()
->NewStringFromOneByte(
{wire_bytes.start(), static_cast<size_t>(wire_bytes.length())},
TENURED)
.ToHandleChecked();
DCHECK(module_bytes->IsSeqOneByteString());
Handle<Script> script = CreateWasmScript(isolate, wire_bytes);
int export_wrappers_size = static_cast<int>(module->num_exported_functions);
Handle<FixedArray> export_wrappers = isolate->factory()->NewFixedArray(
......@@ -550,10 +543,15 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule(
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler;
wasm::ModuleEnv env(module, use_trap_handler,
wasm::RuntimeExceptionSupport::kRuntimeExceptionSupport);
CHECK_LT(wire_bytes.size(), kMaxUInt32);
size_t wire_size = wire_bytes.size();
std::unique_ptr<uint8_t[]> wire_bytes_copy(new uint8_t[wire_size]);
memcpy(wire_bytes_copy.get(), wire_bytes.start(), wire_size);
Handle<WasmModuleObject> module_object = WasmModuleObject::New(
isolate, export_wrappers, std::move(decode_result.val), env,
Handle<SeqOneByteString>::cast(module_bytes), script,
Handle<ByteArray>::null());
std::move(wire_bytes_copy), wire_size, script, Handle<ByteArray>::null());
Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
isolate);
NativeModule* native_module = module_object->native_module();
......
......@@ -100,9 +100,11 @@ class WasmSerializationTest {
v8::Utils::OpenHandle(*deserialized_module));
{
DisallowHeapAllocation assume_no_gc;
CHECK_EQ(memcmp(reinterpret_cast<const uint8_t*>(
module_object->module_bytes()->GetCharsAddress()),
wire_bytes_.start, wire_bytes_.size),
Vector<const byte> deserialized_module_wire_bytes =
module_object->native_module()->wire_bytes();
CHECK_EQ(deserialized_module_wire_bytes.size(), wire_bytes_.size);
CHECK_EQ(memcmp(deserialized_module_wire_bytes.start(), wire_bytes_.start,
wire_bytes_.size),
0);
}
Handle<WasmInstanceObject> instance =
......@@ -141,8 +143,6 @@ class WasmSerializationTest {
Isolate* serialization_isolate = CcTest::InitIsolateOnce();
ErrorThrower thrower(serialization_isolate, "");
uint8_t* bytes = nullptr;
size_t bytes_size = 0;
{
HandleScope scope(serialization_isolate);
testing::SetupIsolateForWasmModule(serialization_isolate);
......@@ -163,18 +163,15 @@ class WasmSerializationTest {
v8::Local<v8::WasmCompiledModule> v8_compiled_module =
v8_module_obj.As<v8::WasmCompiledModule>();
v8::Local<v8::String> uncompiled_bytes =
v8_compiled_module->GetWasmWireBytes();
bytes_size = static_cast<size_t>(uncompiled_bytes->Length());
bytes = zone()->NewArray<uint8_t>(bytes_size);
uncompiled_bytes->WriteOneByte(bytes, 0, uncompiled_bytes->Length(),
v8::String::NO_NULL_TERMINATION);
v8::WasmCompiledModule::BufferReference uncompiled_bytes =
v8_compiled_module->GetWasmWireBytesRef();
uint8_t* bytes_copy = zone()->NewArray<uint8_t>(uncompiled_bytes.size);
memcpy(bytes_copy, uncompiled_bytes.start, uncompiled_bytes.size);
wire_bytes_ = {bytes_copy, uncompiled_bytes.size};
// keep alive data_ until the end
data_ = v8_compiled_module->Serialize();
}
wire_bytes_ = {const_cast<const uint8_t*>(bytes), bytes_size};
serialized_bytes_ = {data_.first.get(), data_.second};
v8::Isolate::CreateParams create_params;
......
......@@ -184,19 +184,16 @@ void TestingModuleBuilder::PopulateIndirectFunctionTable() {
}
uint32_t TestingModuleBuilder::AddBytes(Vector<const byte> bytes) {
Handle<WasmModuleObject> module_object(instance_object_->module_object(),
isolate_);
Handle<SeqOneByteString> old_bytes(module_object->module_bytes(), isolate_);
uint32_t old_size = static_cast<uint32_t>(old_bytes->length());
Vector<const uint8_t> old_bytes = native_module_->wire_bytes();
uint32_t old_size = static_cast<uint32_t>(old_bytes.size());
// Avoid placing strings at offset 0, this might be interpreted as "not
// set", e.g. for function names.
uint32_t bytes_offset = old_size ? old_size : 1;
ScopedVector<byte> new_bytes(bytes_offset + bytes.length());
memcpy(new_bytes.start(), old_bytes->GetChars(), old_size);
memcpy(new_bytes.start() + bytes_offset, bytes.start(), bytes.length());
Handle<SeqOneByteString> new_bytes_str = Handle<SeqOneByteString>::cast(
isolate_->factory()->NewStringFromOneByte(new_bytes).ToHandleChecked());
module_object->set_module_bytes(*new_bytes_str);
size_t new_size = bytes_offset + bytes.size();
std::unique_ptr<uint8_t[]> new_bytes(new uint8_t[new_size]);
memcpy(new_bytes.get(), old_bytes.start(), old_size);
memcpy(new_bytes.get() + bytes_offset, bytes.start(), bytes.length());
native_module_->set_wire_bytes(std::move(new_bytes), new_size);
return bytes_offset;
}
......@@ -219,8 +216,6 @@ const WasmGlobal* TestingModuleBuilder::AddGlobal(ValueType type) {
}
Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() {
Handle<SeqOneByteString> empty_string = Handle<SeqOneByteString>::cast(
isolate_->factory()->NewStringFromOneByte({}).ToHandleChecked());
Handle<Script> script =
isolate_->factory()->NewScript(isolate_->factory()->empty_string());
script->set_type(Script::TYPE_WASM);
......@@ -228,7 +223,7 @@ Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() {
ModuleEnv env = CreateModuleEnv();
Handle<WasmModuleObject> module_object =
WasmModuleObject::New(isolate_, export_wrappers, test_module_, env,
empty_string, script, Handle<ByteArray>::null());
nullptr, 0, script, Handle<ByteArray>::null());
Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
isolate_);
// This method is called when we initialize TestEnvironment. We don't
......@@ -416,19 +411,20 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
interpreter_->SetFunctionCodeForTesting(function_, start, end);
}
Handle<SeqOneByteString> wire_bytes(
builder_->instance_object()->module_object()->module_bytes(), isolate());
Vector<const uint8_t> wire_bytes = builder_->instance_object()
->module_object()
->native_module()
->wire_bytes();
ModuleEnv module_env = builder_->CreateModuleEnv();
ErrorThrower thrower(isolate(), "WasmFunctionCompiler::Build");
ScopedVector<uint8_t> func_wire_bytes(function_->code.length());
memcpy(func_wire_bytes.start(),
wire_bytes->GetChars() + function_->code.offset(),
memcpy(func_wire_bytes.start(), wire_bytes.start() + function_->code.offset(),
func_wire_bytes.length());
WireBytesRef func_name_ref =
module_env.module->LookupName(*wire_bytes, function_->func_index);
module_env.module->LookupName(wire_bytes, function_->func_index);
ScopedVector<char> func_name(func_name_ref.length());
memcpy(func_name.start(), wire_bytes->GetChars() + func_name_ref.offset(),
memcpy(func_name.start(), wire_bytes.start() + func_name_ref.offset(),
func_name_ref.length());
FunctionBody func_body{function_->sig, function_->code.offset(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment