LCOV - code coverage report
Current view: top level - src/interpreter - interpreter.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 79 106 74.5 %
Date: 2017-04-26 Functions: 16 20 80.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 "src/interpreter/interpreter.h"
       6             : 
       7             : #include <fstream>
       8             : #include <memory>
       9             : 
      10             : #include "src/codegen.h"
      11             : #include "src/compilation-info.h"
      12             : #include "src/compiler.h"
      13             : #include "src/counters.h"
      14             : #include "src/interpreter/bytecode-generator.h"
      15             : #include "src/interpreter/bytecodes.h"
      16             : #include "src/log.h"
      17             : #include "src/objects.h"
      18             : #include "src/setup-isolate.h"
      19             : #include "src/visitors.h"
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : namespace interpreter {
      24             : 
      25     4154918 : class InterpreterCompilationJob final : public CompilationJob {
      26             :  public:
      27             :   explicit InterpreterCompilationJob(CompilationInfo* info);
      28             : 
      29             :  protected:
      30             :   Status PrepareJobImpl() final;
      31             :   Status ExecuteJobImpl() final;
      32             :   Status FinalizeJobImpl() final;
      33             : 
      34             :  private:
      35             :   class TimerScope final {
      36             :    public:
      37     2077433 :     TimerScope(RuntimeCallStats* stats, RuntimeCallStats::CounterId counter_id)
      38     2077433 :         : stats_(stats) {
      39     2077433 :       if (V8_UNLIKELY(FLAG_runtime_stats)) {
      40           0 :         RuntimeCallStats::Enter(stats_, &timer_, counter_id);
      41             :       }
      42     2077433 :     }
      43             : 
      44           7 :     explicit TimerScope(RuntimeCallCounter* counter) : stats_(nullptr) {
      45           7 :       if (V8_UNLIKELY(FLAG_runtime_stats)) {
      46           0 :         timer_.Start(counter, nullptr);
      47             :       }
      48           7 :     }
      49             : 
      50     2077454 :     ~TimerScope() {
      51     2077454 :       if (V8_UNLIKELY(FLAG_runtime_stats)) {
      52           0 :         if (stats_) {
      53           0 :           RuntimeCallStats::Leave(stats_, &timer_);
      54             :         } else {
      55           0 :           timer_.Stop();
      56             :         }
      57             :       }
      58     2077454 :     }
      59             : 
      60             :    private:
      61             :     RuntimeCallStats* stats_;
      62             :     RuntimeCallTimer timer_;
      63             :   };
      64             : 
      65             :   BytecodeGenerator* generator() { return &generator_; }
      66             : 
      67             :   BytecodeGenerator generator_;
      68             :   RuntimeCallStats* runtime_call_stats_;
      69             :   RuntimeCallCounter background_execute_counter_;
      70             :   bool print_bytecode_;
      71             : 
      72             :   DISALLOW_COPY_AND_ASSIGN(InterpreterCompilationJob);
      73             : };
      74             : 
      75       60782 : Interpreter::Interpreter(Isolate* isolate) : isolate_(isolate) {
      76       60782 :   memset(dispatch_table_, 0, sizeof(dispatch_table_));
      77             : 
      78       60782 :   if (FLAG_trace_ignition_dispatches) {
      79             :     static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;
      80             :     bytecode_dispatch_counters_table_.reset(
      81           6 :         new uintptr_t[kBytecodeCount * kBytecodeCount]);
      82             :     memset(bytecode_dispatch_counters_table_.get(), 0,
      83             :            sizeof(uintptr_t) * kBytecodeCount * kBytecodeCount);
      84             :   }
      85       60782 : }
      86             : 
      87       76041 : Code* Interpreter::GetBytecodeHandler(Bytecode bytecode,
      88             :                                       OperandScale operand_scale) {
      89             :   DCHECK(IsDispatchTableInitialized());
      90             :   DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale));
      91       76041 :   size_t index = GetDispatchTableIndex(bytecode, operand_scale);
      92       76041 :   Address code_entry = dispatch_table_[index];
      93       76041 :   return Code::GetCodeFromTargetAddress(code_entry);
      94             : }
      95             : 
      96             : // static
      97      113666 : size_t Interpreter::GetDispatchTableIndex(Bytecode bytecode,
      98             :                                           OperandScale operand_scale) {
      99             :   static const size_t kEntriesPerOperandScale = 1u << kBitsPerByte;
     100      113666 :   size_t index = static_cast<size_t>(bytecode);
     101      113666 :   switch (operand_scale) {
     102             :     case OperandScale::kSingle:
     103             :       return index;
     104             :     case OperandScale::kDouble:
     105       14960 :       return index + kEntriesPerOperandScale;
     106             :     case OperandScale::kQuadruple:
     107       14960 :       return index + 2 * kEntriesPerOperandScale;
     108             :   }
     109           0 :   UNREACHABLE();
     110             :   return 0;
     111             : }
     112             : 
     113      172403 : void Interpreter::IterateDispatchTable(RootVisitor* v) {
     114   132571807 :   for (int i = 0; i < kDispatchTableSize; i++) {
     115   132399411 :     Address code_entry = dispatch_table_[i];
     116             :     Object* code = code_entry == nullptr
     117             :                        ? nullptr
     118   132399411 :                        : Code::GetCodeFromTargetAddress(code_entry);
     119             :     Object* old_code = code;
     120   132399411 :     v->VisitRootPointer(Root::kDispatchTable, &code);
     121   132399404 :     if (code != old_code) {
     122    46646927 :       dispatch_table_[i] = reinterpret_cast<Code*>(code)->entry();
     123             :     }
     124             :   }
     125      172396 : }
     126             : 
     127             : // static
     128     2106964 : int Interpreter::InterruptBudget() {
     129     2106964 :   return FLAG_interrupt_budget * kCodeSizeMultiplier;
     130             : }
     131             : 
     132             : namespace {
     133             : 
     134     2077458 : bool ShouldPrintBytecode(Handle<SharedFunctionInfo> shared) {
     135     2077458 :   if (!FLAG_print_bytecode) return false;
     136             : 
     137             :   // Checks whether function passed the filter.
     138           0 :   if (shared->is_toplevel()) {
     139           0 :     Vector<const char> filter = CStrVector(FLAG_print_bytecode_filter);
     140           0 :     return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*');
     141             :   } else {
     142           0 :     return shared->PassesFilter(FLAG_print_bytecode_filter);
     143             :   }
     144             : }
     145             : 
     146             : }  // namespace
     147             : 
     148     4154920 : InterpreterCompilationJob::InterpreterCompilationJob(CompilationInfo* info)
     149             :     : CompilationJob(info->isolate(), info, "Ignition"),
     150             :       generator_(info),
     151     2077457 :       runtime_call_stats_(info->isolate()->counters()->runtime_call_stats()),
     152             :       background_execute_counter_("CompileBackgroundIgnition"),
     153     6232377 :       print_bytecode_(ShouldPrintBytecode(info->shared_info())) {}
     154             : 
     155     2077452 : InterpreterCompilationJob::Status InterpreterCompilationJob::PrepareJobImpl() {
     156     2077452 :   CodeGenerator::MakeCodePrologue(info(), "interpreter");
     157             : 
     158     2077456 :   if (print_bytecode_) {
     159           0 :     OFStream os(stdout);
     160           0 :     std::unique_ptr<char[]> name = info()->GetDebugName();
     161           0 :     os << "[generating bytecode for function: " << info()->GetDebugName().get()
     162           0 :        << "]" << std::endl
     163           0 :        << std::flush;
     164             :   }
     165             : 
     166     2077456 :   return SUCCEEDED;
     167             : }
     168             : 
     169     2077441 : InterpreterCompilationJob::Status InterpreterCompilationJob::ExecuteJobImpl() {
     170             :   TimerScope runtimeTimer =
     171     4154891 :       executed_on_background_thread()
     172             :           ? TimerScope(&background_execute_counter_)
     173     2077441 :           : TimerScope(runtime_call_stats_, &RuntimeCallStats::CompileIgnition);
     174             :   // TODO(lpy): add support for background compilation RCS trace.
     175     6232355 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileIgnition");
     176             : 
     177     2077450 :   generator()->GenerateBytecode(stack_limit());
     178             : 
     179     2077455 :   if (generator()->HasStackOverflow()) {
     180             :     return FAILED;
     181             :   }
     182     4154878 :   return SUCCEEDED;
     183             : }
     184             : 
     185     2077421 : InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl() {
     186             :   // Add background runtime call stats.
     187     6232264 :   if (V8_UNLIKELY(FLAG_runtime_stats && executed_on_background_thread())) {
     188             :     runtime_call_stats_->CompileBackgroundIgnition.Add(
     189           0 :         &background_execute_counter_);
     190             :   }
     191             : 
     192             :   RuntimeCallTimerScope runtimeTimer(
     193     2077421 :       runtime_call_stats_, &RuntimeCallStats::CompileIgnitionFinalization);
     194             : 
     195     2077419 :   Handle<BytecodeArray> bytecodes = generator()->FinalizeBytecode(isolate());
     196     2077425 :   if (generator()->HasStackOverflow()) {
     197             :     return FAILED;
     198             :   }
     199             : 
     200     2077425 :   if (print_bytecode_) {
     201           0 :     OFStream os(stdout);
     202             :     bytecodes->Print(os);
     203           0 :     os << std::flush;
     204             :   }
     205             : 
     206             :   info()->SetBytecodeArray(bytecodes);
     207     2077425 :   info()->SetCode(info()->isolate()->builtins()->InterpreterEntryTrampoline());
     208     2077418 :   return SUCCEEDED;
     209             : }
     210             : 
     211     2077454 : CompilationJob* Interpreter::NewCompilationJob(CompilationInfo* info) {
     212     2077454 :   return new InterpreterCompilationJob(info);
     213             : }
     214             : 
     215           0 : bool Interpreter::IsDispatchTableInitialized() {
     216           0 :   return dispatch_table_[0] != nullptr;
     217             : }
     218             : 
     219           0 : const char* Interpreter::LookupNameOfBytecodeHandler(Code* code) {
     220             : #ifdef ENABLE_DISASSEMBLER
     221             : #define RETURN_NAME(Name, ...)                                 \
     222             :   if (dispatch_table_[Bytecodes::ToByte(Bytecode::k##Name)] == \
     223             :       code->entry()) {                                         \
     224             :     return #Name;                                              \
     225             :   }
     226             :   BYTECODE_LIST(RETURN_NAME)
     227             : #undef RETURN_NAME
     228             : #endif  // ENABLE_DISASSEMBLER
     229           0 :   return nullptr;
     230             : }
     231             : 
     232           0 : uintptr_t Interpreter::GetDispatchCounter(Bytecode from, Bytecode to) const {
     233      762300 :   int from_index = Bytecodes::ToByte(from);
     234      762300 :   int to_index = Bytecodes::ToByte(to);
     235      762300 :   return bytecode_dispatch_counters_table_[from_index * kNumberOfBytecodes +
     236     1524600 :                                            to_index];
     237             : }
     238             : 
     239          28 : Local<v8::Object> Interpreter::GetDispatchCountersObject() {
     240          28 :   v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_);
     241          28 :   Local<v8::Context> context = isolate->GetCurrentContext();
     242             : 
     243          28 :   Local<v8::Object> counters_map = v8::Object::New(isolate);
     244             : 
     245             :   // Output is a JSON-encoded object of objects.
     246             :   //
     247             :   // The keys on the top level object are source bytecodes,
     248             :   // and corresponding value are objects. Keys on these last are the
     249             :   // destinations of the dispatch and the value associated is a counter for
     250             :   // the correspondent source-destination dispatch chain.
     251             :   //
     252             :   // Only non-zero counters are written to file, but an entry in the top-level
     253             :   // object is always present, even if the value is empty because all counters
     254             :   // for that source are zero.
     255             : 
     256        4648 :   for (int from_index = 0; from_index < kNumberOfBytecodes; ++from_index) {
     257        4620 :     Bytecode from_bytecode = Bytecodes::FromByte(from_index);
     258        4620 :     Local<v8::Object> counters_row = v8::Object::New(isolate);
     259             : 
     260      766920 :     for (int to_index = 0; to_index < kNumberOfBytecodes; ++to_index) {
     261      762300 :       Bytecode to_bytecode = Bytecodes::FromByte(to_index);
     262             :       uintptr_t counter = GetDispatchCounter(from_bytecode, to_bytecode);
     263             : 
     264      762300 :       if (counter > 0) {
     265           0 :         std::string to_name = Bytecodes::ToString(to_bytecode);
     266             :         Local<v8::String> to_name_object =
     267             :             v8::String::NewFromUtf8(isolate, to_name.c_str(),
     268             :                                     NewStringType::kNormal)
     269           0 :                 .ToLocalChecked();
     270           0 :         Local<v8::Number> counter_object = v8::Number::New(isolate, counter);
     271           0 :         CHECK(counters_row
     272             :                   ->DefineOwnProperty(context, to_name_object, counter_object)
     273             :                   .IsJust());
     274             :       }
     275             :     }
     276             : 
     277        4620 :     std::string from_name = Bytecodes::ToString(from_bytecode);
     278             :     Local<v8::String> from_name_object =
     279             :         v8::String::NewFromUtf8(isolate, from_name.c_str(),
     280             :                                 NewStringType::kNormal)
     281        4620 :             .ToLocalChecked();
     282             : 
     283        4620 :     CHECK(
     284             :         counters_map->DefineOwnProperty(context, from_name_object, counters_row)
     285             :             .IsJust());
     286             :   }
     287             : 
     288          28 :   return counters_map;
     289             : }
     290             : 
     291             : }  // namespace interpreter
     292             : }  // namespace internal
     293             : }  // namespace v8

Generated by: LCOV version 1.10