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

Generated by: LCOV version 1.10