8 #include "src/api-inl.h" 9 #include "src/assembler-inl.h" 10 #include "src/compiler/wasm-compiler.h" 11 #include "src/debug/interface-types.h" 12 #include "src/frames-inl.h" 13 #include "src/objects.h" 14 #include "src/objects/js-array-inl.h" 15 #include "src/property-descriptor.h" 16 #include "src/simulator.h" 17 #include "src/snapshot/snapshot.h" 19 #include "src/wasm/module-decoder.h" 20 #include "src/wasm/wasm-code-manager.h" 21 #include "src/wasm/wasm-js.h" 22 #include "src/wasm/wasm-module.h" 23 #include "src/wasm/wasm-objects-inl.h" 24 #include "src/wasm/wasm-result.h" 30 WireBytesRef WasmModule::LookupFunctionName(
const ModuleWireBytes& wire_bytes,
32 if (!function_names) {
33 function_names.reset(
new std::unordered_map<uint32_t, WireBytesRef>());
34 DecodeFunctionNames(wire_bytes.start(), wire_bytes.end(),
35 function_names.get());
37 auto it = function_names->find(function_index);
38 if (it == function_names->end())
return WireBytesRef();
42 void WasmModule::AddFunctionNameForTesting(
int function_index,
44 if (!function_names) {
45 function_names.reset(
new std::unordered_map<uint32_t, WireBytesRef>());
47 function_names->insert(std::make_pair(function_index, name));
51 WasmName ModuleWireBytes::GetNameOrNull(WireBytesRef ref)
const {
52 if (!ref.is_set())
return {
nullptr, 0};
53 CHECK(BoundsCheck(ref.offset(), ref.length()));
54 return WasmName::cast(
55 module_bytes_.SubVector(ref.offset(), ref.end_offset()));
59 WasmName ModuleWireBytes::GetNameOrNull(
const WasmFunction*
function,
60 const WasmModule* module)
const {
61 return GetNameOrNull(module->LookupFunctionName(*
this, function->func_index));
64 std::ostream& operator<<(std::ostream& os,
const WasmFunctionName& name) {
65 os <<
"#" << name.function_->func_index;
66 if (!name.name_.is_empty()) {
67 if (name.name_.start()) {
69 os.write(name.name_.start(), name.name_.length());
77 WasmModule::WasmModule(std::unique_ptr<Zone> signature_zone)
78 : signature_zone(
std::move(signature_zone)) {}
80 bool IsWasmCodegenAllowed(Isolate* isolate, Handle<Context> context) {
85 if (
auto wasm_codegen_callback = isolate->allow_wasm_code_gen_callback()) {
86 return wasm_codegen_callback(
87 v8::Utils::ToLocal(context),
88 v8::Utils::ToLocal(isolate->factory()->empty_string()));
90 auto codegen_callback = isolate->allow_code_gen_callback();
91 return codegen_callback ==
nullptr ||
93 v8::Utils::ToLocal(context),
94 v8::Utils::ToLocal(isolate->factory()->empty_string()));
97 Handle<JSArray> GetImports(Isolate* isolate,
98 Handle<WasmModuleObject> module_object) {
99 Factory* factory = isolate->factory();
101 Handle<String> module_string = factory->InternalizeUtf8String(
"module");
102 Handle<String> name_string = factory->InternalizeUtf8String(
"name");
103 Handle<String> kind_string = factory->InternalizeUtf8String(
"kind");
105 Handle<String> function_string = factory->InternalizeUtf8String(
"function");
106 Handle<String> table_string = factory->InternalizeUtf8String(
"table");
107 Handle<String> memory_string = factory->InternalizeUtf8String(
"memory");
108 Handle<String> global_string = factory->InternalizeUtf8String(
"global");
109 Handle<String> exception_string = factory->InternalizeUtf8String(
"exception");
112 const WasmModule* module = module_object->module();
113 int num_imports =
static_cast<int>(module->import_table.size());
114 Handle<JSArray> array_object = factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
115 Handle<FixedArray> storage = factory->NewFixedArray(num_imports);
116 JSArray::SetContent(array_object, storage);
117 array_object->set_length(Smi::FromInt(num_imports));
119 Handle<JSFunction> object_function =
120 Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
123 for (
int index = 0; index < num_imports; ++index) {
124 const WasmImport&
import = module->import_table[index];
126 Handle<JSObject> entry = factory->NewJSObject(object_function);
128 Handle<String> import_kind;
129 switch (
import.kind) {
130 case kExternalFunction:
131 import_kind = function_string;
134 import_kind = table_string;
136 case kExternalMemory:
137 import_kind = memory_string;
139 case kExternalGlobal:
140 import_kind = global_string;
142 case kExternalException:
143 import_kind = exception_string;
149 MaybeHandle<String> import_module =
150 WasmModuleObject::ExtractUtf8StringFromModuleBytes(
151 isolate, module_object,
import.module_name);
153 MaybeHandle<String> import_name =
154 WasmModuleObject::ExtractUtf8StringFromModuleBytes(
155 isolate, module_object,
import.field_name);
157 JSObject::AddProperty(isolate, entry, module_string,
158 import_module.ToHandleChecked(), NONE);
159 JSObject::AddProperty(isolate, entry, name_string,
160 import_name.ToHandleChecked(), NONE);
161 JSObject::AddProperty(isolate, entry, kind_string, import_kind, NONE);
163 storage->set(index, *entry);
169 Handle<JSArray> GetExports(Isolate* isolate,
170 Handle<WasmModuleObject> module_object) {
171 Factory* factory = isolate->factory();
173 Handle<String> name_string = factory->InternalizeUtf8String(
"name");
174 Handle<String> kind_string = factory->InternalizeUtf8String(
"kind");
176 Handle<String> function_string = factory->InternalizeUtf8String(
"function");
177 Handle<String> table_string = factory->InternalizeUtf8String(
"table");
178 Handle<String> memory_string = factory->InternalizeUtf8String(
"memory");
179 Handle<String> global_string = factory->InternalizeUtf8String(
"global");
180 Handle<String> exception_string = factory->InternalizeUtf8String(
"exception");
183 const WasmModule* module = module_object->module();
184 int num_exports =
static_cast<int>(module->export_table.size());
185 Handle<JSArray> array_object = factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
186 Handle<FixedArray> storage = factory->NewFixedArray(num_exports);
187 JSArray::SetContent(array_object, storage);
188 array_object->set_length(Smi::FromInt(num_exports));
190 Handle<JSFunction> object_function =
191 Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
194 for (
int index = 0; index < num_exports; ++index) {
195 const WasmExport& exp = module->export_table[index];
197 Handle<String> export_kind;
199 case kExternalFunction:
200 export_kind = function_string;
203 export_kind = table_string;
205 case kExternalMemory:
206 export_kind = memory_string;
208 case kExternalGlobal:
209 export_kind = global_string;
211 case kExternalException:
212 export_kind = exception_string;
218 Handle<JSObject> entry = factory->NewJSObject(object_function);
220 MaybeHandle<String> export_name =
221 WasmModuleObject::ExtractUtf8StringFromModuleBytes(
222 isolate, module_object, exp.name);
224 JSObject::AddProperty(isolate, entry, name_string,
225 export_name.ToHandleChecked(), NONE);
226 JSObject::AddProperty(isolate, entry, kind_string, export_kind, NONE);
228 storage->set(index, *entry);
234 Handle<JSArray> GetCustomSections(Isolate* isolate,
235 Handle<WasmModuleObject> module_object,
236 Handle<String> name, ErrorThrower* thrower) {
237 Factory* factory = isolate->factory();
239 Vector<const uint8_t> wire_bytes =
240 module_object->native_module()->wire_bytes();
241 std::vector<CustomSectionOffset> custom_sections =
242 DecodeCustomSections(wire_bytes.start(), wire_bytes.end());
244 std::vector<Handle<Object>> matching_sections;
247 for (
auto& section : custom_sections) {
248 MaybeHandle<String> section_name =
249 WasmModuleObject::ExtractUtf8StringFromModuleBytes(
250 isolate, module_object, section.name);
252 if (!name->Equals(*section_name.ToHandleChecked()))
continue;
255 size_t size = section.payload.length();
257 size == 0 ? nullptr : isolate->array_buffer_allocator()->Allocate(size);
259 if (size && !memory) {
260 thrower->RangeError(
"out of memory allocating custom section data");
261 return Handle<JSArray>();
263 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
264 constexpr
bool is_external =
false;
265 JSArrayBuffer::Setup(buffer, isolate, is_external, memory, size);
266 memcpy(memory, wire_bytes.start() + section.payload.offset(),
267 section.payload.length());
269 matching_sections.push_back(buffer);
272 int num_custom_sections =
static_cast<int>(matching_sections.size());
273 Handle<JSArray> array_object = factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
274 Handle<FixedArray> storage = factory->NewFixedArray(num_custom_sections);
275 JSArray::SetContent(array_object, storage);
276 array_object->set_length(Smi::FromInt(num_custom_sections));
278 for (
int i = 0;
i < num_custom_sections;
i++) {
279 storage->set(
i, *matching_sections[
i]);
285 Handle<FixedArray> DecodeLocalNames(Isolate* isolate,
286 Handle<WasmModuleObject> module_object) {
287 Vector<const uint8_t> wire_bytes =
288 module_object->native_module()->wire_bytes();
289 LocalNames decoded_locals;
290 DecodeLocalNames(wire_bytes.start(), wire_bytes.end(), &decoded_locals);
291 Handle<FixedArray> locals_names =
292 isolate->factory()->NewFixedArray(decoded_locals.max_function_index + 1);
293 for (LocalNamesPerFunction& func : decoded_locals.names) {
294 Handle<FixedArray> func_locals_names =
295 isolate->factory()->NewFixedArray(func.max_local_index + 1);
296 locals_names->set(func.function_index, *func_locals_names);
297 for (LocalName& name : func.names) {
298 Handle<String> name_str =
299 WasmModuleObject::ExtractUtf8StringFromModuleBytes(
300 isolate, module_object, name.name)
302 func_locals_names->set(name.local_index, *name_str);
309 template <
typename T>
310 inline size_t VectorSize(
const std::vector<T>& vector) {
311 return sizeof(T) * vector.size();
315 size_t EstimateStoredSize(
const WasmModule* module) {
316 return sizeof(WasmModule) + VectorSize(module->globals) +
317 (module->signature_zone ? module->signature_zone->allocation_size()
319 VectorSize(module->signatures) + VectorSize(module->signature_ids) +
320 VectorSize(module->functions) + VectorSize(module->data_segments) +
321 VectorSize(module->tables) + VectorSize(module->import_table) +
322 VectorSize(module->export_table) + VectorSize(module->exceptions) +
323 VectorSize(module->table_inits);