LCOV - code coverage report
Current view: top level - src/wasm - function-compiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 72 75 96.0 %
Date: 2019-04-17 Functions: 17 17 100.0 %

          Line data    Source code
       1             : // Copyright 2018 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 "src/wasm/function-compiler.h"
       6             : 
       7             : #include "src/compiler/wasm-compiler.h"
       8             : #include "src/counters.h"
       9             : #include "src/macro-assembler-inl.h"
      10             : #include "src/wasm/baseline/liftoff-compiler.h"
      11             : #include "src/wasm/wasm-code-manager.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : namespace wasm {
      16             : 
      17             : namespace {
      18             : 
      19     2912435 : class WasmInstructionBufferImpl {
      20             :  public:
      21             :   class View : public AssemblerBuffer {
      22             :    public:
      23             :     View(Vector<uint8_t> buffer, WasmInstructionBufferImpl* holder)
      24     1459020 :         : buffer_(buffer), holder_(holder) {}
      25             : 
      26     4371551 :     ~View() override {
      27     2913712 :       if (buffer_.start() == holder_->old_buffer_.start()) {
      28             :         DCHECK_EQ(buffer_.size(), holder_->old_buffer_.size());
      29             :         holder_->old_buffer_ = {};
      30             :       }
      31     2914695 :     }
      32             : 
      33     4323525 :     byte* start() const override { return buffer_.start(); }
      34             : 
      35     2894725 :     int size() const override { return static_cast<int>(buffer_.size()); }
      36             : 
      37        1248 :     std::unique_ptr<AssemblerBuffer> Grow(int new_size) override {
      38             :       // If we grow, we must be the current buffer of {holder_}.
      39             :       DCHECK_EQ(buffer_.start(), holder_->buffer_.start());
      40             :       DCHECK_EQ(buffer_.size(), holder_->buffer_.size());
      41             :       DCHECK_NULL(holder_->old_buffer_);
      42             : 
      43             :       DCHECK_LT(size(), new_size);
      44             : 
      45        1248 :       holder_->old_buffer_ = std::move(holder_->buffer_);
      46        2496 :       holder_->buffer_ = OwnedVector<uint8_t>::New(new_size);
      47        2496 :       return base::make_unique<View>(holder_->buffer_.as_vector(), holder_);
      48             :     }
      49             : 
      50             :    private:
      51             :     const Vector<uint8_t> buffer_;
      52             :     WasmInstructionBufferImpl* const holder_;
      53             :   };
      54             : 
      55     1454711 :   std::unique_ptr<AssemblerBuffer> CreateView() {
      56             :     DCHECK_NOT_NULL(buffer_);
      57     1457772 :     return base::make_unique<View>(buffer_.as_vector(), this);
      58             :   }
      59             : 
      60             :   std::unique_ptr<uint8_t[]> ReleaseBuffer() {
      61             :     DCHECK_NULL(old_buffer_);
      62             :     DCHECK_NOT_NULL(buffer_);
      63             :     return buffer_.ReleaseData();
      64             :   }
      65             : 
      66             :   bool released() const { return buffer_ == nullptr; }
      67             : 
      68             :  private:
      69             :   // The current buffer used to emit code.
      70             :   OwnedVector<uint8_t> buffer_ =
      71             :       OwnedVector<uint8_t>::New(AssemblerBase::kMinimalBufferSize);
      72             : 
      73             :   // While the buffer is grown, we need to temporarily also keep the old buffer
      74             :   // alive.
      75             :   OwnedVector<uint8_t> old_buffer_;
      76             : };
      77             : 
      78             : WasmInstructionBufferImpl* Impl(WasmInstructionBuffer* buf) {
      79             :   return reinterpret_cast<WasmInstructionBufferImpl*>(buf);
      80             : }
      81             : 
      82             : }  // namespace
      83             : 
      84             : // PIMPL interface WasmInstructionBuffer for WasmInstBufferImpl
      85     1456582 : WasmInstructionBuffer::~WasmInstructionBuffer() {
      86     1456582 :   Impl(this)->~WasmInstructionBufferImpl();
      87     1456445 : }
      88             : 
      89     1454747 : std::unique_ptr<AssemblerBuffer> WasmInstructionBuffer::CreateView() {
      90     1454747 :   return Impl(this)->CreateView();
      91             : }
      92             : 
      93     1435706 : std::unique_ptr<uint8_t[]> WasmInstructionBuffer::ReleaseBuffer() {
      94     1435706 :   return Impl(this)->ReleaseBuffer();
      95             : }
      96             : 
      97             : // static
      98     1454079 : std::unique_ptr<WasmInstructionBuffer> WasmInstructionBuffer::New() {
      99             :   return std::unique_ptr<WasmInstructionBuffer>{
     100             :       reinterpret_cast<WasmInstructionBuffer*>(
     101     2911333 :           new WasmInstructionBufferImpl())};
     102             : }
     103             : // End of PIMPL interface WasmInstructionBuffer for WasmInstBufferImpl
     104             : 
     105             : // static
     106      420226 : ExecutionTier WasmCompilationUnit::GetDefaultExecutionTier(
     107             :     const WasmModule* module) {
     108             :   // Liftoff does not support the special asm.js opcodes, thus always compile
     109             :   // asm.js modules with TurboFan.
     110      420226 :   if (module->origin == kAsmJsOrigin) return ExecutionTier::kTurbofan;
     111      412257 :   if (FLAG_wasm_interpret_all) return ExecutionTier::kInterpreter;
     112      408263 :   return FLAG_liftoff ? ExecutionTier::kLiftoff : ExecutionTier::kTurbofan;
     113             : }
     114             : 
     115     1075327 : WasmCompilationUnit::WasmCompilationUnit(int index, ExecutionTier tier)
     116     1075327 :     : func_index_(index), tier_(tier) {
     117     1075327 :   if (V8_UNLIKELY(FLAG_wasm_tier_mask_for_testing) && index < 32 &&
     118             :       (FLAG_wasm_tier_mask_for_testing & (1 << index))) {
     119             :     tier = ExecutionTier::kTurbofan;
     120             :   }
     121     1075327 :   SwitchTier(tier);
     122     1075326 : }
     123             : 
     124             : // Declared here such that {LiftoffCompilationUnit} and
     125             : // {TurbofanWasmCompilationUnit} can be opaque in the header file.
     126             : WasmCompilationUnit::~WasmCompilationUnit() = default;
     127             : 
     128     1073047 : WasmCompilationResult WasmCompilationUnit::ExecuteCompilation(
     129             :     WasmEngine* wasm_engine, CompilationEnv* env,
     130             :     const std::shared_ptr<WireBytesStorage>& wire_bytes_storage,
     131             :     Counters* counters, WasmFeatures* detected) {
     132     1073047 :   auto* func = &env->module->functions[func_index_];
     133     1073047 :   Vector<const uint8_t> code = wire_bytes_storage->GetCode(func->code);
     134     1072998 :   wasm::FunctionBody func_body{func->sig, func->code.offset(), code.start(),
     135             :                                code.end()};
     136             : 
     137     1072998 :   auto size_histogram = SELECT_WASM_COUNTER(counters, env->module->origin, wasm,
     138             :                                             function_size_bytes);
     139     1072998 :   size_histogram->AddSample(static_cast<int>(func_body.end - func_body.start));
     140     1072992 :   auto timed_histogram = SELECT_WASM_COUNTER(counters, env->module->origin,
     141             :                                              wasm_compile, function_time);
     142             :   TimedHistogramScope wasm_compile_function_time_scope(timed_histogram);
     143             : 
     144             :   // Exactly one compiler-specific unit must be set.
     145             :   DCHECK_EQ(1, !!liftoff_unit_ + !!turbofan_unit_ + !!interpreter_unit_);
     146             : 
     147             :   if (FLAG_trace_wasm_compiler) {
     148             :     const char* tier =
     149             :         liftoff_unit_ ? "liftoff" : turbofan_unit_ ? "turbofan" : "interpreter";
     150             :     PrintF("Compiling wasm function %d with %s\n\n", func_index_, tier);
     151             :   }
     152             : 
     153             :   WasmCompilationResult result;
     154     1072600 :   if (liftoff_unit_) {
     155      921288 :     result = liftoff_unit_->ExecuteCompilation(wasm_engine->allocator(), env,
     156      460404 :                                                func_body, counters, detected);
     157      460329 :     if (!result.succeeded()) {
     158             :       // If Liftoff failed, fall back to turbofan.
     159             :       // TODO(wasm): We could actually stop or remove the tiering unit for this
     160             :       // function to avoid compiling it twice with TurboFan.
     161       18806 :       SwitchTier(ExecutionTier::kTurbofan);
     162             :       DCHECK_NOT_NULL(turbofan_unit_);
     163             :     }
     164             :   }
     165     1072129 :   if (turbofan_unit_) {
     166     1255489 :     result = turbofan_unit_->ExecuteCompilation(wasm_engine, env, func_body,
     167      627011 :                                                 counters, detected);
     168             :   }
     169     1069765 :   if (interpreter_unit_) {
     170        2862 :     result = interpreter_unit_->ExecuteCompilation(wasm_engine, env, func_body,
     171        1429 :                                                    counters, detected);
     172             :   }
     173     1069756 :   result.func_index = func_index_;
     174     1069756 :   result.requested_tier = tier_;
     175             : 
     176     1069756 :   if (result.succeeded()) {
     177     1060643 :     counters->wasm_generated_code_size()->Increment(
     178     1060643 :         result.code_desc.instr_size);
     179     2121130 :     counters->wasm_reloc_size()->Increment(result.code_desc.reloc_size);
     180             :   }
     181             : 
     182     1069542 :   return result;
     183             : }
     184             : 
     185     1094108 : void WasmCompilationUnit::SwitchTier(ExecutionTier new_tier) {
     186             :   // This method is being called in the constructor, where neither
     187             :   // {liftoff_unit_} nor {turbofan_unit_} nor {interpreter_unit_} are set, or to
     188             :   // switch tier from kLiftoff to kTurbofan, in which case {liftoff_unit_} is
     189             :   // already set.
     190     1094108 :   switch (new_tier) {
     191             :     case ExecutionTier::kLiftoff:
     192             :       DCHECK(!turbofan_unit_);
     193             :       DCHECK(!liftoff_unit_);
     194             :       DCHECK(!interpreter_unit_);
     195      461561 :       liftoff_unit_.reset(new LiftoffCompilationUnit());
     196             :       return;
     197             :     case ExecutionTier::kTurbofan:
     198             :       DCHECK(!turbofan_unit_);
     199             :       DCHECK(!interpreter_unit_);
     200             :       liftoff_unit_.reset();
     201      631217 :       turbofan_unit_.reset(new compiler::TurbofanWasmCompilationUnit(this));
     202      631166 :       return;
     203             :     case ExecutionTier::kInterpreter:
     204             :       DCHECK(!turbofan_unit_);
     205             :       DCHECK(!liftoff_unit_);
     206             :       DCHECK(!interpreter_unit_);
     207        1439 :       interpreter_unit_.reset(new compiler::InterpreterCompilationUnit(this));
     208             :       return;
     209             :     case ExecutionTier::kNone:
     210           0 :       UNREACHABLE();
     211             :   }
     212           0 :   UNREACHABLE();
     213             : }
     214             : 
     215             : // static
     216          20 : void WasmCompilationUnit::CompileWasmFunction(Isolate* isolate,
     217             :                                               NativeModule* native_module,
     218             :                                               WasmFeatures* detected,
     219             :                                               const WasmFunction* function,
     220             :                                               ExecutionTier tier) {
     221             :   ModuleWireBytes wire_bytes(native_module->wire_bytes());
     222             :   FunctionBody function_body{function->sig, function->code.offset(),
     223             :                              wire_bytes.start() + function->code.offset(),
     224             :                              wire_bytes.start() + function->code.end_offset()};
     225             : 
     226          40 :   WasmCompilationUnit unit(function->func_index, tier);
     227          20 :   CompilationEnv env = native_module->CreateCompilationEnv();
     228             :   WasmCompilationResult result = unit.ExecuteCompilation(
     229             :       isolate->wasm_engine(), &env,
     230          40 :       native_module->compilation_state()->GetWireBytesStorage(),
     231          40 :       isolate->counters(), detected);
     232          20 :   if (result.succeeded()) {
     233          40 :     WasmCodeRefScope code_ref_scope;
     234          20 :     native_module->AddCompiledCode(std::move(result));
     235             :   } else {
     236           0 :     native_module->compilation_state()->SetError();
     237             :   }
     238          20 : }
     239             : 
     240             : }  // namespace wasm
     241             : }  // namespace internal
     242      122004 : }  // namespace v8

Generated by: LCOV version 1.10