LCOV - code coverage report
Current view: top level - src - codegen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 19 65 29.2 %
Date: 2017-04-26 Functions: 7 11 63.6 %

          Line data    Source code
       1             : // Copyright 2012 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/codegen.h"
       6             : 
       7             : #if defined(V8_OS_AIX)
       8             : #include <fenv.h>  // NOLINT(build/c++11)
       9             : #endif
      10             : 
      11             : #include <memory>
      12             : 
      13             : #include "src/ast/prettyprinter.h"
      14             : #include "src/bootstrapper.h"
      15             : #include "src/compilation-info.h"
      16             : #include "src/counters.h"
      17             : #include "src/debug/debug.h"
      18             : #include "src/eh-frame.h"
      19             : #include "src/objects-inl.h"
      20             : #include "src/runtime/runtime.h"
      21             : 
      22             : namespace v8 {
      23             : namespace internal {
      24             : 
      25             : 
      26             : #if defined(V8_OS_WIN)
      27             : double modulo(double x, double y) {
      28             :   // Workaround MS fmod bugs. ECMA-262 says:
      29             :   // dividend is finite and divisor is an infinity => result equals dividend
      30             :   // dividend is a zero and divisor is nonzero finite => result equals dividend
      31             :   if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) &&
      32             :       !(x == 0 && (y != 0 && std::isfinite(y)))) {
      33             :     x = fmod(x, y);
      34             :   }
      35             :   return x;
      36             : }
      37             : #else  // POSIX
      38             : 
      39     3912950 : double modulo(double x, double y) {
      40             : #if defined(V8_OS_AIX)
      41             :   // AIX raises an underflow exception for (Number.MIN_VALUE % Number.MAX_VALUE)
      42             :   feclearexcept(FE_ALL_EXCEPT);
      43             :   double result = std::fmod(x, y);
      44             :   int exception = fetestexcept(FE_UNDERFLOW);
      45             :   return (exception ? x : result);
      46             : #else
      47     3912950 :   return std::fmod(x, y);
      48             : #endif
      49             : }
      50             : #endif  // defined(V8_OS_WIN)
      51             : 
      52             : 
      53             : #define UNARY_MATH_FUNCTION(name, generator)                             \
      54             :   static UnaryMathFunctionWithIsolate fast_##name##_function = nullptr;  \
      55             :   double std_##name(double x, Isolate* isolate) { return std::name(x); } \
      56             :   void init_fast_##name##_function(Isolate* isolate) {                   \
      57             :     if (FLAG_fast_math) fast_##name##_function = generator(isolate);     \
      58             :     if (!fast_##name##_function) fast_##name##_function = std_##name;    \
      59             :   }                                                                      \
      60             :   void lazily_initialize_fast_##name(Isolate* isolate) {                 \
      61             :     if (!fast_##name##_function) init_fast_##name##_function(isolate);   \
      62             :   }                                                                      \
      63             :   double fast_##name(double x, Isolate* isolate) {                       \
      64             :     return (*fast_##name##_function)(x, isolate);                        \
      65             :   }
      66             : 
      67          14 : UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction)
      68             : 
      69             : #undef UNARY_MATH_FUNCTION
      70             : 
      71             : 
      72             : #define __ ACCESS_MASM(masm_)
      73             : 
      74             : #ifdef DEBUG
      75             : 
      76             : Comment::Comment(MacroAssembler* masm, const char* msg)
      77             :     : masm_(masm), msg_(msg) {
      78             :   __ RecordComment(msg);
      79             : }
      80             : 
      81             : 
      82             : Comment::~Comment() {
      83             :   if (msg_[0] == '[') __ RecordComment("]");
      84             : }
      85             : 
      86             : #endif  // DEBUG
      87             : 
      88             : #undef __
      89             : 
      90             : 
      91     3434775 : void CodeGenerator::MakeCodePrologue(CompilationInfo* info, const char* kind) {
      92             :   bool print_ast = false;
      93             :   const char* ftype;
      94             : 
      95     3434775 :   if (info->isolate()->bootstrapper()->IsActive()) {
      96             :     print_ast = FLAG_print_builtin_ast;
      97             :     ftype = "builtin";
      98             :   } else {
      99             :     print_ast = FLAG_print_ast;
     100             :     ftype = "user-defined";
     101             :   }
     102             : 
     103     3434775 :   if (FLAG_trace_codegen || print_ast) {
     104           0 :     std::unique_ptr<char[]> name = info->GetDebugName();
     105             :     PrintF("[generating %s code for %s function: %s]\n", kind, ftype,
     106           0 :            name.get());
     107             :   }
     108             : 
     109             : #ifdef DEBUG
     110             :   if (info->parse_info() && print_ast) {
     111             :     PrintF("--- AST ---\n%s\n",
     112             :            AstPrinter(info->isolate()).PrintProgram(info->literal()));
     113             :   }
     114             : #endif  // DEBUG
     115     3434775 : }
     116             : 
     117     2270647 : Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
     118             :                                              EhFrameWriter* eh_frame_writer,
     119     6165098 :                                              CompilationInfo* info,
     120             :                                              Handle<Object> self_reference) {
     121     2270649 :   Isolate* isolate = info->isolate();
     122             : 
     123             :   // Allocate and install the code.
     124             :   CodeDesc desc;
     125             :   Code::Flags flags = info->code_flags();
     126             :   bool is_crankshafted =
     127     3894451 :       Code::ExtractKindFromFlags(flags) == Code::OPTIMIZED_FUNCTION ||
     128             :       info->IsStub();
     129     2270647 :   masm->GetCode(&desc);
     130     2270647 :   if (eh_frame_writer) eh_frame_writer->GetEhFrame(&desc);
     131             : 
     132             :   Handle<Code> code = isolate->factory()->NewCode(
     133             :       desc, flags, self_reference, false, is_crankshafted,
     134     4541294 :       info->prologue_offset(), info->is_debug() && !is_crankshafted);
     135             :   isolate->counters()->total_compiled_code_size()->Increment(
     136     2270649 :       code->instruction_size());
     137     2270649 :   return code;
     138             : }
     139             : 
     140             : // Print function's source if it was not printed before.
     141             : // Return a sequential id under which this function was printed.
     142           0 : static int PrintFunctionSource(CompilationInfo* info,
     143           0 :                                std::vector<Handle<SharedFunctionInfo>>* printed,
     144             :                                int inlining_id,
     145             :                                Handle<SharedFunctionInfo> shared) {
     146             :   // Outermost function has source id -1 and inlined functions take
     147             :   // source ids starting from 0.
     148             :   int source_id = -1;
     149           0 :   if (inlining_id != SourcePosition::kNotInlined) {
     150           0 :     for (unsigned i = 0; i < printed->size(); i++) {
     151           0 :       if (printed->at(i).is_identical_to(shared)) {
     152           0 :         return i;
     153             :       }
     154             :     }
     155           0 :     source_id = static_cast<int>(printed->size());
     156           0 :     printed->push_back(shared);
     157             :   }
     158             : 
     159             :   Isolate* isolate = info->isolate();
     160           0 :   if (!shared->script()->IsUndefined(isolate)) {
     161             :     Handle<Script> script(Script::cast(shared->script()), isolate);
     162             : 
     163           0 :     if (!script->source()->IsUndefined(isolate)) {
     164           0 :       CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
     165             :       Object* source_name = script->name();
     166           0 :       OFStream os(tracing_scope.file());
     167           0 :       os << "--- FUNCTION SOURCE (";
     168           0 :       if (source_name->IsString()) {
     169           0 :         os << String::cast(source_name)->ToCString().get() << ":";
     170             :       }
     171           0 :       os << shared->DebugName()->ToCString().get() << ") id{";
     172           0 :       os << info->optimization_id() << "," << source_id << "} start{";
     173           0 :       os << shared->start_position() << "} ---\n";
     174             :       {
     175             :         DisallowHeapAllocation no_allocation;
     176             :         int start = shared->start_position();
     177           0 :         int len = shared->end_position() - start;
     178             :         String::SubStringRange source(String::cast(script->source()), start,
     179             :                                       len);
     180           0 :         for (const auto& c : source) {
     181           0 :           os << AsReversiblyEscapedUC16(c);
     182             :         }
     183             :       }
     184             : 
     185           0 :       os << "\n--- END ---\n";
     186             :     }
     187             :   }
     188             : 
     189           0 :   return source_id;
     190             : }
     191             : 
     192             : // Print information for the given inlining: which function was inlined and
     193             : // where the inlining occured.
     194           0 : static void PrintInlinedFunctionInfo(
     195           0 :     CompilationInfo* info, int source_id, int inlining_id,
     196             :     const CompilationInfo::InlinedFunctionHolder& h) {
     197           0 :   CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
     198           0 :   OFStream os(tracing_scope.file());
     199           0 :   os << "INLINE (" << h.shared_info->DebugName()->ToCString().get() << ") id{"
     200           0 :      << info->optimization_id() << "," << source_id << "} AS " << inlining_id
     201           0 :      << " AT ";
     202           0 :   const SourcePosition position = h.position.position;
     203           0 :   if (position.IsKnown()) {
     204           0 :     os << "<" << position.InliningId() << ":" << position.ScriptOffset() << ">";
     205             :   } else {
     206           0 :     os << "<?>";
     207             :   }
     208             :   os << std::endl;
     209           0 : }
     210             : 
     211             : // Print the source of all functions that participated in this optimizing
     212             : // compilation. For inlined functions print source position of their inlining.
     213           0 : static void DumpParticipatingSource(CompilationInfo* info) {
     214             :   AllowDeferredHandleDereference allow_deference_for_print_code;
     215             : 
     216             :   std::vector<Handle<SharedFunctionInfo>> printed;
     217           0 :   printed.reserve(info->inlined_functions().size());
     218             : 
     219             :   PrintFunctionSource(info, &printed, SourcePosition::kNotInlined,
     220           0 :                       info->shared_info());
     221           0 :   const auto& inlined = info->inlined_functions();
     222           0 :   for (unsigned id = 0; id < inlined.size(); id++) {
     223             :     const int source_id =
     224           0 :         PrintFunctionSource(info, &printed, id, inlined[id].shared_info);
     225           0 :     PrintInlinedFunctionInfo(info, source_id, id, inlined[id]);
     226             :   }
     227           0 : }
     228             : 
     229     2270646 : void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
     230     2270646 :   if (FLAG_print_opt_source && info->IsOptimizing()) {
     231           0 :     DumpParticipatingSource(info);
     232             :   }
     233             : 
     234             : #ifdef ENABLE_DISASSEMBLER
     235             :   AllowDeferredHandleDereference allow_deference_for_print_code;
     236             :   Isolate* isolate = info->isolate();
     237             :   bool print_code =
     238             :       isolate->bootstrapper()->IsActive()
     239             :           ? FLAG_print_builtin_code
     240             :           : (FLAG_print_code || (info->IsStub() && FLAG_print_code_stubs) ||
     241             :              (info->IsOptimizing() && FLAG_print_opt_code &&
     242             :               info->shared_info()->PassesFilter(FLAG_print_opt_code_filter)) ||
     243             :              (info->IsWasm() && FLAG_print_wasm_code));
     244             :   if (print_code) {
     245             :     std::unique_ptr<char[]> debug_name = info->GetDebugName();
     246             :     CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
     247             :     OFStream os(tracing_scope.file());
     248             : 
     249             :     // Print the source code if available.
     250             :     bool print_source =
     251             :         info->parse_info() && (code->kind() == Code::OPTIMIZED_FUNCTION ||
     252             :                                code->kind() == Code::FUNCTION);
     253             :     if (print_source) {
     254             :       Handle<SharedFunctionInfo> shared = info->shared_info();
     255             :       Handle<Script> script = info->script();
     256             :       if (!script->IsUndefined(isolate) &&
     257             :           !script->source()->IsUndefined(isolate)) {
     258             :         os << "--- Raw source ---\n";
     259             :         StringCharacterStream stream(String::cast(script->source()),
     260             :                                      shared->start_position());
     261             :         // fun->end_position() points to the last character in the stream. We
     262             :         // need to compensate by adding one to calculate the length.
     263             :         int source_len = shared->end_position() - shared->start_position() + 1;
     264             :         for (int i = 0; i < source_len; i++) {
     265             :           if (stream.HasMore()) {
     266             :             os << AsReversiblyEscapedUC16(stream.GetNext());
     267             :           }
     268             :         }
     269             :         os << "\n\n";
     270             :       }
     271             :     }
     272             :     if (info->IsOptimizing()) {
     273             :       if (FLAG_print_unopt_code && info->parse_info()) {
     274             :         os << "--- Unoptimized code ---\n";
     275             :         info->closure()->shared()->code()->Disassemble(debug_name.get(), os);
     276             :       }
     277             :       os << "--- Optimized code ---\n"
     278             :          << "optimization_id = " << info->optimization_id() << "\n";
     279             :     } else {
     280             :       os << "--- Code ---\n";
     281             :     }
     282             :     if (print_source) {
     283             :       Handle<SharedFunctionInfo> shared = info->shared_info();
     284             :       os << "source_position = " << shared->start_position() << "\n";
     285             :     }
     286             :     code->Disassemble(debug_name.get(), os);
     287             :     os << "--- End code ---\n";
     288             :   }
     289             : #endif  // ENABLE_DISASSEMBLER
     290     2270646 : }
     291             : 
     292             : }  // namespace internal
     293             : }  // namespace v8

Generated by: LCOV version 1.10