LCOV - code coverage report
Current view: top level - src/wasm - wasm-module.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 140 148 94.6 %
Date: 2017-10-20 Functions: 11 11 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.h"
       9             : #include "src/assembler-inl.h"
      10             : #include "src/code-stubs.h"
      11             : #include "src/debug/interface-types.h"
      12             : #include "src/frames-inl.h"
      13             : #include "src/objects.h"
      14             : #include "src/property-descriptor.h"
      15             : #include "src/simulator.h"
      16             : #include "src/snapshot/snapshot.h"
      17             : #include "src/v8.h"
      18             : 
      19             : #include "src/compiler/wasm-compiler.h"
      20             : #include "src/wasm/compilation-manager.h"
      21             : #include "src/wasm/module-compiler.h"
      22             : #include "src/wasm/module-decoder.h"
      23             : #include "src/wasm/wasm-code-specialization.h"
      24             : #include "src/wasm/wasm-js.h"
      25             : #include "src/wasm/wasm-module.h"
      26             : #include "src/wasm/wasm-objects-inl.h"
      27             : #include "src/wasm/wasm-result.h"
      28             : 
      29             : namespace v8 {
      30             : namespace internal {
      31             : namespace wasm {
      32             : 
      33             : #define TRACE(...)                                      \
      34             :   do {                                                  \
      35             :     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
      36             :   } while (false)
      37             : 
      38             : #define TRACE_CHAIN(instance)        \
      39             :   do {                               \
      40             :     instance->PrintInstancesChain(); \
      41             :   } while (false)
      42             : 
      43             : #define TRACE_COMPILE(...)                             \
      44             :   do {                                                 \
      45             :     if (FLAG_trace_wasm_compiler) PrintF(__VA_ARGS__); \
      46             :   } while (false)
      47             : 
      48             : // static
      49             : const WasmExceptionSig WasmException::empty_sig_(0, 0, nullptr);
      50             : 
      51             : // static
      52             : constexpr const char* WasmException::kRuntimeIdStr;
      53             : 
      54             : // static
      55             : constexpr const char* WasmException::kRuntimeValuesStr;
      56             : 
      57       21386 : void UnpackAndRegisterProtectedInstructions(Isolate* isolate,
      58             :                                             Handle<FixedArray> code_table) {
      59             :   DisallowHeapAllocation no_gc;
      60             :   std::vector<trap_handler::ProtectedInstructionData> unpacked;
      61             : 
      62      129054 :   for (int i = 0; i < code_table->length(); ++i) {
      63             :     Object* maybe_code = code_table->get(i);
      64             :     // This is sometimes undefined when we're called from cctests.
      65       43141 :     if (maybe_code->IsUndefined(isolate)) continue;
      66             :     Code* code = Code::cast(maybe_code);
      67             : 
      68       41492 :     if (code->kind() != Code::WASM_FUNCTION) {
      69             :       continue;
      70             :     }
      71             : 
      72       37848 :     if (code->trap_handler_index()->value() != trap_handler::kInvalidIndex) {
      73             :       // This function has already been registered.
      74             :       continue;
      75             :     }
      76             : 
      77       37844 :     byte* base = code->entry();
      78             : 
      79             :     const int mode_mask =
      80             :         RelocInfo::ModeMask(RelocInfo::WASM_PROTECTED_INSTRUCTION_LANDING);
      81       43175 :     for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
      82             :       trap_handler::ProtectedInstructionData data;
      83        5331 :       data.instr_offset = static_cast<uint32_t>(it.rinfo()->data());
      84        5331 :       data.landing_offset = static_cast<uint32_t>(it.rinfo()->pc() - base);
      85             :       // Check that now over-/underflow happened.
      86             :       DCHECK_EQ(it.rinfo()->data(), data.instr_offset);
      87             :       DCHECK_EQ(it.rinfo()->pc() - base, data.landing_offset);
      88        5331 :       unpacked.emplace_back(data);
      89             :     }
      90       37844 :     if (unpacked.empty()) continue;
      91             : 
      92             :     const int index = RegisterHandlerData(base, code->instruction_size(),
      93         743 :                                           unpacked.size(), &unpacked[0]);
      94             :     unpacked.clear();
      95             :     // TODO(eholk): if index is negative, fail.
      96             :     DCHECK_LE(0, index);
      97         743 :     code->set_trap_handler_index(Smi::FromInt(index));
      98             :   }
      99       21386 : }
     100             : 
     101        5901 : std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name) {
     102        5901 :   os << "#" << name.function_->func_index;
     103        5901 :   if (name.function_->name.is_set()) {
     104           0 :     if (name.name_.start()) {
     105           0 :       os << ":";
     106           0 :       os.write(name.name_.start(), name.name_.length());
     107             :     }
     108             :   } else {
     109        5901 :     os << "?";
     110             :   }
     111        5901 :   return os;
     112             : }
     113             : 
     114      345897 : WasmModule::WasmModule(std::unique_ptr<Zone> owned)
     115     1037691 :     : signature_zone(std::move(owned)) {}
     116             : 
     117        2230 : WasmFunction* GetWasmFunctionForExport(Isolate* isolate,
     118             :                                        Handle<Object> target) {
     119        2230 :   if (target->IsJSFunction()) {
     120             :     Handle<JSFunction> func = Handle<JSFunction>::cast(target);
     121        2230 :     if (func->code()->kind() == Code::JS_TO_WASM_FUNCTION) {
     122             :       auto exported = Handle<WasmExportedFunction>::cast(func);
     123        2230 :       Handle<WasmInstanceObject> other_instance(exported->instance(), isolate);
     124        2230 :       int func_index = exported->function_index();
     125        4460 :       return &other_instance->module()->functions[func_index];
     126             :     }
     127             :   }
     128             :   return nullptr;
     129             : }
     130             : 
     131        5340 : void UpdateDispatchTables(Isolate* isolate, Handle<FixedArray> dispatch_tables,
     132             :                           int index, WasmFunction* function,
     133             :                           Handle<Code> code) {
     134             :   DCHECK_EQ(0, dispatch_tables->length() % 4);
     135       23060 :   for (int i = 0; i < dispatch_tables->length(); i += 4) {
     136             :     Handle<FixedArray> function_table(
     137        6190 :         FixedArray::cast(dispatch_tables->get(i + 2)), isolate);
     138             :     Handle<FixedArray> signature_table(
     139        6190 :         FixedArray::cast(dispatch_tables->get(i + 3)), isolate);
     140        6190 :     if (function) {
     141             :       Handle<WasmInstanceObject> instance(
     142             :           WasmInstanceObject::cast(dispatch_tables->get(i)), isolate);
     143             :       // Note that {SignatureMap::Find} may return {-1} if the signature is
     144             :       // not found; it will simply never match any check.
     145       10180 :       auto sig_index = instance->module()->signature_map.Find(function->sig);
     146             :       signature_table->set(index, Smi::FromInt(sig_index));
     147        5090 :       function_table->set(index, *code);
     148             :     } else {
     149             :       signature_table->set(index, Smi::FromInt(-1));
     150             :       function_table->set(index, Smi::kZero);
     151             :     }
     152             :   }
     153        5340 : }
     154             : 
     155      157337 : bool IsWasmCodegenAllowed(Isolate* isolate, Handle<Context> context) {
     156             :   // TODO(wasm): Once wasm has its own CSP policy, we should introduce a
     157             :   // separate callback that includes information about the module about to be
     158             :   // compiled. For the time being, pass an empty string as placeholder for the
     159             :   // sources.
     160      157369 :   return isolate->allow_code_gen_callback() == nullptr ||
     161          32 :          isolate->allow_code_gen_callback()(
     162             :              v8::Utils::ToLocal(context),
     163      157337 :              v8::Utils::ToLocal(isolate->factory()->empty_string()));
     164             : }
     165             : 
     166          40 : Handle<JSArray> GetImports(Isolate* isolate,
     167             :                            Handle<WasmModuleObject> module_object) {
     168             :   Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
     169             :                                              isolate);
     170             :   Factory* factory = isolate->factory();
     171             : 
     172          40 :   Handle<String> module_string = factory->InternalizeUtf8String("module");
     173          40 :   Handle<String> name_string = factory->InternalizeUtf8String("name");
     174          40 :   Handle<String> kind_string = factory->InternalizeUtf8String("kind");
     175             : 
     176          40 :   Handle<String> function_string = factory->InternalizeUtf8String("function");
     177          40 :   Handle<String> table_string = factory->InternalizeUtf8String("table");
     178          40 :   Handle<String> memory_string = factory->InternalizeUtf8String("memory");
     179          40 :   Handle<String> global_string = factory->InternalizeUtf8String("global");
     180             : 
     181             :   // Create the result array.
     182          40 :   WasmModule* module = compiled_module->module();
     183         160 :   int num_imports = static_cast<int>(module->import_table.size());
     184          40 :   Handle<JSArray> array_object = factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
     185          40 :   Handle<FixedArray> storage = factory->NewFixedArray(num_imports);
     186          40 :   JSArray::SetContent(array_object, storage);
     187             :   array_object->set_length(Smi::FromInt(num_imports));
     188             : 
     189             :   Handle<JSFunction> object_function =
     190          80 :       Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
     191             : 
     192             :   // Populate the result array.
     193         120 :   for (int index = 0; index < num_imports; ++index) {
     194          80 :     WasmImport& import = module->import_table[index];
     195             : 
     196          80 :     Handle<JSObject> entry = factory->NewJSObject(object_function);
     197             : 
     198             :     Handle<String> import_kind;
     199          80 :     switch (import.kind) {
     200             :       case kExternalFunction:
     201          20 :         import_kind = function_string;
     202          20 :         break;
     203             :       case kExternalTable:
     204          20 :         import_kind = table_string;
     205          20 :         break;
     206             :       case kExternalMemory:
     207          20 :         import_kind = memory_string;
     208          20 :         break;
     209             :       case kExternalGlobal:
     210          20 :         import_kind = global_string;
     211          20 :         break;
     212             :       default:
     213           0 :         UNREACHABLE();
     214             :     }
     215             : 
     216             :     MaybeHandle<String> import_module =
     217             :         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
     218          80 :             isolate, compiled_module, import.module_name);
     219             : 
     220             :     MaybeHandle<String> import_name =
     221             :         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
     222          80 :             isolate, compiled_module, import.field_name);
     223             : 
     224             :     JSObject::AddProperty(entry, module_string, import_module.ToHandleChecked(),
     225          80 :                           NONE);
     226             :     JSObject::AddProperty(entry, name_string, import_name.ToHandleChecked(),
     227          80 :                           NONE);
     228          80 :     JSObject::AddProperty(entry, kind_string, import_kind, NONE);
     229             : 
     230          80 :     storage->set(index, *entry);
     231             :   }
     232             : 
     233          40 :   return array_object;
     234             : }
     235             : 
     236          40 : Handle<JSArray> GetExports(Isolate* isolate,
     237             :                            Handle<WasmModuleObject> module_object) {
     238             :   Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
     239             :                                              isolate);
     240             :   Factory* factory = isolate->factory();
     241             : 
     242          40 :   Handle<String> name_string = factory->InternalizeUtf8String("name");
     243          40 :   Handle<String> kind_string = factory->InternalizeUtf8String("kind");
     244             : 
     245          40 :   Handle<String> function_string = factory->InternalizeUtf8String("function");
     246          40 :   Handle<String> table_string = factory->InternalizeUtf8String("table");
     247          40 :   Handle<String> memory_string = factory->InternalizeUtf8String("memory");
     248          40 :   Handle<String> global_string = factory->InternalizeUtf8String("global");
     249             : 
     250             :   // Create the result array.
     251          40 :   WasmModule* module = compiled_module->module();
     252         160 :   int num_exports = static_cast<int>(module->export_table.size());
     253          40 :   Handle<JSArray> array_object = factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
     254          40 :   Handle<FixedArray> storage = factory->NewFixedArray(num_exports);
     255          40 :   JSArray::SetContent(array_object, storage);
     256             :   array_object->set_length(Smi::FromInt(num_exports));
     257             : 
     258             :   Handle<JSFunction> object_function =
     259          80 :       Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
     260             : 
     261             :   // Populate the result array.
     262         120 :   for (int index = 0; index < num_exports; ++index) {
     263          80 :     WasmExport& exp = module->export_table[index];
     264             : 
     265             :     Handle<String> export_kind;
     266          80 :     switch (exp.kind) {
     267             :       case kExternalFunction:
     268          20 :         export_kind = function_string;
     269          20 :         break;
     270             :       case kExternalTable:
     271          20 :         export_kind = table_string;
     272          20 :         break;
     273             :       case kExternalMemory:
     274          20 :         export_kind = memory_string;
     275          20 :         break;
     276             :       case kExternalGlobal:
     277          20 :         export_kind = global_string;
     278          20 :         break;
     279             :       default:
     280           0 :         UNREACHABLE();
     281             :     }
     282             : 
     283          80 :     Handle<JSObject> entry = factory->NewJSObject(object_function);
     284             : 
     285             :     MaybeHandle<String> export_name =
     286             :         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
     287          80 :             isolate, compiled_module, exp.name);
     288             : 
     289             :     JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(),
     290          80 :                           NONE);
     291          80 :     JSObject::AddProperty(entry, kind_string, export_kind, NONE);
     292             : 
     293          80 :     storage->set(index, *entry);
     294             :   }
     295             : 
     296          40 :   return array_object;
     297             : }
     298             : 
     299         110 : Handle<JSArray> GetCustomSections(Isolate* isolate,
     300             :                                   Handle<WasmModuleObject> module_object,
     301             :                                   Handle<String> name, ErrorThrower* thrower) {
     302             :   Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
     303             :                                              isolate);
     304             :   Factory* factory = isolate->factory();
     305             : 
     306             :   std::vector<CustomSectionOffset> custom_sections;
     307             :   {
     308             :     DisallowHeapAllocation no_gc;  // for raw access to string bytes.
     309             :     Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(),
     310             :                                           isolate);
     311             :     const byte* start =
     312          60 :         reinterpret_cast<const byte*>(module_bytes->GetCharsAddress());
     313          60 :     const byte* end = start + module_bytes->length();
     314         120 :     custom_sections = DecodeCustomSections(start, end);
     315             :   }
     316             : 
     317             :   std::vector<Handle<Object>> matching_sections;
     318             : 
     319             :   // Gather matching sections.
     320         280 :   for (auto& section : custom_sections) {
     321             :     MaybeHandle<String> section_name =
     322             :         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
     323         160 :             isolate, compiled_module, section.name);
     324             : 
     325         270 :     if (!name->Equals(*section_name.ToHandleChecked())) continue;
     326             : 
     327             :     // Make a copy of the payload data in the section.
     328         150 :     size_t size = section.payload.length();
     329             :     void* memory =
     330         100 :         size == 0 ? nullptr : isolate->array_buffer_allocator()->Allocate(size);
     331             : 
     332          50 :     if (size && !memory) {
     333           0 :       thrower->RangeError("out of memory allocating custom section data");
     334           0 :       return Handle<JSArray>();
     335             :     }
     336          50 :     Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
     337             :     constexpr bool is_external = false;
     338             :     JSArrayBuffer::Setup(buffer, isolate, is_external, memory, size, memory,
     339          50 :                          size);
     340             :     DisallowHeapAllocation no_gc;  // for raw access to string bytes.
     341             :     Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(),
     342             :                                           isolate);
     343             :     const byte* start =
     344          50 :         reinterpret_cast<const byte*>(module_bytes->GetCharsAddress());
     345         100 :     memcpy(memory, start + section.payload.offset(), section.payload.length());
     346             : 
     347          50 :     matching_sections.push_back(buffer);
     348             :   }
     349             : 
     350         120 :   int num_custom_sections = static_cast<int>(matching_sections.size());
     351          60 :   Handle<JSArray> array_object = factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
     352          60 :   Handle<FixedArray> storage = factory->NewFixedArray(num_custom_sections);
     353          60 :   JSArray::SetContent(array_object, storage);
     354             :   array_object->set_length(Smi::FromInt(num_custom_sections));
     355             : 
     356         110 :   for (int i = 0; i < num_custom_sections; i++) {
     357         100 :     storage->set(i, *matching_sections[i]);
     358             :   }
     359             : 
     360          60 :   return array_object;
     361             : }
     362             : 
     363          15 : Handle<FixedArray> DecodeLocalNames(
     364             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
     365             :   Handle<SeqOneByteString> wire_bytes(compiled_module->module_bytes(), isolate);
     366             :   LocalNames decoded_locals;
     367             :   {
     368             :     DisallowHeapAllocation no_gc;
     369             :     DecodeLocalNames(wire_bytes->GetChars(),
     370          15 :                      wire_bytes->GetChars() + wire_bytes->length(),
     371          15 :                      &decoded_locals);
     372             :   }
     373             :   Handle<FixedArray> locals_names =
     374          15 :       isolate->factory()->NewFixedArray(decoded_locals.max_function_index + 1);
     375          35 :   for (LocalNamesPerFunction& func : decoded_locals.names) {
     376             :     Handle<FixedArray> func_locals_names =
     377           5 :         isolate->factory()->NewFixedArray(func.max_local_index + 1);
     378          10 :     locals_names->set(func.function_index, *func_locals_names);
     379          20 :     for (LocalName& name : func.names) {
     380             :       Handle<String> name_str =
     381             :           WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
     382             :               isolate, compiled_module, name.name)
     383          20 :               .ToHandleChecked();
     384          20 :       func_locals_names->set(name.local_index, *name_str);
     385             :     }
     386             :   }
     387          30 :   return locals_names;
     388             : }
     389             : 
     390         800 : const char* ExternalKindName(WasmExternalKind kind) {
     391         800 :   switch (kind) {
     392             :     case kExternalFunction:
     393             :       return "function";
     394             :     case kExternalTable:
     395         160 :       return "table";
     396             :     case kExternalMemory:
     397         160 :       return "memory";
     398             :     case kExternalGlobal:
     399         250 :       return "global";
     400             :   }
     401           0 :   return "unknown";
     402             : }
     403             : 
     404             : #undef TRACE
     405             : #undef TRACE_CHAIN
     406             : #undef TRACE_COMPILE
     407             : 
     408             : }  // namespace wasm
     409             : }  // namespace internal
     410             : }  // namespace v8

Generated by: LCOV version 1.10