LCOV - code coverage report
Current view: top level - src/wasm - function-compiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 71 74 95.9 %
Date: 2019-02-19 Functions: 19 19 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             : const char* GetExecutionTierAsString(ExecutionTier tier) {
      20             :   switch (tier) {
      21             :     case ExecutionTier::kBaseline:
      22             :       return "liftoff";
      23             :     case ExecutionTier::kOptimized:
      24             :       return "turbofan";
      25             :     case ExecutionTier::kInterpreter:
      26             :       return "interpreter";
      27             :   }
      28             :   UNREACHABLE();
      29             : }
      30             : 
      31     3271538 : class WasmInstructionBufferImpl {
      32             :  public:
      33             :   class View : public AssemblerBuffer {
      34             :    public:
      35             :     View(Vector<uint8_t> buffer, WasmInstructionBufferImpl* holder)
      36     1091767 :         : buffer_(buffer), holder_(holder) {}
      37             : 
      38     2182918 :     ~View() override {
      39     2182840 :       if (buffer_.start() == holder_->old_buffer_.start()) {
      40             :         DCHECK_EQ(buffer_.size(), holder_->old_buffer_.size());
      41        2006 :         holder_->old_buffer_ = {};
      42             :       }
      43     2182918 :     }
      44             : 
      45     3224148 :     byte* start() const override { return buffer_.start(); }
      46             : 
      47     2158248 :     int size() const override { return static_cast<int>(buffer_.size()); }
      48             : 
      49        1003 :     std::unique_ptr<AssemblerBuffer> Grow(int new_size) override {
      50             :       // If we grow, we must be the current buffer of {holder_}.
      51             :       DCHECK_EQ(buffer_.start(), holder_->buffer_.start());
      52             :       DCHECK_EQ(buffer_.size(), holder_->buffer_.size());
      53             :       DCHECK_NULL(holder_->old_buffer_);
      54             : 
      55             :       DCHECK_LT(size(), new_size);
      56             : 
      57        1003 :       holder_->old_buffer_ = std::move(holder_->buffer_);
      58        3009 :       holder_->buffer_ = OwnedVector<uint8_t>::New(new_size);
      59        3009 :       return base::make_unique<View>(holder_->buffer_.as_vector(), holder_);
      60             :     }
      61             : 
      62             :    private:
      63             :     const Vector<uint8_t> buffer_;
      64             :     WasmInstructionBufferImpl* const holder_;
      65             :   };
      66             : 
      67     1090669 :   std::unique_ptr<AssemblerBuffer> CreateView() {
      68             :     DCHECK_NOT_NULL(buffer_);
      69     2181430 :     return base::make_unique<View>(buffer_.as_vector(), this);
      70             :   }
      71             : 
      72             :   std::unique_ptr<uint8_t[]> ReleaseBuffer() {
      73             :     DCHECK_NULL(old_buffer_);
      74             :     DCHECK_NOT_NULL(buffer_);
      75             :     return buffer_.ReleaseData();
      76             :   }
      77             : 
      78             :   bool released() const { return buffer_ == nullptr; }
      79             : 
      80             :  private:
      81             :   // The current buffer used to emit code.
      82             :   OwnedVector<uint8_t> buffer_ =
      83             :       OwnedVector<uint8_t>::New(AssemblerBase::kMinimalBufferSize);
      84             : 
      85             :   // While the buffer is grown, we need to temporarily also keep the old
      86             :   // buffer alive.
      87             :   OwnedVector<uint8_t> old_buffer_;
      88             : };
      89             : 
      90             : WasmInstructionBufferImpl* Impl(WasmInstructionBuffer* buf) {
      91             :   return reinterpret_cast<WasmInstructionBufferImpl*>(buf);
      92             : }
      93             : 
      94             : }  // namespace
      95             : 
      96             : // PIMPL interface WasmInstructionBuffer for WasmInstBufferImpl
      97     1090349 : WasmInstructionBuffer::~WasmInstructionBuffer() {
      98     1090349 :   Impl(this)->~WasmInstructionBufferImpl();
      99     1090501 : }
     100             : 
     101     1090678 : std::unique_ptr<AssemblerBuffer> WasmInstructionBuffer::CreateView() {
     102     1090678 :   return Impl(this)->CreateView();
     103             : }
     104             : 
     105     1066544 : std::unique_ptr<uint8_t[]> WasmInstructionBuffer::ReleaseBuffer() {
     106     1066544 :   return Impl(this)->ReleaseBuffer();
     107             : }
     108             : 
     109             : // static
     110     1090500 : std::unique_ptr<WasmInstructionBuffer> WasmInstructionBuffer::New() {
     111             :   return std::unique_ptr<WasmInstructionBuffer>{
     112             :       reinterpret_cast<WasmInstructionBuffer*>(
     113     2181242 :           new WasmInstructionBufferImpl())};
     114             : }
     115             : // End of PIMPL interface WasmInstructionBuffer for WasmInstBufferImpl
     116             : 
     117             : // static
     118      150004 : ExecutionTier WasmCompilationUnit::GetDefaultExecutionTier(
     119             :     const WasmModule* module) {
     120      149968 :   return FLAG_liftoff && module->origin == kWasmOrigin
     121             :              ? ExecutionTier::kBaseline
     122      300008 :              : ExecutionTier::kOptimized;
     123             : }
     124             : 
     125     1074796 : WasmCompilationUnit::WasmCompilationUnit(WasmEngine* wasm_engine, int index,
     126             :                                          ExecutionTier tier)
     127     1074796 :     : wasm_engine_(wasm_engine), func_index_(index), requested_tier_(tier) {
     128     1074796 :   if (V8_UNLIKELY(FLAG_wasm_tier_mask_for_testing) && index < 32 &&
     129             :       (FLAG_wasm_tier_mask_for_testing & (1 << index))) {
     130             :     tier = ExecutionTier::kOptimized;
     131             :   }
     132     1074796 :   SwitchTier(tier);
     133     1074795 : }
     134             : 
     135             : // Declared here such that {LiftoffCompilationUnit} and
     136             : // {TurbofanWasmCompilationUnit} can be opaque in the header file.
     137             : WasmCompilationUnit::~WasmCompilationUnit() = default;
     138             : 
     139     1073506 : WasmCompilationResult WasmCompilationUnit::ExecuteCompilation(
     140             :     CompilationEnv* env,
     141             :     const std::shared_ptr<WireBytesStorage>& wire_bytes_storage,
     142             :     Counters* counters, WasmFeatures* detected) {
     143     1073506 :   auto* func = &env->module->functions[func_index_];
     144     1073506 :   Vector<const uint8_t> code = wire_bytes_storage->GetCode(func->code);
     145             :   wasm::FunctionBody func_body{func->sig, func->code.offset(), code.start(),
     146     1073495 :                                code.end()};
     147             : 
     148     1073495 :   auto size_histogram = SELECT_WASM_COUNTER(counters, env->module->origin, wasm,
     149             :                                             function_size_bytes);
     150     1073495 :   size_histogram->AddSample(static_cast<int>(func_body.end - func_body.start));
     151     1073492 :   auto timed_histogram = SELECT_WASM_COUNTER(counters, env->module->origin,
     152             :                                              wasm_compile, function_time);
     153             :   TimedHistogramScope wasm_compile_function_time_scope(timed_histogram);
     154             : 
     155             :   if (FLAG_trace_wasm_compiler) {
     156             :     PrintF("Compiling wasm function %d with %s\n\n", func_index_,
     157             :            GetExecutionTierAsString(executed_tier_));
     158             :   }
     159             : 
     160     1073488 :   WasmCompilationResult result;
     161     1073487 :   switch (executed_tier_) {
     162             :     case ExecutionTier::kBaseline:
     163     1188369 :       result =
     164      594208 :           liftoff_unit_->ExecuteCompilation(env, func_body, counters, detected);
     165      594149 :       if (result.succeeded()) break;
     166             :       // Otherwise, fall back to turbofan.
     167       23943 :       SwitchTier(ExecutionTier::kOptimized);
     168             :       // TODO(wasm): We could actually stop or remove the tiering unit for this
     169             :       // function to avoid compiling it twice with TurboFan.
     170             :       V8_FALLTHROUGH;
     171             :     case ExecutionTier::kOptimized:
     172     1006444 :       result = turbofan_unit_->ExecuteCompilation(env, func_body, counters,
     173      503213 :                                                   detected);
     174      503186 :       break;
     175             :     case ExecutionTier::kInterpreter:
     176           0 :       UNREACHABLE();  // TODO(titzer): compile interpreter entry stub.
     177             :   }
     178             : 
     179     1073371 :   if (result.succeeded()) {
     180             :     counters->wasm_generated_code_size()->Increment(
     181     1066683 :         result.code_desc.instr_size);
     182     1066660 :     counters->wasm_reloc_size()->Increment(result.code_desc.reloc_size);
     183             :   }
     184             : 
     185     1073395 :   return result;
     186             : }
     187             : 
     188     1073333 : WasmCode* WasmCompilationUnit::Publish(WasmCompilationResult result,
     189             :                                        NativeModule* native_module) {
     190     1073333 :   if (!result.succeeded()) {
     191             :     native_module->compilation_state()->SetError(func_index_,
     192       13292 :                                                  std::move(result.error));
     193        6646 :     return nullptr;
     194             :   }
     195             : 
     196             :   DCHECK(result.succeeded());
     197             :   WasmCode::Tier code_tier = executed_tier_ == ExecutionTier::kBaseline
     198             :                                  ? WasmCode::kLiftoff
     199     1066687 :                                  : WasmCode::kTurbofan;
     200             :   DCHECK_EQ(result.code_desc.buffer, result.instr_buffer.get());
     201             : 
     202             :   WasmCode* code = native_module->AddCode(
     203             :       func_index_, result.code_desc, result.frame_slot_count,
     204             :       result.tagged_parameter_slots, std::move(result.protected_instructions),
     205     4266800 :       std::move(result.source_positions), WasmCode::kFunction, code_tier);
     206             :   // TODO(clemensh): Merge this into {AddCode}?
     207     1066713 :   native_module->PublishCode(code);
     208     1066716 :   return code;
     209             : }
     210             : 
     211     1098733 : void WasmCompilationUnit::SwitchTier(ExecutionTier new_tier) {
     212             :   // This method is being called in the constructor, where neither
     213             :   // {liftoff_unit_} nor {turbofan_unit_} are set, or to switch tier from
     214             :   // kLiftoff to kTurbofan, in which case {liftoff_unit_} is already set.
     215     1098733 :   executed_tier_ = new_tier;
     216     1098733 :   switch (new_tier) {
     217             :     case ExecutionTier::kBaseline:
     218             :       DCHECK(!turbofan_unit_);
     219             :       DCHECK(!liftoff_unit_);
     220      594543 :       liftoff_unit_.reset(new LiftoffCompilationUnit(this));
     221             :       return;
     222             :     case ExecutionTier::kOptimized:
     223             :       DCHECK(!turbofan_unit_);
     224             :       liftoff_unit_.reset();
     225      504200 :       turbofan_unit_.reset(new compiler::TurbofanWasmCompilationUnit(this));
     226             :       return;
     227             :     case ExecutionTier::kInterpreter:
     228           0 :       UNREACHABLE();  // TODO(titzer): allow compiling interpreter entry stub.
     229             :   }
     230           0 :   UNREACHABLE();
     231             : }
     232             : 
     233             : // static
     234      130386 : void WasmCompilationUnit::CompileWasmFunction(Isolate* isolate,
     235             :                                               NativeModule* native_module,
     236             :                                               WasmFeatures* detected,
     237             :                                               const WasmFunction* function,
     238             :                                               ExecutionTier tier) {
     239             :   ModuleWireBytes wire_bytes(native_module->wire_bytes());
     240             :   FunctionBody function_body{function->sig, function->code.offset(),
     241             :                              wire_bytes.start() + function->code.offset(),
     242             :                              wire_bytes.start() + function->code.end_offset()};
     243             : 
     244      260772 :   WasmCompilationUnit unit(isolate->wasm_engine(), function->func_index, tier);
     245      130385 :   CompilationEnv env = native_module->CreateCompilationEnv();
     246             :   WasmCompilationResult result = unit.ExecuteCompilation(
     247             :       &env, native_module->compilation_state()->GetWireBytesStorage(),
     248      391157 :       isolate->counters(), detected);
     249      260772 :   unit.Publish(std::move(result), native_module);
     250      130386 : }
     251             : 
     252             : }  // namespace wasm
     253             : }  // namespace internal
     254      178779 : }  // namespace v8

Generated by: LCOV version 1.10