Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/allocation.h"
6 :
7 : #include <stdlib.h> // For free, malloc.
8 : #include "src/base/bits.h"
9 : #include "src/base/logging.h"
10 : #include "src/base/platform/platform.h"
11 : #include "src/utils.h"
12 : #include "src/v8.h"
13 :
14 : #if V8_LIBC_BIONIC
15 : #include <malloc.h> // NOLINT
16 : #endif
17 :
18 : #if defined(LEAK_SANITIZER)
19 : #include <sanitizer/lsan_interface.h>
20 : #endif
21 :
22 : namespace v8 {
23 : namespace internal {
24 :
25 : namespace {
26 :
27 : void* AlignedAllocInternal(size_t size, size_t alignment) {
28 : void* ptr;
29 : #if V8_OS_WIN
30 : ptr = _aligned_malloc(size, alignment);
31 : #elif V8_LIBC_BIONIC
32 : // posix_memalign is not exposed in some Android versions, so we fall back to
33 : // memalign. See http://code.google.com/p/android/issues/detail?id=35391.
34 : ptr = memalign(alignment, size);
35 : #else
36 287 : if (posix_memalign(&ptr, alignment, size)) ptr = nullptr;
37 : #endif
38 287 : return ptr;
39 : }
40 :
41 : } // namespace
42 :
43 1310828 : void* Malloced::New(size_t size) {
44 1310828 : void* result = malloc(size);
45 1310828 : if (result == nullptr) {
46 6 : V8::GetCurrentPlatform()->OnCriticalMemoryPressure();
47 6 : result = malloc(size);
48 6 : if (result == nullptr) {
49 6 : V8::FatalProcessOutOfMemory("Malloced operator new");
50 : }
51 : }
52 1310822 : return result;
53 : }
54 :
55 :
56 1355043 : void Malloced::Delete(void* p) {
57 1355043 : free(p);
58 1355043 : }
59 :
60 :
61 101953864 : char* StrDup(const char* str) {
62 : int length = StrLength(str);
63 101953864 : char* result = NewArray<char>(length + 1);
64 101953864 : MemCopy(result, str, length);
65 101953864 : result[length] = '\0';
66 101953864 : return result;
67 : }
68 :
69 :
70 0 : char* StrNDup(const char* str, int n) {
71 : int length = StrLength(str);
72 0 : if (n < length) length = n;
73 0 : char* result = NewArray<char>(length + 1);
74 0 : MemCopy(result, str, length);
75 0 : result[length] = '\0';
76 0 : return result;
77 : }
78 :
79 :
80 281 : void* AlignedAlloc(size_t size, size_t alignment) {
81 : DCHECK_LE(V8_ALIGNOF(void*), alignment);
82 : DCHECK(base::bits::IsPowerOfTwo(alignment));
83 : void* ptr = AlignedAllocInternal(size, alignment);
84 281 : if (ptr == nullptr) {
85 6 : V8::GetCurrentPlatform()->OnCriticalMemoryPressure();
86 : ptr = AlignedAllocInternal(size, alignment);
87 6 : if (ptr == nullptr) {
88 6 : V8::FatalProcessOutOfMemory("AlignedAlloc");
89 : }
90 : }
91 275 : return ptr;
92 : }
93 :
94 :
95 275 : void AlignedFree(void *ptr) {
96 : #if V8_OS_WIN
97 : _aligned_free(ptr);
98 : #elif V8_LIBC_BIONIC
99 : // Using free is not correct in general, but for V8_LIBC_BIONIC it is.
100 : free(ptr);
101 : #else
102 275 : free(ptr);
103 : #endif
104 275 : }
105 :
106 2546062 : VirtualMemory::VirtualMemory() : address_(nullptr), size_(0) {}
107 :
108 0 : VirtualMemory::VirtualMemory(size_t size, void* hint)
109 55011 : : address_(base::OS::ReserveRegion(size, hint)), size_(size) {
110 : #if defined(LEAK_SANITIZER)
111 : __lsan_register_root_region(address_, size_);
112 : #endif
113 0 : }
114 :
115 0 : VirtualMemory::VirtualMemory(size_t size, size_t alignment, void* hint)
116 494811 : : address_(nullptr), size_(0) {
117 494811 : address_ = base::OS::ReserveAlignedRegion(size, alignment, hint, &size_);
118 : #if defined(LEAK_SANITIZER)
119 : __lsan_register_root_region(address_, size_);
120 : #endif
121 0 : }
122 :
123 3129992 : VirtualMemory::~VirtualMemory() {
124 3184997 : if (IsReserved()) {
125 0 : bool result = base::OS::ReleaseRegion(address(), size());
126 : DCHECK(result);
127 : USE(result);
128 : }
129 2635183 : }
130 :
131 762713 : void VirtualMemory::Reset() {
132 3377062 : address_ = nullptr;
133 3377062 : size_ = 0;
134 762713 : }
135 :
136 1111033 : bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
137 1111033 : CHECK(InVM(address, size));
138 1111033 : return base::OS::CommitRegion(address, size, is_executable);
139 : }
140 :
141 300713 : bool VirtualMemory::Uncommit(void* address, size_t size) {
142 300713 : CHECK(InVM(address, size));
143 300713 : return base::OS::UncommitRegion(address, size);
144 : }
145 :
146 619866 : bool VirtualMemory::Guard(void* address) {
147 1239732 : CHECK(InVM(address, base::OS::CommitPageSize()));
148 619866 : base::OS::Guard(address, base::OS::CommitPageSize());
149 619866 : return true;
150 : }
151 :
152 109926 : size_t VirtualMemory::ReleasePartial(void* free_start) {
153 : DCHECK(IsReserved());
154 : // Notice: Order is important here. The VirtualMemory object might live
155 : // inside the allocated region.
156 109926 : const size_t free_size = size_ - (reinterpret_cast<size_t>(free_start) -
157 109926 : reinterpret_cast<size_t>(address_));
158 109926 : CHECK(InVM(free_start, free_size));
159 : DCHECK_LT(address_, free_start);
160 : DCHECK_LT(free_start, reinterpret_cast<void*>(
161 : reinterpret_cast<size_t>(address_) + size_));
162 : #if defined(LEAK_SANITIZER)
163 : __lsan_unregister_root_region(address_, size_);
164 : __lsan_register_root_region(address_, size_ - free_size);
165 : #endif
166 109926 : const bool result = base::OS::ReleasePartialRegion(free_start, free_size);
167 : USE(result);
168 : DCHECK(result);
169 109926 : size_ -= free_size;
170 109926 : return free_size;
171 : }
172 :
173 370257 : void VirtualMemory::Release() {
174 : DCHECK(IsReserved());
175 : // Notice: Order is important here. The VirtualMemory object might live
176 : // inside the allocated region.
177 370257 : void* address = address_;
178 370257 : size_t size = size_;
179 370257 : CHECK(InVM(address, size));
180 : Reset();
181 370257 : bool result = base::OS::ReleaseRegion(address, size);
182 : USE(result);
183 : DCHECK(result);
184 370267 : }
185 :
186 1749283 : void VirtualMemory::TakeControl(VirtualMemory* from) {
187 : DCHECK(!IsReserved());
188 2299097 : address_ = from->address_;
189 2299097 : size_ = from->size_;
190 : from->Reset();
191 1749283 : }
192 :
193 55005 : bool AllocVirtualMemory(size_t size, void* hint, VirtualMemory* result) {
194 : VirtualMemory first_try(size, hint);
195 55005 : if (first_try.IsReserved()) {
196 : result->TakeControl(&first_try);
197 54999 : return true;
198 : }
199 :
200 6 : V8::GetCurrentPlatform()->OnCriticalMemoryPressure();
201 : VirtualMemory second_try(size, hint);
202 : result->TakeControl(&second_try);
203 : return result->IsReserved();
204 : }
205 :
206 494805 : bool AlignedAllocVirtualMemory(size_t size, size_t alignment, void* hint,
207 : VirtualMemory* result) {
208 : VirtualMemory first_try(size, alignment, hint);
209 494809 : if (first_try.IsReserved()) {
210 : result->TakeControl(&first_try);
211 494803 : return true;
212 : }
213 :
214 6 : V8::GetCurrentPlatform()->OnCriticalMemoryPressure();
215 : VirtualMemory second_try(size, alignment, hint);
216 : result->TakeControl(&second_try);
217 : return result->IsReserved();
218 : }
219 :
220 : } // namespace internal
221 : } // namespace v8
|