LCOV - code coverage report
Current view: top level - src/wasm - function-compiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 71 72 98.6 %
Date: 2019-03-21 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     2933435 : class WasmInstructionBufferImpl {
      20             :  public:
      21             :   class View : public AssemblerBuffer {
      22             :    public:
      23             :     View(Vector<uint8_t> buffer, WasmInstructionBufferImpl* holder)
      24     1469634 :         : buffer_(buffer), holder_(holder) {}
      25             : 
      26     4401239 :     ~View() override {
      27     2934560 :       if (buffer_.start() == holder_->old_buffer_.start()) {
      28             :         DCHECK_EQ(buffer_.size(), holder_->old_buffer_.size());
      29             :         holder_->old_buffer_ = {};
      30             :       }
      31     2933959 :     }
      32             : 
      33     4340236 :     byte* start() const override { return buffer_.start(); }
      34             : 
      35     2908390 :     int size() const override { return static_cast<int>(buffer_.size()); }
      36             : 
      37        1558 :     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        1558 :       holder_->old_buffer_ = std::move(holder_->buffer_);
      46        3116 :       holder_->buffer_ = OwnedVector<uint8_t>::New(new_size);
      47        3116 :       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     1465625 :   std::unique_ptr<AssemblerBuffer> CreateView() {
      56             :     DCHECK_NOT_NULL(buffer_);
      57     1468076 :     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     1466458 : WasmInstructionBuffer::~WasmInstructionBuffer() {
      86     1466458 :   Impl(this)->~WasmInstructionBufferImpl();
      87     1466969 : }
      88             : 
      89     1465527 : std::unique_ptr<AssemblerBuffer> WasmInstructionBuffer::CreateView() {
      90     1465527 :   return Impl(this)->CreateView();
      91             : }
      92             : 
      93     1437550 : std::unique_ptr<uint8_t[]> WasmInstructionBuffer::ReleaseBuffer() {
      94     1437550 :   return Impl(this)->ReleaseBuffer();
      95             : }
      96             : 
      97             : // static
      98     1464260 : std::unique_ptr<WasmInstructionBuffer> WasmInstructionBuffer::New() {
      99             :   return std::unique_ptr<WasmInstructionBuffer>{
     100             :       reinterpret_cast<WasmInstructionBuffer*>(
     101     2932262 :           new WasmInstructionBufferImpl())};
     102             : }
     103             : // End of PIMPL interface WasmInstructionBuffer for WasmInstBufferImpl
     104             : 
     105             : // static
     106      151536 : ExecutionTier WasmCompilationUnit::GetDefaultExecutionTier(
     107             :     const WasmModule* module) {
     108      151536 :   if (module->origin == kWasmOrigin) {
     109      143614 :     if (FLAG_wasm_interpret_all) {
     110             :       return ExecutionTier::kInterpreter;
     111      143306 :     } else if (FLAG_liftoff) {
     112             :       return ExecutionTier::kBaseline;
     113             :     }
     114             :   }
     115        7958 :   return ExecutionTier::kOptimized;
     116             : }
     117             : 
     118     1077725 : WasmCompilationUnit::WasmCompilationUnit(WasmEngine* wasm_engine, int index,
     119             :                                          ExecutionTier tier)
     120     1077725 :     : wasm_engine_(wasm_engine), func_index_(index), tier_(tier) {
     121     1077725 :   if (V8_UNLIKELY(FLAG_wasm_tier_mask_for_testing) && index < 32 &&
     122             :       (FLAG_wasm_tier_mask_for_testing & (1 << index))) {
     123             :     tier = ExecutionTier::kOptimized;
     124             :   }
     125     1077725 :   SwitchTier(tier);
     126     1077725 : }
     127             : 
     128             : // Declared here such that {LiftoffCompilationUnit} and
     129             : // {TurbofanWasmCompilationUnit} can be opaque in the header file.
     130             : WasmCompilationUnit::~WasmCompilationUnit() = default;
     131             : 
     132     1075653 : WasmCompilationResult WasmCompilationUnit::ExecuteCompilation(
     133             :     CompilationEnv* env,
     134             :     const std::shared_ptr<WireBytesStorage>& wire_bytes_storage,
     135             :     Counters* counters, WasmFeatures* detected) {
     136     1075653 :   auto* func = &env->module->functions[func_index_];
     137     1075653 :   Vector<const uint8_t> code = wire_bytes_storage->GetCode(func->code);
     138     1075570 :   wasm::FunctionBody func_body{func->sig, func->code.offset(), code.start(),
     139             :                                code.end()};
     140             : 
     141     1075570 :   auto size_histogram = SELECT_WASM_COUNTER(counters, env->module->origin, wasm,
     142             :                                             function_size_bytes);
     143     1075570 :   size_histogram->AddSample(static_cast<int>(func_body.end - func_body.start));
     144     1075588 :   auto timed_histogram = SELECT_WASM_COUNTER(counters, env->module->origin,
     145             :                                              wasm_compile, function_time);
     146             :   TimedHistogramScope wasm_compile_function_time_scope(timed_histogram);
     147             : 
     148             :   // Exactly one compiler-specific unit must be set.
     149             :   DCHECK_EQ(1, !!liftoff_unit_ + !!turbofan_unit_ + !!interpreter_unit_);
     150             : 
     151             :   if (FLAG_trace_wasm_compiler) {
     152             :     const char* tier =
     153             :         liftoff_unit_ ? "liftoff" : turbofan_unit_ ? "turbofan" : "interpreter";
     154             :     PrintF("Compiling wasm function %d with %s\n\n", func_index_, tier);
     155             :   }
     156             : 
     157             :   WasmCompilationResult result;
     158     1074892 :   if (liftoff_unit_) {
     159             :     result =
     160      594921 :         liftoff_unit_->ExecuteCompilation(env, func_body, counters, detected);
     161      593570 :     if (!result.succeeded()) {
     162             :       // If Liftoff failed, fall back to turbofan.
     163             :       // TODO(wasm): We could actually stop or remove the tiering unit for this
     164             :       // function to avoid compiling it twice with TurboFan.
     165       25486 :       SwitchTier(ExecutionTier::kOptimized);
     166             :       DCHECK_NOT_NULL(turbofan_unit_);
     167             :     }
     168             :   }
     169     1074214 :   if (turbofan_unit_) {
     170             :     result =
     171      505086 :         turbofan_unit_->ExecuteCompilation(env, func_body, counters, detected);
     172             :   }
     173     1072043 :   if (interpreter_unit_) {
     174         896 :     result = interpreter_unit_->ExecuteCompilation(env, func_body, counters,
     175         448 :                                                    detected);
     176             :   }
     177     1072038 :   result.func_index = func_index_;
     178     1072038 :   result.requested_tier = tier_;
     179             : 
     180     1072038 :   if (result.succeeded()) {
     181     1064352 :     counters->wasm_generated_code_size()->Increment(
     182     1064352 :         result.code_desc.instr_size);
     183     2127648 :     counters->wasm_reloc_size()->Increment(result.code_desc.reloc_size);
     184             :   }
     185             : 
     186     1071887 :   return result;
     187             : }
     188             : 
     189     1103213 : void WasmCompilationUnit::SwitchTier(ExecutionTier new_tier) {
     190             :   // This method is being called in the constructor, where neither
     191             :   // {liftoff_unit_} nor {turbofan_unit_} nor {interpreter_unit_} are set, or to
     192             :   // switch tier from kLiftoff to kTurbofan, in which case {liftoff_unit_} is
     193             :   // already set.
     194     1103213 :   switch (new_tier) {
     195             :     case ExecutionTier::kBaseline:
     196             :       DCHECK(!turbofan_unit_);
     197             :       DCHECK(!liftoff_unit_);
     198             :       DCHECK(!interpreter_unit_);
     199      596202 :       liftoff_unit_.reset(new LiftoffCompilationUnit(this));
     200             :       return;
     201             :     case ExecutionTier::kOptimized:
     202             :       DCHECK(!turbofan_unit_);
     203             :       DCHECK(!interpreter_unit_);
     204             :       liftoff_unit_.reset();
     205      506626 :       turbofan_unit_.reset(new compiler::TurbofanWasmCompilationUnit(this));
     206      506543 :       return;
     207             :     case ExecutionTier::kInterpreter:
     208             :       DCHECK(!turbofan_unit_);
     209             :       DCHECK(!liftoff_unit_);
     210             :       DCHECK(!interpreter_unit_);
     211         452 :       interpreter_unit_.reset(new compiler::InterpreterCompilationUnit(this));
     212             :       return;
     213             :   }
     214           0 :   UNREACHABLE();
     215             : }
     216             : 
     217             : // static
     218      131489 : void WasmCompilationUnit::CompileWasmFunction(Isolate* isolate,
     219             :                                               NativeModule* native_module,
     220             :                                               WasmFeatures* detected,
     221             :                                               const WasmFunction* function,
     222             :                                               ExecutionTier tier) {
     223             :   ModuleWireBytes wire_bytes(native_module->wire_bytes());
     224             :   FunctionBody function_body{function->sig, function->code.offset(),
     225             :                              wire_bytes.start() + function->code.offset(),
     226             :                              wire_bytes.start() + function->code.end_offset()};
     227             : 
     228      262977 :   WasmCompilationUnit unit(isolate->wasm_engine(), function->func_index, tier);
     229      131489 :   CompilationEnv env = native_module->CreateCompilationEnv();
     230             :   WasmCompilationResult result = unit.ExecuteCompilation(
     231      262978 :       &env, native_module->compilation_state()->GetWireBytesStorage(),
     232      262978 :       isolate->counters(), detected);
     233      131489 :   if (result.succeeded()) {
     234      124360 :     native_module->AddCompiledCode(std::move(result));
     235             :   } else {
     236        7129 :     native_module->compilation_state()->SetError();
     237             :   }
     238      131488 : }
     239             : 
     240             : }  // namespace wasm
     241             : }  // namespace internal
     242      120216 : }  // namespace v8

Generated by: LCOV version 1.10