LCOV - code coverage report
Current view: top level - src/crankshaft - hydrogen-store-elimination.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 36 50 72.0 %
Date: 2017-04-26 Functions: 4 4 100.0 %

          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/hydrogen-store-elimination.h"
       6             : 
       7             : #include "src/crankshaft/hydrogen-instructions.h"
       8             : #include "src/objects-inl.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : 
      13             : #define TRACE(x) if (FLAG_trace_store_elimination) PrintF x
      14             : 
      15             : // Performs a block-by-block local analysis for removable stores.
      16          39 : void HStoreEliminationPhase::Run() {
      17             :   GVNFlagSet flags;  // Use GVN flags as an approximation for some instructions.
      18             :   flags.RemoveAll();
      19             : 
      20             :   flags.Add(kArrayElements);
      21             :   flags.Add(kArrayLengths);
      22             :   flags.Add(kStringLengths);
      23             :   flags.Add(kBackingStoreFields);
      24             :   flags.Add(kDoubleArrayElements);
      25             :   flags.Add(kDoubleFields);
      26             :   flags.Add(kElementsPointer);
      27             :   flags.Add(kInobjectFields);
      28             :   flags.Add(kExternalMemory);
      29             :   flags.Add(kStringChars);
      30             :   flags.Add(kTypedArrayElements);
      31             : 
      32         724 :   for (int i = 0; i < graph()->blocks()->length(); i++) {
      33             :     unobserved_.Rewind(0);
      34         685 :     HBasicBlock* block = graph()->blocks()->at(i);
      35         323 :     if (!block->IsReachable()) continue;
      36        3208 :     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
      37             :       HInstruction* instr = it.Current();
      38        5774 :       if (instr->CheckFlag(HValue::kIsDead)) continue;
      39             : 
      40        2804 :       switch (instr->opcode()) {
      41             :         case HValue::kStoreNamedField:
      42             :           // Remove any unobserved stores overwritten by this store.
      43         253 :           ProcessStore(HStoreNamedField::cast(instr));
      44         253 :           break;
      45             :         case HValue::kLoadNamedField:
      46             :           // Observe any unobserved stores on this object + field.
      47          27 :           ProcessLoad(HLoadNamedField::cast(instr));
      48          27 :           break;
      49             :         default:
      50        2524 :           ProcessInstr(instr, flags);
      51        2524 :           break;
      52             :       }
      53             :     }
      54             :   }
      55          39 : }
      56             : 
      57             : 
      58         253 : void HStoreEliminationPhase::ProcessStore(HStoreNamedField* store) {
      59         506 :   HValue* object = store->object()->ActualValue();
      60             :   int i = 0;
      61         796 :   while (i < unobserved_.length()) {
      62         833 :     HStoreNamedField* prev = unobserved_.at(i);
      63         870 :     if (aliasing_->MustAlias(object, prev->object()->ActualValue()) &&
      64         290 :         prev->CanBeReplacedWith(store)) {
      65             :       // This store is guaranteed to overwrite the previous store.
      66           0 :       prev->DeleteAndReplaceWith(NULL);
      67           0 :       TRACE(("++ Unobserved store S%d overwritten by S%d\n",
      68           0 :              prev->id(), store->id()));
      69           0 :       unobserved_.Remove(i);
      70             :     } else {
      71         290 :       i++;
      72             :     }
      73             :   }
      74             :   // Only non-transitioning stores are removable.
      75         253 :   if (!store->has_transition()) {
      76         195 :     TRACE(("-- Might remove store S%d\n", store->id()));
      77         195 :     unobserved_.Add(store, zone());
      78             :   }
      79         253 : }
      80             : 
      81             : 
      82          27 : void HStoreEliminationPhase::ProcessLoad(HLoadNamedField* load) {
      83          27 :   HValue* object = load->object()->ActualValue();
      84             :   int i = 0;
      85          54 :   while (i < unobserved_.length()) {
      86          27 :     HStoreNamedField* prev = unobserved_.at(i);
      87           0 :     if (aliasing_->MayAlias(object, prev->object()->ActualValue()) &&
      88           0 :         load->access().Equals(prev->access())) {
      89           0 :       TRACE(("-- Observed store S%d by load L%d\n", prev->id(), load->id()));
      90           0 :       unobserved_.Remove(i);
      91             :     } else {
      92           0 :       i++;
      93             :     }
      94             :   }
      95          27 : }
      96             : 
      97             : 
      98        2524 : void HStoreEliminationPhase::ProcessInstr(HInstruction* instr,
      99             :     GVNFlagSet flags) {
     100        2524 :   if (unobserved_.length() == 0) return;  // Nothing to do.
     101         166 :   if (instr->CanDeoptimize()) {
     102          79 :     TRACE(("-- Observed stores at I%d (%s might deoptimize)\n",
     103           0 :            instr->id(), instr->Mnemonic()));
     104             :     unobserved_.Rewind(0);
     105             :     return;
     106             :   }
     107          87 :   if (instr->CheckChangesFlag(kNewSpacePromotion)) {
     108           0 :     TRACE(("-- Observed stores at I%d (%s might GC)\n",
     109           0 :            instr->id(), instr->Mnemonic()));
     110             :     unobserved_.Rewind(0);
     111             :     return;
     112             :   }
     113          87 :   if (instr->DependsOnFlags().ContainsAnyOf(flags)) {
     114           0 :     TRACE(("-- Observed stores at I%d (GVN flags of %s)\n",
     115           0 :            instr->id(), instr->Mnemonic()));
     116             :     unobserved_.Rewind(0);
     117             :     return;
     118             :   }
     119             : }
     120             : 
     121             : }  // namespace internal
     122             : }  // namespace v8

Generated by: LCOV version 1.10