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     3934543 : 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     3934543 :   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             : #ifdef DEBUG
      73             : 
      74             : Comment::Comment(Assembler* assembler, const char* msg)
      75             :     : assembler_(assembler), msg_(msg) {
      76             :   assembler_->RecordComment(msg);
      77             : }
      78             : 
      79             : 
      80             : Comment::~Comment() {
      81             :   if (msg_[0] == '[') assembler_->RecordComment("]");
      82             : }
      83             : 
      84             : #endif  // DEBUG
      85             : 
      86             : 
      87     3437113 : void CodeGenerator::MakeCodePrologue(CompilationInfo* info, const char* kind) {
      88             :   bool print_ast = false;
      89             :   const char* ftype;
      90             : 
      91     3437113 :   if (info->isolate()->bootstrapper()->IsActive()) {
      92             :     print_ast = FLAG_print_builtin_ast;
      93             :     ftype = "builtin";
      94             :   } else {
      95             :     print_ast = FLAG_print_ast;
      96             :     ftype = "user-defined";
      97             :   }
      98             : 
      99     3437113 :   if (FLAG_trace_codegen || print_ast) {
     100           0 :     std::unique_ptr<char[]> name = info->GetDebugName();
     101             :     PrintF("[generating %s code for %s function: %s]\n", kind, ftype,
     102           0 :            name.get());
     103             :   }
     104             : 
     105             : #ifdef DEBUG
     106             :   if (info->parse_info() && print_ast) {
     107             :     PrintF("--- AST ---\n%s\n",
     108             :            AstPrinter(info->isolate()).PrintProgram(info->literal()));
     109             :   }
     110             : #endif  // DEBUG
     111     3437113 : }
     112             : 
     113     2272043 : Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
     114             :                                              EhFrameWriter* eh_frame_writer,
     115     6168805 :                                              CompilationInfo* info,
     116             :                                              Handle<Object> self_reference) {
     117     2272048 :   Isolate* isolate = info->isolate();
     118             : 
     119             :   // Allocate and install the code.
     120             :   CodeDesc desc;
     121             :   Code::Flags flags = info->code_flags();
     122             :   bool is_crankshafted =
     123     3896759 :       Code::ExtractKindFromFlags(flags) == Code::OPTIMIZED_FUNCTION ||
     124             :       info->IsStub();
     125     2272043 :   masm->GetCode(&desc);
     126     2272042 :   if (eh_frame_writer) eh_frame_writer->GetEhFrame(&desc);
     127             : 
     128             :   Handle<Code> code = isolate->factory()->NewCode(
     129             :       desc, flags, self_reference, false, is_crankshafted,
     130     4544088 :       info->prologue_offset(), info->is_debug() && !is_crankshafted);
     131             :   isolate->counters()->total_compiled_code_size()->Increment(
     132     2272048 :       code->instruction_size());
     133     2272052 :   return code;
     134             : }
     135             : 
     136             : // Print function's source if it was not printed before.
     137             : // Return a sequential id under which this function was printed.
     138           0 : static int PrintFunctionSource(CompilationInfo* info,
     139           0 :                                std::vector<Handle<SharedFunctionInfo>>* printed,
     140             :                                int inlining_id,
     141             :                                Handle<SharedFunctionInfo> shared) {
     142             :   // Outermost function has source id -1 and inlined functions take
     143             :   // source ids starting from 0.
     144             :   int source_id = -1;
     145           0 :   if (inlining_id != SourcePosition::kNotInlined) {
     146           0 :     for (unsigned i = 0; i < printed->size(); i++) {
     147           0 :       if (printed->at(i).is_identical_to(shared)) {
     148           0 :         return i;
     149             :       }
     150             :     }
     151           0 :     source_id = static_cast<int>(printed->size());
     152           0 :     printed->push_back(shared);
     153             :   }
     154             : 
     155             :   Isolate* isolate = info->isolate();
     156           0 :   if (!shared->script()->IsUndefined(isolate)) {
     157             :     Handle<Script> script(Script::cast(shared->script()), isolate);
     158             : 
     159           0 :     if (!script->source()->IsUndefined(isolate)) {
     160           0 :       CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
     161             :       Object* source_name = script->name();
     162           0 :       OFStream os(tracing_scope.file());
     163           0 :       os << "--- FUNCTION SOURCE (";
     164           0 :       if (source_name->IsString()) {
     165           0 :         os << String::cast(source_name)->ToCString().get() << ":";
     166             :       }
     167           0 :       os << shared->DebugName()->ToCString().get() << ") id{";
     168           0 :       os << info->optimization_id() << "," << source_id << "} start{";
     169           0 :       os << shared->start_position() << "} ---\n";
     170             :       {
     171             :         DisallowHeapAllocation no_allocation;
     172             :         int start = shared->start_position();
     173           0 :         int len = shared->end_position() - start;
     174             :         String::SubStringRange source(String::cast(script->source()), start,
     175             :                                       len);
     176           0 :         for (const auto& c : source) {
     177           0 :           os << AsReversiblyEscapedUC16(c);
     178             :         }
     179             :       }
     180             : 
     181           0 :       os << "\n--- END ---\n";
     182             :     }
     183             :   }
     184             : 
     185           0 :   return source_id;
     186             : }
     187             : 
     188             : // Print information for the given inlining: which function was inlined and
     189             : // where the inlining occured.
     190           0 : static void PrintInlinedFunctionInfo(
     191           0 :     CompilationInfo* info, int source_id, int inlining_id,
     192             :     const CompilationInfo::InlinedFunctionHolder& h) {
     193           0 :   CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
     194           0 :   OFStream os(tracing_scope.file());
     195           0 :   os << "INLINE (" << h.shared_info->DebugName()->ToCString().get() << ") id{"
     196           0 :      << info->optimization_id() << "," << source_id << "} AS " << inlining_id
     197           0 :      << " AT ";
     198           0 :   const SourcePosition position = h.position.position;
     199           0 :   if (position.IsKnown()) {
     200           0 :     os << "<" << position.InliningId() << ":" << position.ScriptOffset() << ">";
     201             :   } else {
     202           0 :     os << "<?>";
     203             :   }
     204             :   os << std::endl;
     205           0 : }
     206             : 
     207             : // Print the source of all functions that participated in this optimizing
     208             : // compilation. For inlined functions print source position of their inlining.
     209           0 : static void DumpParticipatingSource(CompilationInfo* info) {
     210             :   AllowDeferredHandleDereference allow_deference_for_print_code;
     211             : 
     212             :   std::vector<Handle<SharedFunctionInfo>> printed;
     213           0 :   printed.reserve(info->inlined_functions().size());
     214             : 
     215             :   PrintFunctionSource(info, &printed, SourcePosition::kNotInlined,
     216           0 :                       info->shared_info());
     217           0 :   const auto& inlined = info->inlined_functions();
     218           0 :   for (unsigned id = 0; id < inlined.size(); id++) {
     219             :     const int source_id =
     220           0 :         PrintFunctionSource(info, &printed, id, inlined[id].shared_info);
     221           0 :     PrintInlinedFunctionInfo(info, source_id, id, inlined[id]);
     222             :   }
     223           0 : }
     224             : 
     225     2272042 : void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
     226     2272042 :   if (FLAG_print_opt_source && info->IsOptimizing()) {
     227           0 :     DumpParticipatingSource(info);
     228             :   }
     229             : 
     230             : #ifdef ENABLE_DISASSEMBLER
     231             :   AllowDeferredHandleDereference allow_deference_for_print_code;
     232             :   Isolate* isolate = info->isolate();
     233             :   bool print_code =
     234             :       isolate->bootstrapper()->IsActive()
     235             :           ? FLAG_print_builtin_code
     236             :           : (FLAG_print_code || (info->IsStub() && FLAG_print_code_stubs) ||
     237             :              (info->IsOptimizing() && FLAG_print_opt_code &&
     238             :               info->shared_info()->PassesFilter(FLAG_print_opt_code_filter)) ||
     239             :              (info->IsWasm() && FLAG_print_wasm_code));
     240             :   if (print_code) {
     241             :     std::unique_ptr<char[]> debug_name = info->GetDebugName();
     242             :     CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
     243             :     OFStream os(tracing_scope.file());
     244             : 
     245             :     // Print the source code if available.
     246             :     bool print_source =
     247             :         info->parse_info() && (code->kind() == Code::OPTIMIZED_FUNCTION ||
     248             :                                code->kind() == Code::FUNCTION);
     249             :     if (print_source) {
     250             :       Handle<SharedFunctionInfo> shared = info->shared_info();
     251             :       Handle<Script> script = info->script();
     252             :       if (!script->IsUndefined(isolate) &&
     253             :           !script->source()->IsUndefined(isolate)) {
     254             :         os << "--- Raw source ---\n";
     255             :         StringCharacterStream stream(String::cast(script->source()),
     256             :                                      shared->start_position());
     257             :         // fun->end_position() points to the last character in the stream. We
     258             :         // need to compensate by adding one to calculate the length.
     259             :         int source_len = shared->end_position() - shared->start_position() + 1;
     260             :         for (int i = 0; i < source_len; i++) {
     261             :           if (stream.HasMore()) {
     262             :             os << AsReversiblyEscapedUC16(stream.GetNext());
     263             :           }
     264             :         }
     265             :         os << "\n\n";
     266             :       }
     267             :     }
     268             :     if (info->IsOptimizing()) {
     269             :       if (FLAG_print_unopt_code && info->parse_info()) {
     270             :         os << "--- Unoptimized code ---\n";
     271             :         info->closure()->shared()->code()->Disassemble(debug_name.get(), os);
     272             :       }
     273             :       os << "--- Optimized code ---\n"
     274             :          << "optimization_id = " << info->optimization_id() << "\n";
     275             :     } else {
     276             :       os << "--- Code ---\n";
     277             :     }
     278             :     if (print_source) {
     279             :       Handle<SharedFunctionInfo> shared = info->shared_info();
     280             :       os << "source_position = " << shared->start_position() << "\n";
     281             :     }
     282             :     code->Disassemble(debug_name.get(), os);
     283             :     os << "--- End code ---\n";
     284             :   }
     285             : #endif  // ENABLE_DISASSEMBLER
     286     2272042 : }
     287             : 
     288             : }  // namespace internal
     289             : }  // namespace v8

Generated by: LCOV version 1.10