DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (1aeaa33a64f9)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "ResourceQueue.h"
#include "nsDeque.h"
#include "MediaData.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Logging.h"
#include "mozilla/Sprintf.h"
#include "mozilla/Unused.h"

extern mozilla::LogModule* GetSourceBufferResourceLog();

#define SBR_DEBUG(arg, ...)                                       \
  MOZ_LOG(GetSourceBufferResourceLog(), mozilla::LogLevel::Debug, \
          ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
#define SBR_DEBUGV(arg, ...)                                        \
  MOZ_LOG(GetSourceBufferResourceLog(), mozilla::LogLevel::Verbose, \
          ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))

namespace mozilla {

ResourceItem::ResourceItem(MediaByteBuffer* aData) : mData(aData) {}

size_t ResourceItem::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
  // size including this
  size_t size = aMallocSizeOf(this);

  // size excluding this
  size += mData->ShallowSizeOfExcludingThis(aMallocSizeOf);

  return size;
}

class ResourceQueueDeallocator : public nsDequeFunctor {
  void operator()(void* aObject) override {
    delete static_cast<ResourceItem*>(aObject);
  }
};

ResourceQueue::ResourceQueue()
    : nsDeque(new ResourceQueueDeallocator()), mLogicalLength(0), mOffset(0) {}

uint64_t ResourceQueue::GetOffset() { return mOffset; }

uint64_t ResourceQueue::GetLength() { return mLogicalLength; }

void ResourceQueue::CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) {
  uint32_t offset = 0;
  uint32_t start = GetAtOffset(aOffset, &offset);
  uint32_t end =
      std::min(GetAtOffset(aOffset + aCount, nullptr) + 1, uint32_t(GetSize()));
  for (uint32_t i = start; i < end; ++i) {
    ResourceItem* item = ResourceAt(i);
    uint32_t bytes = std::min(aCount, uint32_t(item->mData->Length() - offset));
    if (bytes != 0) {
      memcpy(aDest, &(*item->mData)[offset], bytes);
      offset = 0;
      aCount -= bytes;
      aDest += bytes;
    }
  }
}

void ResourceQueue::AppendItem(MediaByteBuffer* aData) {
  mLogicalLength += aData->Length();
  Push(new ResourceItem(aData));
}

uint32_t ResourceQueue::Evict(uint64_t aOffset, uint32_t aSizeToEvict,
                              ErrorResult& aRv) {
  SBR_DEBUG("Evict(aOffset=%" PRIu64 ", aSizeToEvict=%u)", aOffset,
            aSizeToEvict);
  return EvictBefore(std::min(aOffset, mOffset + (uint64_t)aSizeToEvict), aRv);
}

uint32_t ResourceQueue::EvictBefore(uint64_t aOffset, ErrorResult& aRv) {
  SBR_DEBUG("EvictBefore(%" PRIu64 ")", aOffset);
  uint32_t evicted = 0;
  while (ResourceItem* item = ResourceAt(0)) {
    SBR_DEBUG("item=%p length=%zu offset=%" PRIu64, item, item->mData->Length(),
              mOffset);
    if (item->mData->Length() + mOffset >= aOffset) {
      if (aOffset <= mOffset) {
        break;
      }
      uint32_t offset = aOffset - mOffset;
      mOffset += offset;
      evicted += offset;
      RefPtr<MediaByteBuffer> data = new MediaByteBuffer;
      if (!data->AppendElements(item->mData->Elements() + offset,
                                item->mData->Length() - offset, fallible)) {
        aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
        return 0;
      }

      item->mData = data;
      break;
    }
    mOffset += item->mData->Length();
    evicted += item->mData->Length();
    delete PopFront();
  }
  return evicted;
}

uint32_t ResourceQueue::EvictAll() {
  SBR_DEBUG("EvictAll()");
  uint32_t evicted = 0;
  while (ResourceItem* item = ResourceAt(0)) {
    SBR_DEBUG("item=%p length=%zu offset=%" PRIu64, item, item->mData->Length(),
              mOffset);
    mOffset += item->mData->Length();
    evicted += item->mData->Length();
    delete PopFront();
  }
  return evicted;
}

size_t ResourceQueue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
  // Calculate the size of the internal deque.
  size_t size = nsDeque::SizeOfExcludingThis(aMallocSizeOf);

  // Sum the ResourceItems.
  for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
    const ResourceItem* item = ResourceAt(i);
    size += item->SizeOfIncludingThis(aMallocSizeOf);
  }

  return size;
}

#if defined(DEBUG)
void ResourceQueue::Dump(const char* aPath) {
  for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
    ResourceItem* item = ResourceAt(i);

    char buf[255];
    SprintfLiteral(buf, "%s/%08u.bin", aPath, i);
    FILE* fp = fopen(buf, "wb");
    if (!fp) {
      return;
    }
    Unused << fwrite(item->mData->Elements(), item->mData->Length(), 1, fp);
    fclose(fp);
  }
}
#endif

ResourceItem* ResourceQueue::ResourceAt(uint32_t aIndex) const {
  return static_cast<ResourceItem*>(ObjectAt(aIndex));
}

uint32_t ResourceQueue::GetAtOffset(uint64_t aOffset,
                                    uint32_t* aResourceOffset) {
  MOZ_RELEASE_ASSERT(aOffset >= mOffset);
  uint64_t offset = mOffset;
  for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
    ResourceItem* item = ResourceAt(i);
    // If the item contains the start of the offset we want to
    // break out of the loop.
    if (item->mData->Length() + offset > aOffset) {
      if (aResourceOffset) {
        *aResourceOffset = aOffset - offset;
      }
      return i;
    }
    offset += item->mData->Length();
  }
  return GetSize();
}

ResourceItem* ResourceQueue::PopFront() {
  return static_cast<ResourceItem*>(nsDeque::PopFront());
}

#undef SBR_DEBUG
#undef SBR_DEBUGV

}  // namespace mozilla