Coverage for /Syzygy/bard/events/play_util_impl.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
21.7%10460.C++source

Line-by-line coverage:

   1    :  // Copyright 2016 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  //
  15    :  // Implementation details for play_util.h
  16    :  
  17    :  #ifndef SYZYGY_BARD_EVENTS_PLAY_UTIL_IMPL_H_
  18    :  #define SYZYGY_BARD_EVENTS_PLAY_UTIL_IMPL_H_
  19    :  
  20    :  #include <cinttypes>
  21    :  #include <utility>
  22    :  
  23    :  #include "base/logging.h"
  24    :  #include "syzygy/trace/common/clock.h"
  25    :  
  26    :  namespace bard {
  27    :  namespace detail {
  28    :  
  29    :  // This warnings relates to optimizations and manually injected assembly code.
  30    :  #pragma warning(disable: 4740)
  31    :  
  32    :  // Turn off all optimizations. These functions need to be distinct so they
  33    :  // each generate a unique stack frame.
  34    :  #pragma optimize("", off)
  35    :  
  36    :  // Helper for extracting the return type of a function.
  37    :  // @tparam FunctionType The type of the function to be called.
  38    :  // @tparam ParamTypes The types of the function parameters.
  39    :  template<typename FunctionType, typename ...ParamTypes>
  40    :  struct GetReturnType {
  41    :    using type =
  42    :        decltype(std::declval<FunctionType>()(std::declval<ParamTypes>()...));
  43    :  };
  44    :  
  45    :  // A testing seam that allows having the InvokeFunctionWithStackIdHelper
  46    :  // report its function extents.
  47    :  enum : uint32_t { kGetFunctionExtentsDepth = 0xFFFFFFFF };
  48    :  extern const void* kInvokeFunctionBegin;
  49    :  extern const void* kInvokeFunctionEnd;
  50    :  
  51    :  // Workhorse for InvokeFunctionWithStackId.
  52    :  template<uint32_t kInvokeValue,
  53    :           typename FunctionType,
  54    :           typename ReturnType,
  55    :           typename ...ParamTypes>
  56    :  struct InvokeFunctionWithStackIdHelper {
  57    :    template<uint32_t kChildInvokerValue>
  58    :    using Invoke = InvokeFunctionWithStackIdHelper<kChildInvokerValue,
  59    :        FunctionType, ReturnType, ParamTypes...>;
  60    :  
  61    :    static __declspec(noinline) ReturnType Do(uint32_t depth, uint32_t stack_id,
  62  i :        FunctionType& function, ParamTypes... params) {
  63    :      function_start:
  64    :  
  65    :      // Special case for testing. This gets the extents of this function as
  66    :      // actually laid out in memory.
  67  i :      if (depth == kGetFunctionExtentsDepth) {
  68    :        __asm {
  69  i :          push eax
  70  i :          mov eax, function_start
  71  i :          mov kInvokeFunctionBegin, eax
  72  i :          mov eax, function_end
  73  i :          mov kInvokeFunctionEnd, eax
  74  i :          pop eax
  75    :        }
  76  i :        return function(params...);
  77    :      }
  78    :  
  79    :      // Outside of testing the depth should never be more than 8, as there are
  80    :      // only 8 nibbles in a 32-bit int.
  81  i :      DCHECK_GE(8u, depth);
  82    :  
  83    :      // Handle the base case.
  84  i :      if (depth == 0) {
  85  i :        DCHECK_EQ(0u, stack_id);
  86  i :        return function(params...);
  87    :      }
  88    :  
  89    :      // Get the lowest nibble, shift it out, and decrement the depth.
  90  i :      uint32_t invoke_id = stack_id & 0xF;
  91  i :      stack_id >>= 4;
  92  i :      --depth;
  93    :  
  94    :      // Dispatch to the appropriate child invoker, based on the bottom nibble
  95    :      // of the stack ID.
  96  i :      switch (invoke_id) {
  97  i :        case 0x0: return Invoke<0x0>().Do(depth, stack_id, function, params...);
  98  i :        case 0x1: return Invoke<0x1>().Do(depth, stack_id, function, params...);
  99  i :        case 0x2: return Invoke<0x2>().Do(depth, stack_id, function, params...);
 100  i :        case 0x3: return Invoke<0x3>().Do(depth, stack_id, function, params...);
 101  i :        case 0x4: return Invoke<0x4>().Do(depth, stack_id, function, params...);
 102  i :        case 0x5: return Invoke<0x5>().Do(depth, stack_id, function, params...);
 103  i :        case 0x6: return Invoke<0x6>().Do(depth, stack_id, function, params...);
 104  i :        case 0x7: return Invoke<0x7>().Do(depth, stack_id, function, params...);
 105  i :        case 0x8: return Invoke<0x8>().Do(depth, stack_id, function, params...);
 106  i :        case 0x9: return Invoke<0x9>().Do(depth, stack_id, function, params...);
 107  i :        case 0xA: return Invoke<0xA>().Do(depth, stack_id, function, params...);
 108  i :        case 0xB: return Invoke<0xB>().Do(depth, stack_id, function, params...);
 109  i :        case 0xC: return Invoke<0xC>().Do(depth, stack_id, function, params...);
 110  i :        case 0xD: return Invoke<0xD>().Do(depth, stack_id, function, params...);
 111  i :        case 0xE: return Invoke<0xE>().Do(depth, stack_id, function, params...);
 112  i :        case 0xF: return Invoke<0xF>().Do(depth, stack_id, function, params...);
 113    :        default: break;
 114    :      }
 115    :  
 116    :      function_end:
 117  i :      NOTREACHED();
 118  i :      return function(params...);
 119  i :    }
 120    :  };
 121    :  
 122    :  // Implementation of InvokeOnBackdrop.
 123    :  template<typename BackdropType, typename ReturnType, typename ...ParamTypes>
 124    :  struct InvokeOnBackdropHelper {
 125    :    static ReturnType DoImpl(uint64_t* timing,
 126    :                             BackdropType* backdrop,
 127    :                             ReturnType (BackdropType::*function)(ParamTypes...),
 128  E :                             ParamTypes... params) {
 129  E :      uint64_t t0 = ::trace::common::GetTsc();
 130  E :      ReturnType ret = (backdrop->*function)(params...);
 131  E :      uint64_t t1 = ::trace::common::GetTsc();
 132  E :      *timing = t1 - t0;
 133  E :      return ret;
 134  E :    }
 135    :  
 136    :    static ReturnType Do(uint32_t stack_id,
 137    :                         uint64_t* timing,
 138    :                         BackdropType* backdrop,
 139    :                         ReturnType (BackdropType::*function)(ParamTypes...),
 140  E :                         ParamTypes... params) {
 141  E :      return InvokeFunctionWithStackId(
 142    :          stack_id, DoImpl, timing, backdrop, function, params...);
 143  E :    }
 144    :  };
 145    :  
 146    :  #pragma optimize("", on)
 147    :  
 148    :  }  // namespace detail
 149    :  }  // namespace bard
 150    :  
 151    :  #endif  // SYZYGY_BARD_EVENTS_PLAY_UTIL_IMPL_H_

Coverage information generated Fri Jul 29 11:00:21 2016.