2012-01-25 16:31:25 +00:00
|
|
|
// Copyright 2012 the V8 project authors. All rights reserved.
|
2014-04-29 06:42:26 +00:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
#ifndef V8_ALLOCATION_H_
|
|
|
|
#define V8_ALLOCATION_H_
|
|
|
|
|
2017-08-01 01:41:13 +00:00
|
|
|
#include "include/v8-platform.h"
|
2016-10-17 10:01:42 +00:00
|
|
|
#include "src/base/compiler-specific.h"
|
2017-08-01 01:41:13 +00:00
|
|
|
#include "src/base/platform/platform.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/globals.h"
|
2017-08-01 01:41:13 +00:00
|
|
|
#include "src/v8.h"
|
2010-12-15 08:07:27 +00:00
|
|
|
|
2009-05-25 10:05:56 +00:00
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2017-08-01 01:41:13 +00:00
|
|
|
// This file defines memory allocation functions. If a first attempt at an
|
|
|
|
// allocation fails, these functions call back into the embedder, then attempt
|
|
|
|
// the allocation a second time. The embedder callback must not reenter V8.
|
|
|
|
|
|
|
|
// Called when allocation routines fail to allocate, even with a possible retry.
|
|
|
|
// This function should not return, but should terminate the current processing.
|
2016-09-20 12:06:34 +00:00
|
|
|
V8_EXPORT_PRIVATE void FatalProcessOutOfMemory(const char* message);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Superclass for classes managed with new & delete.
|
2016-09-20 12:06:34 +00:00
|
|
|
class V8_EXPORT_PRIVATE Malloced {
|
2008-07-03 15:10:15 +00:00
|
|
|
public:
|
|
|
|
void* operator new(size_t size) { return New(size); }
|
|
|
|
void operator delete(void* p) { Delete(p); }
|
|
|
|
|
|
|
|
static void* New(size_t size);
|
|
|
|
static void Delete(void* p);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
2012-03-11 15:04:50 +00:00
|
|
|
T* NewArray(size_t size) {
|
2017-08-04 20:28:52 +00:00
|
|
|
T* result = new (std::nothrow) T[size];
|
|
|
|
if (result == nullptr) {
|
2017-08-01 01:41:13 +00:00
|
|
|
V8::GetCurrentPlatform()->OnCriticalMemoryPressure();
|
2017-08-04 20:28:52 +00:00
|
|
|
result = new (std::nothrow) T[size];
|
|
|
|
if (result == nullptr) FatalProcessOutOfMemory("NewArray");
|
2017-08-01 01:41:13 +00:00
|
|
|
}
|
2017-08-04 20:28:52 +00:00
|
|
|
return result;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
[assembler] Make Register et al. real classes
Up to now, each architecture defined all Register types as structs,
with lots of redundancy. An often found comment noted that they cannot
be classes due to initialization order problems. As these problems are
gone with C++11 constexpr constants, I now tried making Registers
classes again.
All register types now inherit from RegisterBase, which provides a
default set of methods and named constructors (like ::from_code,
code(), bit(), is_valid(), ...).
This design allows to guarantee an interesting property: Each register
is either valid, or it's the no_reg register. There are no other
invalid registers. This is guaranteed statically by the constexpr
constructor, and dynamically by ::from_code.
I decided to disallow the default constructor completely, so instead of
"Register reg;" you now need "Register reg = no_reg;". This makes
explicit how the Register is initialized.
I did this change to the x64, ia32, arm, arm64, mips and mips64 ports.
Overall, code got much more compact and more safe. In theory, it should
also increase performance (since the is_valid() check is simpler), but
this is probably not measurable.
R=mstarzinger@chromium.org
Change-Id: I5ccfa4050daf4e146a557970e9d37fd3d2788d4a
Reviewed-on: https://chromium-review.googlesource.com/650927
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47847}
2017-09-06 08:05:07 +00:00
|
|
|
template <typename T,
|
|
|
|
typename = typename std::enable_if<IS_TRIVIALLY_COPYABLE(T)>::type>
|
|
|
|
T* NewArray(size_t size, T default_val) {
|
|
|
|
T* result = reinterpret_cast<T*>(NewArray<uint8_t>(sizeof(T) * size));
|
|
|
|
for (size_t i = 0; i < size; ++i) result[i] = default_val;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
template <typename T>
|
2011-11-29 10:56:11 +00:00
|
|
|
void DeleteArray(T* array) {
|
2008-07-03 15:10:15 +00:00
|
|
|
delete[] array;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-18 12:27:37 +00:00
|
|
|
// The normal strdup functions use malloc. These versions of StrDup
|
|
|
|
// and StrNDup uses new and calls the FatalProcessOutOfMemory handler
|
|
|
|
// if allocation fails.
|
2016-09-20 12:06:34 +00:00
|
|
|
V8_EXPORT_PRIVATE char* StrDup(const char* str);
|
2009-11-20 13:08:44 +00:00
|
|
|
char* StrNDup(const char* str, int n);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Allocation policy for allocating in the C free store using malloc
|
|
|
|
// and free. Used as the default policy for lists.
|
|
|
|
class FreeStoreAllocationPolicy {
|
|
|
|
public:
|
2012-06-04 14:42:58 +00:00
|
|
|
INLINE(void* New(size_t size)) { return Malloced::New(size); }
|
2008-07-03 15:10:15 +00:00
|
|
|
INLINE(static void Delete(void* p)) { Malloced::Delete(p); }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-01-10 10:39:47 +00:00
|
|
|
void* AlignedAlloc(size_t size, size_t alignment);
|
|
|
|
void AlignedFree(void *ptr);
|
|
|
|
|
2017-11-14 15:55:09 +00:00
|
|
|
// Allocates a single system memory page with read/write permissions. The
|
|
|
|
// address parameter is a hint. Returns the base address of the memory, or null
|
|
|
|
// on failure. Permissions can be changed on the base address.
|
|
|
|
byte* AllocateSystemPage(void* address, size_t* allocated);
|
|
|
|
|
2017-09-20 15:36:15 +00:00
|
|
|
// Represents and controls an area of reserved memory.
|
|
|
|
class V8_EXPORT_PRIVATE VirtualMemory {
|
|
|
|
public:
|
|
|
|
// Empty VirtualMemory object, controlling no reserved memory.
|
|
|
|
VirtualMemory();
|
|
|
|
|
2017-11-14 15:55:09 +00:00
|
|
|
// Reserves virtual memory containing an area of the given size that is
|
|
|
|
// aligned per alignment. This may not be at the position returned by
|
|
|
|
// address().
|
|
|
|
VirtualMemory(size_t size, void* hint,
|
|
|
|
size_t alignment = base::OS::AllocatePageSize());
|
2017-09-20 15:36:15 +00:00
|
|
|
|
|
|
|
// Construct a virtual memory by assigning it some already mapped address
|
|
|
|
// and size.
|
|
|
|
VirtualMemory(void* address, size_t size) : address_(address), size_(size) {}
|
|
|
|
|
|
|
|
// Releases the reserved memory, if any, controlled by this VirtualMemory
|
|
|
|
// object.
|
|
|
|
~VirtualMemory();
|
|
|
|
|
|
|
|
// Returns whether the memory has been reserved.
|
|
|
|
bool IsReserved() const { return address_ != nullptr; }
|
|
|
|
|
|
|
|
// Initialize or resets an embedded VirtualMemory object.
|
|
|
|
void Reset();
|
|
|
|
|
|
|
|
// Returns the start address of the reserved memory.
|
|
|
|
// If the memory was reserved with an alignment, this address is not
|
|
|
|
// necessarily aligned. The user might need to round it up to a multiple of
|
|
|
|
// the alignment to get the start of the aligned block.
|
|
|
|
void* address() const {
|
|
|
|
DCHECK(IsReserved());
|
|
|
|
return address_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* end() const {
|
|
|
|
DCHECK(IsReserved());
|
|
|
|
return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(address_) +
|
|
|
|
size_);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the size of the reserved memory. The returned value is only
|
|
|
|
// meaningful when IsReserved() returns true.
|
|
|
|
// If the memory was reserved with an alignment, this size may be larger
|
|
|
|
// than the requested size.
|
|
|
|
size_t size() const { return size_; }
|
|
|
|
|
|
|
|
// Commits real memory. Returns whether the operation succeeded.
|
2017-11-16 12:02:12 +00:00
|
|
|
bool Commit(void* address, size_t size);
|
2017-09-20 15:36:15 +00:00
|
|
|
|
|
|
|
// Uncommit real memory. Returns whether the operation succeeded.
|
|
|
|
bool Uncommit(void* address, size_t size);
|
|
|
|
|
|
|
|
// Creates a single guard page at the given address.
|
|
|
|
bool Guard(void* address);
|
|
|
|
|
|
|
|
// Releases the memory after |free_start|. Returns the bytes released.
|
|
|
|
size_t ReleasePartial(void* free_start);
|
|
|
|
|
|
|
|
void Release();
|
|
|
|
|
|
|
|
// Assign control of the reserved region to a different VirtualMemory object.
|
|
|
|
// The old object is no longer functional (IsReserved() returns false).
|
|
|
|
void TakeControl(VirtualMemory* from);
|
|
|
|
|
|
|
|
bool InVM(void* address, size_t size) {
|
|
|
|
return (reinterpret_cast<uintptr_t>(address_) <=
|
|
|
|
reinterpret_cast<uintptr_t>(address)) &&
|
|
|
|
((reinterpret_cast<uintptr_t>(address_) + size_) >=
|
|
|
|
(reinterpret_cast<uintptr_t>(address) + size));
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void* address_; // Start address of the virtual memory.
|
|
|
|
size_t size_; // Size of the virtual memory.
|
|
|
|
};
|
|
|
|
|
|
|
|
bool AllocVirtualMemory(size_t size, void* hint, VirtualMemory* result);
|
2017-08-01 01:41:13 +00:00
|
|
|
bool AlignedAllocVirtualMemory(size_t size, size_t alignment, void* hint,
|
2017-09-20 15:36:15 +00:00
|
|
|
VirtualMemory* result);
|
2017-08-01 01:41:13 +00:00
|
|
|
|
2015-09-30 13:46:56 +00:00
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
#endif // V8_ALLOCATION_H_
|