File: BaseAlloc.cpp

package info (click to toggle)
firefox 147.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 4,683,324 kB
  • sloc: cpp: 7,607,156; javascript: 6,532,492; ansic: 3,775,158; python: 1,415,368; xml: 634,556; asm: 438,949; java: 186,241; sh: 62,751; makefile: 18,079; objc: 13,092; perl: 12,808; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (77 lines) | stat: -rw-r--r-- 2,251 bytes parent folder | download | duplicates (2)
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
/* 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 https://mozilla.org/MPL/2.0/. */

#include "BaseAlloc.h"

#include <cstring>

#include "Globals.h"

using namespace mozilla;

MOZ_CONSTINIT BaseAlloc sBaseAlloc;

// Initialize base allocation data structures.
void BaseAlloc::Init() MOZ_REQUIRES(gInitLock) { mMutex.Init(); }

bool BaseAlloc::pages_alloc(size_t minsize) MOZ_REQUIRES(mMutex) {
  MOZ_ASSERT(minsize != 0);
  size_t csize = CHUNK_CEILING(minsize);
  uintptr_t base_pages =
      reinterpret_cast<uintptr_t>(chunk_alloc(csize, kChunkSize, true));
  if (base_pages == 0) {
    return false;
  }
  mNextAddr = reinterpret_cast<uintptr_t>(base_pages);
  mPastAddr = base_pages + csize;
  // Leave enough pages for minsize committed, since otherwise they would
  // have to be immediately recommitted.
  size_t pminsize = REAL_PAGE_CEILING(minsize);
  mNextDecommitted = base_pages + pminsize;
  if (pminsize < csize) {
    pages_decommit(reinterpret_cast<void*>(mNextDecommitted), csize - pminsize);
  }
  mStats.mMapped += csize;
  mStats.mCommitted += pminsize;

  return true;
}

void* BaseAlloc::alloc(size_t aSize) {
  // Round size up to nearest multiple of the cacheline size.
  size_t csize = CACHELINE_CEILING(aSize);

  MutexAutoLock lock(mMutex);
  // Make sure there's enough space for the allocation.
  if (mNextAddr + csize > mPastAddr) {
    if (!pages_alloc(csize)) {
      return nullptr;
    }
  }
  // Allocate.
  void* ret = reinterpret_cast<void*>(mNextAddr);
  mNextAddr = mNextAddr + csize;
  // Make sure enough pages are committed for the new allocation.
  if (mNextAddr > mNextDecommitted) {
    uintptr_t pbase_next_addr = REAL_PAGE_CEILING(mNextAddr);

    if (!pages_commit(reinterpret_cast<void*>(mNextDecommitted),
                      mNextAddr - mNextDecommitted)) {
      return nullptr;
    }

    mStats.mCommitted += pbase_next_addr - mNextDecommitted;
    mNextDecommitted = pbase_next_addr;
  }

  return ret;
}

void* BaseAlloc::calloc(size_t aNumber, size_t aSize) {
  void* ret = alloc(aNumber * aSize);
  if (ret) {
    memset(ret, 0, aNumber * aSize);
  }
  return ret;
}