LCOV - code coverage report
Current view: top level - src/wasm - wasm-module.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 142 149 95.3 %
Date: 2019-03-21 Functions: 13 13 100.0 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include <functional>
       6             : #include <memory>
       7             : 
       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"
      18             : #include "src/v8.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"
      25             : 
      26             : namespace v8 {
      27             : namespace internal {
      28             : namespace wasm {
      29             : 
      30      160240 : WireBytesRef WasmModule::LookupFunctionName(const ModuleWireBytes& wire_bytes,
      31             :                                             uint32_t function_index) const {
      32      160240 :   if (!function_names) {
      33      254580 :     function_names.reset(new std::unordered_map<uint32_t, WireBytesRef>());
      34             :     DecodeFunctionNames(wire_bytes.start(), wire_bytes.end(),
      35      127290 :                         function_names.get());
      36             :   }
      37             :   auto it = function_names->find(function_index);
      38      160240 :   if (it == function_names->end()) return WireBytesRef();
      39       15940 :   return it->second;
      40             : }
      41             : 
      42     1094352 : void WasmModule::AddFunctionNameForTesting(int function_index,
      43             :                                            WireBytesRef name) {
      44     1094352 :   if (!function_names) {
      45     2187896 :     function_names.reset(new std::unordered_map<uint32_t, WireBytesRef>());
      46             :   }
      47     2188704 :   function_names->insert(std::make_pair(function_index, name));
      48     1094352 : }
      49             : 
      50             : // Get a string stored in the module bytes representing a name.
      51      144572 : WasmName ModuleWireBytes::GetNameOrNull(WireBytesRef ref) const {
      52      144572 :   if (!ref.is_set()) return {nullptr, 0};  // no name.
      53         480 :   CHECK(BoundsCheck(ref.offset(), ref.length()));
      54             :   return WasmName::cast(
      55         480 :       module_bytes_.SubVector(ref.offset(), ref.end_offset()));
      56             : }
      57             : 
      58             : // Get a string stored in the module bytes representing a function name.
      59      144552 : WasmName ModuleWireBytes::GetNameOrNull(const WasmFunction* function,
      60             :                                         const WasmModule* module) const {
      61      144552 :   return GetNameOrNull(module->LookupFunctionName(*this, function->func_index));
      62             : }
      63             : 
      64        7649 : std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name) {
      65        7649 :   os << "#" << name.function_->func_index;
      66        7649 :   if (!name.name_.is_empty()) {
      67           0 :     if (name.name_.start()) {
      68           0 :       os << ":";
      69           0 :       os.write(name.name_.start(), name.name_.length());
      70             :     }
      71             :   } else {
      72        7649 :     os << "?";
      73             :   }
      74        7649 :   return os;
      75             : }
      76             : 
      77     1380184 : WasmModule::WasmModule(std::unique_ptr<Zone> signature_zone)
      78     5520736 :     : signature_zone(std::move(signature_zone)) {}
      79             : 
      80      154165 : bool IsWasmCodegenAllowed(Isolate* isolate, Handle<Context> context) {
      81             :   // TODO(wasm): Once wasm has its own CSP policy, we should introduce a
      82             :   // separate callback that includes information about the module about to be
      83             :   // compiled. For the time being, pass an empty string as placeholder for the
      84             :   // sources.
      85      154165 :   if (auto wasm_codegen_callback = isolate->allow_wasm_code_gen_callback()) {
      86             :     return wasm_codegen_callback(
      87             :         v8::Utils::ToLocal(context),
      88          96 :         v8::Utils::ToLocal(isolate->factory()->empty_string()));
      89             :   }
      90             :   auto codegen_callback = isolate->allow_code_gen_callback();
      91      154117 :   return codegen_callback == nullptr ||
      92          48 :          codegen_callback(
      93             :              v8::Utils::ToLocal(context),
      94             :              v8::Utils::ToLocal(isolate->factory()->empty_string()));
      95             : }
      96             : 
      97         144 : Handle<JSArray> GetImports(Isolate* isolate,
      98             :                            Handle<WasmModuleObject> module_object) {
      99             :   Factory* factory = isolate->factory();
     100             : 
     101         144 :   Handle<String> module_string = factory->InternalizeUtf8String("module");
     102         144 :   Handle<String> name_string = factory->InternalizeUtf8String("name");
     103         144 :   Handle<String> kind_string = factory->InternalizeUtf8String("kind");
     104             : 
     105         144 :   Handle<String> function_string = factory->InternalizeUtf8String("function");
     106         144 :   Handle<String> table_string = factory->InternalizeUtf8String("table");
     107         144 :   Handle<String> memory_string = factory->InternalizeUtf8String("memory");
     108         144 :   Handle<String> global_string = factory->InternalizeUtf8String("global");
     109         144 :   Handle<String> exception_string = factory->InternalizeUtf8String("exception");
     110             : 
     111             :   // Create the result array.
     112         288 :   const WasmModule* module = module_object->module();
     113         144 :   int num_imports = static_cast<int>(module->import_table.size());
     114         144 :   Handle<JSArray> array_object = factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
     115         144 :   Handle<FixedArray> storage = factory->NewFixedArray(num_imports);
     116         144 :   JSArray::SetContent(array_object, storage);
     117             :   array_object->set_length(Smi::FromInt(num_imports));
     118             : 
     119             :   Handle<JSFunction> object_function =
     120         432 :       Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
     121             : 
     122             :   // Populate the result array.
     123         288 :   for (int index = 0; index < num_imports; ++index) {
     124          72 :     const WasmImport& import = module->import_table[index];
     125             : 
     126          72 :     Handle<JSObject> entry = factory->NewJSObject(object_function);
     127             : 
     128             :     Handle<String> import_kind;
     129          72 :     switch (import.kind) {
     130             :       case kExternalFunction:
     131          16 :         import_kind = function_string;
     132          16 :         break;
     133             :       case kExternalTable:
     134          16 :         import_kind = table_string;
     135          16 :         break;
     136             :       case kExternalMemory:
     137          16 :         import_kind = memory_string;
     138          16 :         break;
     139             :       case kExternalGlobal:
     140          16 :         import_kind = global_string;
     141          16 :         break;
     142             :       case kExternalException:
     143           8 :         import_kind = exception_string;
     144           8 :         break;
     145             :       default:
     146           0 :         UNREACHABLE();
     147             :     }
     148             : 
     149             :     MaybeHandle<String> import_module =
     150             :         WasmModuleObject::ExtractUtf8StringFromModuleBytes(
     151          72 :             isolate, module_object, import.module_name);
     152             : 
     153             :     MaybeHandle<String> import_name =
     154             :         WasmModuleObject::ExtractUtf8StringFromModuleBytes(
     155          72 :             isolate, module_object, import.field_name);
     156             : 
     157          72 :     JSObject::AddProperty(isolate, entry, module_string,
     158          72 :                           import_module.ToHandleChecked(), NONE);
     159          72 :     JSObject::AddProperty(isolate, entry, name_string,
     160          72 :                           import_name.ToHandleChecked(), NONE);
     161          72 :     JSObject::AddProperty(isolate, entry, kind_string, import_kind, NONE);
     162             : 
     163         144 :     storage->set(index, *entry);
     164             :   }
     165             : 
     166         144 :   return array_object;
     167             : }
     168             : 
     169         136 : Handle<JSArray> GetExports(Isolate* isolate,
     170             :                            Handle<WasmModuleObject> module_object) {
     171             :   Factory* factory = isolate->factory();
     172             : 
     173         136 :   Handle<String> name_string = factory->InternalizeUtf8String("name");
     174         136 :   Handle<String> kind_string = factory->InternalizeUtf8String("kind");
     175             : 
     176         136 :   Handle<String> function_string = factory->InternalizeUtf8String("function");
     177         136 :   Handle<String> table_string = factory->InternalizeUtf8String("table");
     178         136 :   Handle<String> memory_string = factory->InternalizeUtf8String("memory");
     179         136 :   Handle<String> global_string = factory->InternalizeUtf8String("global");
     180         136 :   Handle<String> exception_string = factory->InternalizeUtf8String("exception");
     181             : 
     182             :   // Create the result array.
     183         272 :   const WasmModule* module = module_object->module();
     184         136 :   int num_exports = static_cast<int>(module->export_table.size());
     185         136 :   Handle<JSArray> array_object = factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
     186         136 :   Handle<FixedArray> storage = factory->NewFixedArray(num_exports);
     187         136 :   JSArray::SetContent(array_object, storage);
     188             :   array_object->set_length(Smi::FromInt(num_exports));
     189             : 
     190             :   Handle<JSFunction> object_function =
     191         408 :       Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
     192             : 
     193             :   // Populate the result array.
     194         312 :   for (int index = 0; index < num_exports; ++index) {
     195          88 :     const WasmExport& exp = module->export_table[index];
     196             : 
     197             :     Handle<String> export_kind;
     198          88 :     switch (exp.kind) {
     199             :       case kExternalFunction:
     200          24 :         export_kind = function_string;
     201          24 :         break;
     202             :       case kExternalTable:
     203          16 :         export_kind = table_string;
     204          16 :         break;
     205             :       case kExternalMemory:
     206          16 :         export_kind = memory_string;
     207          16 :         break;
     208             :       case kExternalGlobal:
     209          24 :         export_kind = global_string;
     210          24 :         break;
     211             :       case kExternalException:
     212           8 :         export_kind = exception_string;
     213           8 :         break;
     214             :       default:
     215           0 :         UNREACHABLE();
     216             :     }
     217             : 
     218          88 :     Handle<JSObject> entry = factory->NewJSObject(object_function);
     219             : 
     220             :     MaybeHandle<String> export_name =
     221             :         WasmModuleObject::ExtractUtf8StringFromModuleBytes(
     222          88 :             isolate, module_object, exp.name);
     223             : 
     224          88 :     JSObject::AddProperty(isolate, entry, name_string,
     225          88 :                           export_name.ToHandleChecked(), NONE);
     226          88 :     JSObject::AddProperty(isolate, entry, kind_string, export_kind, NONE);
     227             : 
     228         176 :     storage->set(index, *entry);
     229             :   }
     230             : 
     231         136 :   return array_object;
     232             : }
     233             : 
     234         248 : Handle<JSArray> GetCustomSections(Isolate* isolate,
     235             :                                   Handle<WasmModuleObject> module_object,
     236             :                                   Handle<String> name, ErrorThrower* thrower) {
     237             :   Factory* factory = isolate->factory();
     238             : 
     239             :   Vector<const uint8_t> wire_bytes =
     240         496 :       module_object->native_module()->wire_bytes();
     241             :   std::vector<CustomSectionOffset> custom_sections =
     242         248 :       DecodeCustomSections(wire_bytes.start(), wire_bytes.end());
     243             : 
     244             :   std::vector<Handle<Object>> matching_sections;
     245             : 
     246             :   // Gather matching sections.
     247         568 :   for (auto& section : custom_sections) {
     248             :     MaybeHandle<String> section_name =
     249             :         WasmModuleObject::ExtractUtf8StringFromModuleBytes(
     250         320 :             isolate, module_object, section.name);
     251             : 
     252         560 :     if (!name->Equals(*section_name.ToHandleChecked())) continue;
     253             : 
     254             :     // Make a copy of the payload data in the section.
     255          80 :     size_t size = section.payload.length();
     256             :     void* memory =
     257          80 :         size == 0 ? nullptr : isolate->array_buffer_allocator()->Allocate(size);
     258             : 
     259          80 :     if (size && !memory) {
     260           0 :       thrower->RangeError("out of memory allocating custom section data");
     261           0 :       return Handle<JSArray>();
     262             :     }
     263             :     Handle<JSArrayBuffer> buffer =
     264          80 :         isolate->factory()->NewJSArrayBuffer(SharedFlag::kNotShared);
     265             :     constexpr bool is_external = false;
     266          80 :     JSArrayBuffer::Setup(buffer, isolate, is_external, memory, size);
     267          80 :     memcpy(memory, wire_bytes.start() + section.payload.offset(),
     268             :            section.payload.length());
     269             : 
     270          80 :     matching_sections.push_back(buffer);
     271             :   }
     272             : 
     273         248 :   int num_custom_sections = static_cast<int>(matching_sections.size());
     274         248 :   Handle<JSArray> array_object = factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
     275         248 :   Handle<FixedArray> storage = factory->NewFixedArray(num_custom_sections);
     276         248 :   JSArray::SetContent(array_object, storage);
     277             :   array_object->set_length(Smi::FromInt(num_custom_sections));
     278             : 
     279         408 :   for (int i = 0; i < num_custom_sections; i++) {
     280         160 :     storage->set(i, *matching_sections[i]);
     281             :   }
     282             : 
     283         248 :   return array_object;
     284             : }
     285             : 
     286          20 : Handle<FixedArray> DecodeLocalNames(Isolate* isolate,
     287             :                                     Handle<WasmModuleObject> module_object) {
     288             :   Vector<const uint8_t> wire_bytes =
     289          40 :       module_object->native_module()->wire_bytes();
     290             :   LocalNames decoded_locals;
     291          20 :   DecodeLocalNames(wire_bytes.start(), wire_bytes.end(), &decoded_locals);
     292             :   Handle<FixedArray> locals_names =
     293          20 :       isolate->factory()->NewFixedArray(decoded_locals.max_function_index + 1);
     294          24 :   for (LocalNamesPerFunction& func : decoded_locals.names) {
     295             :     Handle<FixedArray> func_locals_names =
     296           4 :         isolate->factory()->NewFixedArray(func.max_local_index + 1);
     297           8 :     locals_names->set(func.function_index, *func_locals_names);
     298          16 :     for (LocalName& name : func.names) {
     299             :       Handle<String> name_str =
     300          24 :           WasmModuleObject::ExtractUtf8StringFromModuleBytes(
     301             :               isolate, module_object, name.name)
     302             :               .ToHandleChecked();
     303          24 :       func_locals_names->set(name.local_index, *name_str);
     304             :     }
     305             :   }
     306          40 :   return locals_names;
     307             : }
     308             : 
     309             : namespace {
     310             : template <typename T>
     311             : inline size_t VectorSize(const std::vector<T>& vector) {
     312    12386030 :   return sizeof(T) * vector.size();
     313             : }
     314             : }  // namespace
     315             : 
     316     1238603 : size_t EstimateStoredSize(const WasmModule* module) {
     317     3715809 :   return sizeof(WasmModule) + VectorSize(module->globals) +
     318             :          (module->signature_zone ? module->signature_zone->allocation_size()
     319     1238603 :                                  : 0) +
     320     2477206 :          VectorSize(module->signatures) + VectorSize(module->signature_ids) +
     321     2477206 :          VectorSize(module->functions) + VectorSize(module->data_segments) +
     322     2477206 :          VectorSize(module->tables) + VectorSize(module->import_table) +
     323     1238603 :          VectorSize(module->export_table) + VectorSize(module->exceptions) +
     324     1238603 :          VectorSize(module->elem_segments);
     325             : }
     326             : }  // namespace wasm
     327             : }  // namespace internal
     328      120216 : }  // namespace v8

Generated by: LCOV version 1.10