LCOV - code coverage report
Current view: top level - js/src/jit - WasmBCE.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 36 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 1 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : #include "jit/WasmBCE.h"
       7             : #include "jit/MIRGenerator.h"
       8             : #include "jit/MIRGraph.h"
       9             : #include "wasm/WasmTypes.h"
      10             : 
      11             : using namespace js;
      12             : using namespace js::jit;
      13             : using namespace mozilla;
      14             : 
      15             : typedef js::HashMap<uint32_t, MDefinition*, DefaultHasher<uint32_t>, SystemAllocPolicy>
      16             :     LastSeenMap;
      17             : 
      18             : // The Wasm Bounds Check Elimination (BCE) pass looks for bounds checks
      19             : // on SSA values that have already been checked. (in the same block or in a
      20             : // dominating block). These bounds checks are redundant and thus eliminated.
      21             : //
      22             : // Note: This is safe in the presense of dynamic memory sizes as long as they
      23             : // can ONLY GROW. If we allow SHRINKING the heap, this pass should be
      24             : // RECONSIDERED.
      25             : //
      26             : // TODO (dbounov): Are there a lot of cases where there is no single dominating
      27             : // check, but a set of checks that together dominate a redundant check?
      28             : //
      29             : // TODO (dbounov): Generalize to constant additions relative to one base
      30             : bool
      31           0 : jit::EliminateBoundsChecks(MIRGenerator* mir, MIRGraph& graph)
      32             : {
      33             :     // Map for dominating block where a given definition was checked
      34           0 :     LastSeenMap lastSeen;
      35           0 :     if (!lastSeen.init())
      36           0 :         return false;
      37             : 
      38           0 :     for (ReversePostorderIterator bIter(graph.rpoBegin()); bIter != graph.rpoEnd(); bIter++) {
      39           0 :         MBasicBlock* block = *bIter;
      40           0 :         for (MDefinitionIterator dIter(block); dIter;) {
      41           0 :             MDefinition* def = *dIter++;
      42             : 
      43           0 :             switch (def->op()) {
      44             :               case MDefinition::Op_WasmBoundsCheck: {
      45           0 :                 MWasmBoundsCheck* bc = def->toWasmBoundsCheck();
      46           0 :                 MDefinition* addr = bc->index();
      47             : 
      48             :                 // Eliminate constant-address bounds checks to addresses below
      49             :                 // the heap minimum.
      50             :                 //
      51             :                 // The payload of the MConstant will be Double if the constant
      52             :                 // result is above 2^31-1, but we don't care about that for BCE.
      53             : 
      54             : #ifndef WASM_HUGE_MEMORY
      55             :                 MOZ_ASSERT(wasm::MaxMemoryAccessSize < wasm::GuardSize,
      56             :                            "Guard page handles partial out-of-bounds");
      57             : #endif
      58             : 
      59           0 :                 if (addr->isConstant() && addr->toConstant()->type() == MIRType::Int32 &&
      60           0 :                     uint32_t(addr->toConstant()->toInt32()) < mir->minWasmHeapLength())
      61             :                 {
      62           0 :                     bc->setRedundant();
      63             :                 }
      64             :                 else
      65             :                 {
      66           0 :                     LastSeenMap::AddPtr ptr = lastSeen.lookupForAdd(addr->id());
      67           0 :                     if (ptr) {
      68           0 :                         if (ptr->value()->block()->dominates(block))
      69           0 :                             bc->setRedundant();
      70             :                     } else {
      71           0 :                         if (!lastSeen.add(ptr, addr->id(), def))
      72           0 :                             return false;
      73             :                     }
      74             :                 }
      75           0 :                 break;
      76             :               }
      77             :               case MDefinition::Op_Phi: {
      78           0 :                 MPhi* phi = def->toPhi();
      79           0 :                 bool phiChecked = true;
      80             : 
      81           0 :                 MOZ_ASSERT(phi->numOperands() > 0);
      82             : 
      83             :                 // If all incoming values to a phi node are safe (i.e. have a
      84             :                 // check that dominates this block) then we can consider this
      85             :                 // phi node checked.
      86             :                 //
      87             :                 // Note that any phi that is part of a cycle
      88             :                 // will not be "safe" since the value coming on the backedge
      89             :                 // cannot be in lastSeen because its block hasn't been traversed yet.
      90           0 :                 for (int i = 0, nOps = phi->numOperands(); i < nOps; i++) {
      91           0 :                     MDefinition* src = phi->getOperand(i);
      92             : 
      93           0 :                     LastSeenMap::Ptr checkPtr = lastSeen.lookup(src->id());
      94           0 :                     if (!checkPtr || !checkPtr->value()->block()->dominates(block)) {
      95           0 :                         phiChecked = false;
      96           0 :                         break;
      97             :                     }
      98             :                 }
      99             : 
     100           0 :                 if (phiChecked) {
     101           0 :                     if (!lastSeen.put(def->id(), def))
     102           0 :                         return false;
     103             :                 }
     104             : 
     105           0 :                 break;
     106             :               }
     107             :               default:
     108           0 :                 break;
     109             :             }
     110             :         }
     111             :     }
     112             : 
     113           0 :     return true;
     114             : }

Generated by: LCOV version 1.13