tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ResourceQueue.cpp (6269B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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 
      7 #include "ResourceQueue.h"
      8 
      9 #include "MediaData.h"
     10 #include "mozilla/ErrorResult.h"
     11 #include "mozilla/IntegerPrintfMacros.h"
     12 #include "mozilla/Logging.h"
     13 #include "mozilla/Sprintf.h"
     14 
     15 extern mozilla::LogModule* GetSourceBufferResourceLog();
     16 
     17 #define SBR_DEBUG(arg, ...)                                       \
     18  MOZ_LOG(GetSourceBufferResourceLog(), mozilla::LogLevel::Debug, \
     19          ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
     20 #define SBR_DEBUGV(arg, ...)                                        \
     21  MOZ_LOG(GetSourceBufferResourceLog(), mozilla::LogLevel::Verbose, \
     22          ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
     23 
     24 namespace mozilla {
     25 
     26 ResourceItem::ResourceItem(const MediaSpan& aData, uint64_t aOffset)
     27    : mData(aData), mOffset(aOffset) {}
     28 
     29 size_t ResourceItem::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
     30  return aMallocSizeOf(this);
     31 }
     32 
     33 class ResourceQueueDeallocator : public nsDequeFunctor<ResourceItem> {
     34  void operator()(ResourceItem* aObject) override { delete aObject; }
     35 };
     36 
     37 ResourceQueue::ResourceQueue()
     38    : nsDeque<ResourceItem>(new ResourceQueueDeallocator()),
     39      mLogicalLength(0),
     40      mOffset(0) {}
     41 
     42 uint64_t ResourceQueue::GetOffset() { return mOffset; }
     43 
     44 uint64_t ResourceQueue::GetLength() { return mLogicalLength; }
     45 
     46 const uint8_t* ResourceQueue::GetContiguousAccess(int64_t aOffset,
     47                                                  size_t aSize) {
     48  uint32_t offset = 0;
     49  uint32_t start = GetAtOffset(aOffset, &offset);
     50  if (start >= GetSize()) {
     51    return nullptr;
     52  }
     53  ResourceItem* item = ResourceAt(start);
     54  if (offset + aSize > item->mData.Length()) {
     55    return nullptr;
     56  }
     57  return item->mData.Elements() + offset;
     58 }
     59 
     60 void ResourceQueue::CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) {
     61  uint32_t offset = 0;
     62  uint32_t start = GetAtOffset(aOffset, &offset);
     63  size_t i = start;
     64  while (i < uint32_t(GetSize()) && aCount > 0) {
     65    ResourceItem* item = ResourceAt(i++);
     66    uint32_t bytes = std::min(aCount, uint32_t(item->mData.Length() - offset));
     67    if (bytes != 0) {
     68      memcpy(aDest, item->mData.Elements() + offset, bytes);
     69      offset = 0;
     70      aCount -= bytes;
     71      aDest += bytes;
     72    }
     73  }
     74 }
     75 
     76 void ResourceQueue::AppendItem(const MediaSpan& aData) {
     77  uint64_t offset = mLogicalLength;
     78  mLogicalLength += aData.Length();
     79  Push(new ResourceItem(aData, offset));
     80 }
     81 
     82 uint32_t ResourceQueue::Evict(uint64_t aOffset, uint32_t aSizeToEvict) {
     83  SBR_DEBUG("Evict(aOffset=%" PRIu64 ", aSizeToEvict=%u)", aOffset,
     84            aSizeToEvict);
     85  return EvictBefore(std::min(aOffset, mOffset + (uint64_t)aSizeToEvict));
     86 }
     87 
     88 uint32_t ResourceQueue::EvictBefore(uint64_t aOffset) {
     89  SBR_DEBUG("EvictBefore(%" PRIu64 ")", aOffset);
     90  uint32_t evicted = 0;
     91  while (GetSize()) {
     92    ResourceItem* item = ResourceAt(0);
     93    SBR_DEBUG("item=%p length=%zu offset=%" PRIu64, item, item->mData.Length(),
     94              mOffset);
     95    if (item->mData.Length() + mOffset >= aOffset) {
     96      if (aOffset <= mOffset) {
     97        break;
     98      }
     99      uint32_t offset = aOffset - mOffset;
    100      mOffset += offset;
    101      evicted += offset;
    102      item->mData.RemoveFront(offset);
    103      item->mOffset += offset;
    104      break;
    105    }
    106    mOffset += item->mData.Length();
    107    evicted += item->mData.Length();
    108    delete PopFront();
    109  }
    110  return evicted;
    111 }
    112 
    113 uint32_t ResourceQueue::EvictAll() {
    114  SBR_DEBUG("EvictAll()");
    115  uint32_t evicted = 0;
    116  while (GetSize()) {
    117    ResourceItem* item = ResourceAt(0);
    118    SBR_DEBUG("item=%p length=%zu offset=%" PRIu64, item, item->mData.Length(),
    119              mOffset);
    120    mOffset += item->mData.Length();
    121    evicted += item->mData.Length();
    122    delete PopFront();
    123  }
    124  return evicted;
    125 }
    126 
    127 size_t ResourceQueue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
    128  // Calculate the size of the internal deque.
    129  size_t size = nsDeque<ResourceItem>::SizeOfExcludingThis(aMallocSizeOf);
    130 
    131  // Sum the ResourceItems. The ResourceItems's MediaSpans may share the
    132  // same underlying MediaByteBuffers, so we need to de-dupe the buffers
    133  // in order to report an accurate size.
    134  nsTArray<MediaByteBuffer*> buffers;
    135  for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
    136    const ResourceItem* item = ResourceAt(i);
    137    size += item->SizeOfIncludingThis(aMallocSizeOf);
    138    if (!buffers.Contains(item->mData.Buffer())) {
    139      buffers.AppendElement(item->mData.Buffer());
    140    }
    141  }
    142 
    143  for (MediaByteBuffer* buffer : buffers) {
    144    size += buffer->ShallowSizeOfExcludingThis(aMallocSizeOf);
    145  }
    146 
    147  return size;
    148 }
    149 
    150 #if defined(DEBUG)
    151 void ResourceQueue::Dump(const char* aPath) {
    152  for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
    153    ResourceItem* item = ResourceAt(i);
    154 
    155    char buf[255];
    156    SprintfLiteral(buf, "%s/%08u.bin", aPath, i);
    157    FILE* fp = fopen(buf, "wb");
    158    if (!fp) {
    159      return;
    160    }
    161    (void)fwrite(item->mData.Elements(), item->mData.Length(), 1, fp);
    162    fclose(fp);
    163  }
    164 }
    165 #endif
    166 
    167 ResourceItem* ResourceQueue::ResourceAt(uint32_t aIndex) const {
    168  return static_cast<ResourceItem*>(ObjectAt(aIndex));
    169 }
    170 
    171 uint32_t ResourceQueue::GetAtOffset(uint64_t aOffset,
    172                                    uint32_t* aResourceOffset) const {
    173  MOZ_RELEASE_ASSERT(aOffset >= mOffset);
    174 
    175  size_t hi = GetSize();
    176  size_t lo = 0;
    177  while (lo < hi) {
    178    size_t mid = lo + (hi - lo) / 2;
    179    const ResourceItem* resource = ResourceAt(mid);
    180    if (resource->mOffset <= aOffset &&
    181        aOffset < resource->mOffset + resource->mData.Length()) {
    182      if (aResourceOffset) {
    183        *aResourceOffset = aOffset - resource->mOffset;
    184      }
    185      return uint32_t(mid);
    186    }
    187    if (resource->mOffset + resource->mData.Length() <= aOffset) {
    188      lo = mid + 1;
    189    } else {
    190      hi = mid;
    191    }
    192  }
    193 
    194  return uint32_t(GetSize());
    195 }
    196 
    197 ResourceItem* ResourceQueue::PopFront() {
    198  return nsDeque<ResourceItem>::PopFront();
    199 }
    200 
    201 #undef SBR_DEBUG
    202 #undef SBR_DEBUGV
    203 
    204 }  // namespace mozilla