LCOV - code coverage report
Current view: top level - src/crankshaft - lithium-codegen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 141 155 91.0 %
Date: 2017-04-26 Functions: 17 19 89.5 %

          Line data    Source code
       1             : // Copyright 2013 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/crankshaft/lithium-codegen.h"
       6             : 
       7             : #include <sstream>
       8             : 
       9             : #include "src/objects-inl.h"
      10             : 
      11             : #if V8_TARGET_ARCH_IA32
      12             : #include "src/crankshaft/ia32/lithium-ia32.h"  // NOLINT
      13             : #include "src/crankshaft/ia32/lithium-codegen-ia32.h"  // NOLINT
      14             : #elif V8_TARGET_ARCH_X64
      15             : #include "src/crankshaft/x64/lithium-x64.h"  // NOLINT
      16             : #include "src/crankshaft/x64/lithium-codegen-x64.h"  // NOLINT
      17             : #elif V8_TARGET_ARCH_ARM
      18             : #include "src/crankshaft/arm/lithium-arm.h"  // NOLINT
      19             : #include "src/crankshaft/arm/lithium-codegen-arm.h"  // NOLINT
      20             : #elif V8_TARGET_ARCH_ARM64
      21             : #include "src/crankshaft/arm64/lithium-arm64.h"  // NOLINT
      22             : #include "src/crankshaft/arm64/lithium-codegen-arm64.h"  // NOLINT
      23             : #elif V8_TARGET_ARCH_MIPS
      24             : #include "src/crankshaft/mips/lithium-mips.h"  // NOLINT
      25             : #include "src/crankshaft/mips/lithium-codegen-mips.h"  // NOLINT
      26             : #elif V8_TARGET_ARCH_MIPS64
      27             : #include "src/crankshaft/mips64/lithium-mips64.h"  // NOLINT
      28             : #include "src/crankshaft/mips64/lithium-codegen-mips64.h"  // NOLINT
      29             : #elif V8_TARGET_ARCH_X87
      30             : #include "src/crankshaft/x87/lithium-x87.h"  // NOLINT
      31             : #include "src/crankshaft/x87/lithium-codegen-x87.h"  // NOLINT
      32             : #elif V8_TARGET_ARCH_PPC
      33             : #include "src/crankshaft/ppc/lithium-ppc.h"          // NOLINT
      34             : #include "src/crankshaft/ppc/lithium-codegen-ppc.h"  // NOLINT
      35             : #elif V8_TARGET_ARCH_S390
      36             : #include "src/crankshaft/s390/lithium-s390.h"          // NOLINT
      37             : #include "src/crankshaft/s390/lithium-codegen-s390.h"  // NOLINT
      38             : #else
      39             : #error Unsupported target architecture.
      40             : #endif
      41             : 
      42             : #include "src/globals.h"
      43             : 
      44             : namespace v8 {
      45             : namespace internal {
      46             : 
      47             : 
      48     2973168 : HGraph* LCodeGenBase::graph() const {
      49     2973168 :   return chunk()->graph();
      50             : }
      51             : 
      52      279085 : LCodeGenBase::LCodeGenBase(LChunk* chunk, MacroAssembler* assembler,
      53     1116340 :                            CompilationInfo* info)
      54             :     : chunk_(static_cast<LPlatformChunk*>(chunk)),
      55             :       masm_(assembler),
      56             :       info_(info),
      57             :       zone_(info->zone()),
      58             :       status_(UNUSED),
      59             :       current_block_(-1),
      60             :       current_instruction_(-1),
      61      279085 :       instructions_(chunk->instructions()),
      62             :       deoptimizations_(4, info->zone()),
      63             :       deoptimization_literals_(8, info->zone()),
      64             :       translations_(info->zone()),
      65             :       inlined_function_count_(0),
      66             :       last_lazy_deopt_pc_(0),
      67             :       osr_pc_offset_(-1),
      68             :       source_position_table_builder_(info->zone(),
      69     1674510 :                                      info->SourcePositionRecordingMode()) {}
      70             : 
      71    20626105 : Isolate* LCodeGenBase::isolate() const { return info_->isolate(); }
      72             : 
      73    45091981 : bool LCodeGenBase::GenerateBody() {
      74             :   DCHECK(is_generating());
      75             :   bool emit_instructions = true;
      76             :   LCodeGen* codegen = static_cast<LCodeGen*>(this);
      77    88509452 :   for (current_instruction_ = 0;
      78    88509403 :        !is_aborted() && current_instruction_ < instructions_->length();
      79             :        current_instruction_++) {
      80   165489439 :     LInstruction* instr = instructions_->at(current_instruction_);
      81             : 
      82             :     // Don't emit code for basic blocks with a replacement.
      83    43975630 :     if (instr->IsLabel()) {
      84     6889008 :       emit_instructions = !LLabel::cast(instr)->HasReplacement() &&
      85     4895182 :           (!FLAG_unreachable_code_elimination ||
      86     2447591 :            instr->hydrogen_value()->block()->IsReachable());
      87     4441417 :       if (FLAG_code_comments && !emit_instructions) {
      88             :         Comment(
      89             :             ";;; <@%d,#%d> -------------------- B%d (unreachable/replaced) "
      90             :             "--------------------",
      91             :             current_instruction_,
      92             :             instr->hydrogen_value()->id(),
      93           0 :             instr->hydrogen_value()->block()->block_id());
      94             :       }
      95             :     }
      96    43975639 :     if (!emit_instructions) continue;
      97             : 
      98    30835952 :     if (FLAG_code_comments && instr->HasInterestingComment(codegen)) {
      99             :       Comment(";;; <@%d,#%d> %s",
     100             :               current_instruction_,
     101             :               instr->hydrogen_value()->id(),
     102           0 :               instr->Mnemonic());
     103             :     }
     104             : 
     105    30835952 :     GenerateBodyInstructionPre(instr);
     106             : 
     107             :     HValue* value = instr->hydrogen_value();
     108    61671769 :     if (value->position().IsKnown()) {
     109    20074562 :       RecordAndWritePosition(value->position());
     110             :     }
     111             : 
     112    30835906 :     instr->CompileToNative(codegen);
     113             : 
     114    30835973 :     GenerateBodyInstructionPost(instr);
     115             :   }
     116      279085 :   EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
     117      558168 :   last_lazy_deopt_pc_ = masm()->pc_offset();
     118      279084 :   return !is_aborted();
     119             : }
     120             : 
     121             : 
     122      279048 : void LCodeGenBase::CheckEnvironmentUsage() {
     123             : #ifdef DEBUG
     124             :   bool dead_block = false;
     125             :   for (int i = 0; i < instructions_->length(); i++) {
     126             :     LInstruction* instr = instructions_->at(i);
     127             :     HValue* hval = instr->hydrogen_value();
     128             :     if (instr->IsLabel()) dead_block = LLabel::cast(instr)->HasReplacement();
     129             :     if (dead_block || !hval->block()->IsReachable()) continue;
     130             : 
     131             :     HInstruction* hinstr = HInstruction::cast(hval);
     132             :     if (!hinstr->CanDeoptimize() && instr->HasEnvironment()) {
     133             :       V8_Fatal(__FILE__, __LINE__, "CanDeoptimize is wrong for %s (%s)",
     134             :                hinstr->Mnemonic(), instr->Mnemonic());
     135             :     }
     136             : 
     137             :     if (instr->HasEnvironment() && !instr->environment()->has_been_used()) {
     138             :       V8_Fatal(__FILE__, __LINE__, "unused environment for %s (%s)",
     139             :                hinstr->Mnemonic(), instr->Mnemonic());
     140             :     }
     141             :   }
     142             : #endif
     143      279048 : }
     144             : 
     145    20228691 : void LCodeGenBase::RecordAndWritePosition(SourcePosition pos) {
     146    40457433 :   if (!pos.IsKnown()) return;
     147    40417962 :   source_position_table_builder_.AddPosition(masm_->pc_offset(), pos, false);
     148             : }
     149             : 
     150     2819322 : void LCodeGenBase::Comment(const char* format, ...) {
     151     5638644 :   if (!FLAG_code_comments) return;
     152             :   char buffer[4 * KB];
     153             :   StringBuilder builder(buffer, arraysize(buffer));
     154             :   va_list arguments;
     155           0 :   va_start(arguments, format);
     156           0 :   builder.AddFormattedList(format, arguments);
     157           0 :   va_end(arguments);
     158             : 
     159             :   // Copy the string before recording it in the assembler to avoid
     160             :   // issues when the stack allocated buffer goes out of scope.
     161           0 :   size_t length = builder.position();
     162           0 :   Vector<char> copy = Vector<char>::New(static_cast<int>(length) + 1);
     163           0 :   MemCopy(copy.start(), builder.Finalize(), copy.length());
     164           0 :   masm()->RecordComment(copy.start());
     165             : }
     166             : 
     167             : 
     168     1435909 : void LCodeGenBase::DeoptComment(const Deoptimizer::DeoptInfo& deopt_info) {
     169      635736 :   SourcePosition position = deopt_info.position;
     170      635736 :   int deopt_id = deopt_info.deopt_id;
     171      635736 :   if (masm()->isolate()->NeedsSourcePositionsForProfiling()) {
     172      328874 :     masm()->RecordDeoptReason(deopt_info.deopt_reason, position, deopt_id);
     173             :   }
     174      635736 : }
     175             : 
     176             : 
     177     1550393 : int LCodeGenBase::GetNextEmittedBlock() const {
     178     5946336 :   for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) {
     179     5945678 :     if (!graph()->blocks()->at(i)->IsReachable()) continue;
     180     2721407 :     if (!chunk_->GetLabel(i)->HasReplacement()) return i;
     181             :   }
     182             :   return -1;
     183             : }
     184             : 
     185             : 
     186           5 : void LCodeGenBase::Abort(BailoutReason reason) {
     187             :   info()->AbortOptimization(reason);
     188           5 :   status_ = ABORTED;
     189           5 : }
     190             : 
     191             : 
     192          32 : void LCodeGenBase::Retry(BailoutReason reason) {
     193             :   info()->RetryOptimization(reason);
     194          32 :   status_ = ABORTED;
     195           0 : }
     196             : 
     197             : 
     198        9704 : void LCodeGenBase::AddDeprecationDependency(Handle<Map> map) {
     199       19408 :   if (map->is_deprecated()) return Retry(kMapBecameDeprecated);
     200        9684 :   chunk_->AddDeprecationDependency(map);
     201             : }
     202             : 
     203             : 
     204      110904 : void LCodeGenBase::AddStabilityDependency(Handle<Map> map) {
     205      221808 :   if (!map->is_stable()) return Retry(kMapBecameUnstable);
     206      110892 :   chunk_->AddStabilityDependency(map);
     207             : }
     208             : 
     209             : 
     210    20913753 : int LCodeGenBase::DefineDeoptimizationLiteral(Handle<Object> literal) {
     211   303962127 :   int result = deoptimization_literals_.length();
     212   284406466 :   for (int i = 0; i < deoptimization_literals_.length(); ++i) {
     213   283727420 :     if (deoptimization_literals_[i].is_identical_to(literal)) return i;
     214             :   }
     215             :   deoptimization_literals_.Add(literal, zone());
     216      679045 :   return result;
     217             : }
     218             : 
     219             : 
     220    13706907 : void LCodeGenBase::WriteTranslationFrame(LEnvironment* environment,
     221     7346804 :                                          Translation* translation) {
     222             :   int translation_size = environment->translation_size();
     223             :   // The output frame height does not include the parameters.
     224     4587585 :   int height = translation_size - environment->parameter_count();
     225             : 
     226     4587585 :   switch (environment->frame_type()) {
     227             :     case JS_FUNCTION: {
     228             :       int shared_id = DefineDeoptimizationLiteral(
     229             :           environment->entry() ? environment->entry()->shared()
     230    10269423 :                                : info()->shared_info());
     231     3995332 :       translation->BeginJSFrame(environment->ast_id(), shared_id, height);
     232     3995331 :       if (info()->closure().is_identical_to(environment->closure())) {
     233     2278755 :         translation->StoreJSFrameFunction();
     234             :       } else {
     235     1716576 :         int closure_id = DefineDeoptimizationLiteral(environment->closure());
     236     1716576 :         translation->StoreLiteral(closure_id);
     237             :       }
     238             :       break;
     239             :     }
     240             :     case JS_CONSTRUCT: {
     241             :       int shared_id = DefineDeoptimizationLiteral(
     242             :           environment->entry() ? environment->entry()->shared()
     243        3606 :                                : info()->shared_info());
     244             :       translation->BeginConstructStubFrame(BailoutId::ConstructStubInvoke(),
     245        1202 :                                            shared_id, translation_size);
     246        1202 :       if (info()->closure().is_identical_to(environment->closure())) {
     247           0 :         translation->StoreJSFrameFunction();
     248             :       } else {
     249        1202 :         int closure_id = DefineDeoptimizationLiteral(environment->closure());
     250        1202 :         translation->StoreLiteral(closure_id);
     251             :       }
     252             :       break;
     253             :     }
     254             :     case JS_GETTER: {
     255             :       DCHECK_EQ(1, translation_size);
     256             :       DCHECK_EQ(0, height);
     257             :       int shared_id = DefineDeoptimizationLiteral(
     258             :           environment->entry() ? environment->entry()->shared()
     259       29049 :                                : info()->shared_info());
     260        9683 :       translation->BeginGetterStubFrame(shared_id);
     261        9683 :       if (info()->closure().is_identical_to(environment->closure())) {
     262           0 :         translation->StoreJSFrameFunction();
     263             :       } else {
     264        9683 :         int closure_id = DefineDeoptimizationLiteral(environment->closure());
     265        9683 :         translation->StoreLiteral(closure_id);
     266             :       }
     267             :       break;
     268             :     }
     269             :     case JS_SETTER: {
     270             :       DCHECK_EQ(2, translation_size);
     271             :       DCHECK_EQ(0, height);
     272             :       int shared_id = DefineDeoptimizationLiteral(
     273             :           environment->entry() ? environment->entry()->shared()
     274        2424 :                                : info()->shared_info());
     275         808 :       translation->BeginSetterStubFrame(shared_id);
     276         808 :       if (info()->closure().is_identical_to(environment->closure())) {
     277           0 :         translation->StoreJSFrameFunction();
     278             :       } else {
     279         808 :         int closure_id = DefineDeoptimizationLiteral(environment->closure());
     280         808 :         translation->StoreLiteral(closure_id);
     281             :       }
     282             :       break;
     283             :     }
     284             :     case TAIL_CALLER_FUNCTION: {
     285             :       DCHECK_EQ(0, translation_size);
     286             :       int shared_id = DefineDeoptimizationLiteral(
     287             :           environment->entry() ? environment->entry()->shared()
     288         379 :                                : info()->shared_info());
     289         157 :       translation->BeginTailCallerFrame(shared_id);
     290         157 :       if (info()->closure().is_identical_to(environment->closure())) {
     291          65 :         translation->StoreJSFrameFunction();
     292             :       } else {
     293          92 :         int closure_id = DefineDeoptimizationLiteral(environment->closure());
     294          92 :         translation->StoreLiteral(closure_id);
     295             :       }
     296             :       break;
     297             :     }
     298             :     case ARGUMENTS_ADAPTOR: {
     299             :       int shared_id = DefineDeoptimizationLiteral(
     300             :           environment->entry() ? environment->entry()->shared()
     301     1573662 :                                : info()->shared_info());
     302      524554 :       translation->BeginArgumentsAdaptorFrame(shared_id, translation_size);
     303      524554 :       if (info()->closure().is_identical_to(environment->closure())) {
     304           0 :         translation->StoreJSFrameFunction();
     305             :       } else {
     306      524554 :         int closure_id = DefineDeoptimizationLiteral(environment->closure());
     307      524554 :         translation->StoreLiteral(closure_id);
     308             :       }
     309             :       break;
     310             :     }
     311             :     case STUB:
     312       55849 :       translation->BeginCompiledStubFrame(translation_size);
     313       55849 :       break;
     314             :   }
     315     4587583 : }
     316             : 
     317             : namespace {
     318             : 
     319      279047 : Handle<PodArray<InliningPosition>> CreateInliningPositions(
     320      279047 :     CompilationInfo* info) {
     321      402525 :   const CompilationInfo::InlinedFunctionList& inlined_functions =
     322             :       info->inlined_functions();
     323      279047 :   if (inlined_functions.size() == 0) {
     324             :     return Handle<PodArray<InliningPosition>>::cast(
     325             :         info->isolate()->factory()->empty_byte_array());
     326             :   }
     327             :   Handle<PodArray<InliningPosition>> inl_positions =
     328             :       PodArray<InliningPosition>::New(
     329       18100 :           info->isolate(), static_cast<int>(inlined_functions.size()), TENURED);
     330      246956 :   for (size_t i = 0; i < inlined_functions.size(); ++i) {
     331      105378 :     inl_positions->set(static_cast<int>(i), inlined_functions[i].position);
     332             :   }
     333       18100 :   return inl_positions;
     334             : }
     335             : 
     336             : }  // namespace
     337             : 
     338      558096 : void LCodeGenBase::PopulateDeoptimizationData(Handle<Code> code) {
     339     2613259 :   int length = deoptimizations_.length();
     340      279048 :   if (length == 0) return;
     341             :   Handle<DeoptimizationInputData> data =
     342      279048 :       DeoptimizationInputData::New(isolate(), length, TENURED);
     343             : 
     344             :   Handle<ByteArray> translations =
     345      279048 :       translations_.CreateByteArray(isolate()->factory());
     346             :   data->SetTranslationByteArray(*translations);
     347      279048 :   data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
     348      558096 :   data->SetOptimizationId(Smi::FromInt(info_->optimization_id()));
     349      558096 :   if (info_->IsOptimizing()) {
     350             :     // Reference to shared function info does not change between phases.
     351             :     AllowDeferredHandleDereference allow_handle_dereference;
     352      511030 :     data->SetSharedFunctionInfo(*info_->shared_info());
     353             :   } else {
     354             :     data->SetSharedFunctionInfo(Smi::kZero);
     355             :   }
     356             :   data->SetWeakCellCache(Smi::kZero);
     357             : 
     358             :   Handle<FixedArray> literals =
     359     2194970 :       factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
     360             :   {
     361             :     AllowDeferredHandleDereference copy_handles;
     362     1915922 :     for (int i = 0; i < deoptimization_literals_.length(); i++) {
     363      678913 :       literals->set(i, *deoptimization_literals_[i]);
     364             :     }
     365             :     data->SetLiteralArray(*literals);
     366             :   }
     367             : 
     368      279047 :   Handle<PodArray<InliningPosition>> inl_pos = CreateInliningPositions(info_);
     369             :   data->SetInliningPositions(*inl_pos);
     370             : 
     371      279047 :   data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
     372      279047 :   data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
     373             : 
     374             :   // Populate the deoptimization entries.
     375     2613259 :   for (int i = 0; i < length; i++) {
     376     9336846 :     LEnvironment* env = deoptimizations_[i];
     377             :     data->SetAstId(i, env->ast_id());
     378     2334212 :     data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
     379             :     data->SetArgumentsStackHeight(i,
     380     2334212 :                                   Smi::FromInt(env->arguments_stack_height()));
     381     2334211 :     data->SetPc(i, Smi::FromInt(env->pc_offset()));
     382             :   }
     383      279048 :   code->set_deoptimization_data(*data);
     384             : }
     385             : 
     386             : 
     387      769082 : void LCodeGenBase::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
     388             :   DCHECK_EQ(0, deoptimization_literals_.length());
     389      663626 :   for (CompilationInfo::InlinedFunctionHolder& inlined :
     390             :        info()->inlined_functions()) {
     391      210912 :     if (!inlined.shared_info.is_identical_to(info()->shared_info())) {
     392      105431 :       int index = DefineDeoptimizationLiteral(inlined.shared_info);
     393             :       inlined.RegisterInlinedFunctionId(index);
     394             :     }
     395             :   }
     396      279085 :   inlined_function_count_ = deoptimization_literals_.length();
     397             : 
     398             :   // Define deoptimization literals for all unoptimized code objects of inlined
     399             :   // functions. This ensures unoptimized code is kept alive by optimized code.
     400      663626 :   for (const CompilationInfo::InlinedFunctionHolder& inlined :
     401             :        info()->inlined_functions()) {
     402      210912 :     if (!inlined.shared_info.is_identical_to(info()->shared_info())) {
     403      105431 :       DefineDeoptimizationLiteral(inlined.inlined_code_object_root);
     404             :     }
     405             :   }
     406      279085 : }
     407             : 
     408      779377 : Deoptimizer::DeoptInfo LCodeGenBase::MakeDeoptInfo(
     409      779377 :     LInstruction* instr, DeoptimizeReason deopt_reason, int deopt_id) {
     410      779377 :   Deoptimizer::DeoptInfo deopt_info(instr->hydrogen_value()->position(),
     411      779377 :                                     deopt_reason, deopt_id);
     412      779377 :   return deopt_info;
     413             : }
     414             : 
     415             : }  // namespace internal
     416             : }  // namespace v8

Generated by: LCOV version 1.10