Allow the embedder to pass the virtual memory limit to v8
The getrlimit() call might be sandboxed, so it's not safe to use it. BUG=none R=mstarzinger@chromium.org LOG=y Review URL: https://codereview.chromium.org/228923002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20615 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
4df132a878
commit
dc4ba08d17
13
include/v8.h
13
include/v8.h
@ -3951,11 +3951,19 @@ class V8_EXPORT ResourceConstraints {
|
||||
*
|
||||
* \param physical_memory The total amount of physical memory on the current
|
||||
* device, in bytes.
|
||||
* \param virtual_memory_limit The amount of virtual memory on the current
|
||||
* device, in bytes, or zero, if there is no limit.
|
||||
* \param number_of_processors The number of CPUs available on the current
|
||||
* device.
|
||||
*/
|
||||
void ConfigureDefaults(uint64_t physical_memory,
|
||||
uint64_t virtual_memory_limit,
|
||||
uint32_t number_of_processors);
|
||||
// Deprecated.
|
||||
void ConfigureDefaults(uint64_t physical_memory,
|
||||
uint32_t number_of_processors) {
|
||||
ConfigureDefaults(physical_memory, 0, number_of_processors);
|
||||
}
|
||||
|
||||
int max_young_space_size() const { return max_young_space_size_; }
|
||||
void set_max_young_space_size(int value) { max_young_space_size_ = value; }
|
||||
@ -3971,6 +3979,10 @@ class V8_EXPORT ResourceConstraints {
|
||||
void set_max_available_threads(int value) {
|
||||
max_available_threads_ = value;
|
||||
}
|
||||
int code_range_size() const { return code_range_size_; }
|
||||
void set_code_range_size(int value) {
|
||||
code_range_size_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
int max_young_space_size_;
|
||||
@ -3978,6 +3990,7 @@ class V8_EXPORT ResourceConstraints {
|
||||
int max_executable_size_;
|
||||
uint32_t* stack_limit_;
|
||||
int max_available_threads_;
|
||||
int code_range_size_;
|
||||
};
|
||||
|
||||
|
||||
|
18
src/api.cc
18
src/api.cc
@ -464,9 +464,11 @@ ResourceConstraints::ResourceConstraints()
|
||||
max_old_space_size_(0),
|
||||
max_executable_size_(0),
|
||||
stack_limit_(NULL),
|
||||
max_available_threads_(0) { }
|
||||
max_available_threads_(0),
|
||||
code_range_size_(0) { }
|
||||
|
||||
void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
|
||||
uint64_t virtual_memory_limit,
|
||||
uint32_t number_of_processors) {
|
||||
const int lump_of_memory = (i::kPointerSize / 4) * i::MB;
|
||||
#if V8_OS_ANDROID
|
||||
@ -502,6 +504,13 @@ void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
|
||||
}
|
||||
|
||||
set_max_available_threads(i::Max(i::Min(number_of_processors, 4u), 1u));
|
||||
|
||||
if (virtual_memory_limit > 0 && i::kIs64BitArch) {
|
||||
// Reserve no more than 1/8 of the memory for the code range, but at most
|
||||
// 512 MB.
|
||||
set_code_range_size(
|
||||
i::Min(512 * i::MB, static_cast<int>(virtual_memory_limit >> 3)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -511,12 +520,15 @@ bool SetResourceConstraints(Isolate* v8_isolate,
|
||||
int young_space_size = constraints->max_young_space_size();
|
||||
int old_gen_size = constraints->max_old_space_size();
|
||||
int max_executable_size = constraints->max_executable_size();
|
||||
if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0) {
|
||||
int code_range_size = constraints->code_range_size();
|
||||
if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0 ||
|
||||
code_range_size != 0) {
|
||||
// After initialization it's too late to change Heap constraints.
|
||||
ASSERT(!isolate->IsInitialized());
|
||||
bool result = isolate->heap()->ConfigureHeap(young_space_size / 2,
|
||||
old_gen_size,
|
||||
max_executable_size);
|
||||
max_executable_size,
|
||||
code_range_size);
|
||||
if (!result) return false;
|
||||
}
|
||||
if (constraints->stack_limit() != NULL) {
|
||||
|
@ -1696,6 +1696,7 @@ int Shell::Main(int argc, char* argv[]) {
|
||||
#ifndef V8_SHARED
|
||||
v8::ResourceConstraints constraints;
|
||||
constraints.ConfigureDefaults(i::OS::TotalPhysicalMemory(),
|
||||
i::OS::MaxVirtualMemory(),
|
||||
i::CPU::NumberOfProcessorsOnline());
|
||||
v8::SetResourceConstraints(isolate, &constraints);
|
||||
#endif
|
||||
|
29
src/heap.cc
29
src/heap.cc
@ -68,7 +68,7 @@ namespace internal {
|
||||
|
||||
Heap::Heap()
|
||||
: isolate_(NULL),
|
||||
code_range_size_(kIs64BitArch ? 512 * MB : 0),
|
||||
code_range_size_(0),
|
||||
// semispace_size_ should be a power of 2 and old_generation_size_ should be
|
||||
// a multiple of Page::kPageSize.
|
||||
reserved_semispace_size_(8 * (kPointerSize / 4) * MB),
|
||||
@ -165,15 +165,6 @@ Heap::Heap()
|
||||
// Ensure old_generation_size_ is a multiple of kPageSize.
|
||||
ASSERT(MB >= Page::kPageSize);
|
||||
|
||||
intptr_t max_virtual = OS::MaxVirtualMemory();
|
||||
|
||||
if (max_virtual > 0) {
|
||||
if (code_range_size_ > 0) {
|
||||
// Reserve no more than 1/8 of the memory for the code range.
|
||||
code_range_size_ = Min(code_range_size_, max_virtual >> 3);
|
||||
}
|
||||
}
|
||||
|
||||
memset(roots_, 0, sizeof(roots_[0]) * kRootListLength);
|
||||
native_contexts_list_ = NULL;
|
||||
array_buffers_list_ = Smi::FromInt(0);
|
||||
@ -6137,7 +6128,8 @@ void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
|
||||
// size is not big enough to fit all the initial objects.
|
||||
bool Heap::ConfigureHeap(int max_semispace_size,
|
||||
intptr_t max_old_gen_size,
|
||||
intptr_t max_executable_size) {
|
||||
intptr_t max_executable_size,
|
||||
intptr_t code_range_size) {
|
||||
if (HasBeenSetUp()) return false;
|
||||
|
||||
if (FLAG_stress_compaction) {
|
||||
@ -6211,6 +6203,8 @@ bool Heap::ConfigureHeap(int max_semispace_size,
|
||||
FixedArray::SizeFor(JSObject::kInitialMaxFastElementArray) +
|
||||
AllocationMemento::kSize));
|
||||
|
||||
code_range_size_ = code_range_size;
|
||||
|
||||
configured_ = true;
|
||||
return true;
|
||||
}
|
||||
@ -6219,7 +6213,8 @@ bool Heap::ConfigureHeap(int max_semispace_size,
|
||||
bool Heap::ConfigureHeapDefault() {
|
||||
return ConfigureHeap(static_cast<intptr_t>(FLAG_max_new_space_size / 2) * KB,
|
||||
static_cast<intptr_t>(FLAG_max_old_space_size) * MB,
|
||||
static_cast<intptr_t>(FLAG_max_executable_size) * MB);
|
||||
static_cast<intptr_t>(FLAG_max_executable_size) * MB,
|
||||
static_cast<intptr_t>(0));
|
||||
}
|
||||
|
||||
|
||||
@ -6372,16 +6367,10 @@ bool Heap::SetUp() {
|
||||
if (old_data_space_ == NULL) return false;
|
||||
if (!old_data_space_->SetUp()) return false;
|
||||
|
||||
if (!isolate_->code_range()->SetUp(code_range_size_)) return false;
|
||||
|
||||
// Initialize the code space, set its maximum capacity to the old
|
||||
// generation size. It needs executable memory.
|
||||
// On 64-bit platform(s), we put all code objects in a 2 GB range of
|
||||
// virtual address space, so that they can call each other with near calls.
|
||||
if (code_range_size_ > 0) {
|
||||
if (!isolate_->code_range()->SetUp(code_range_size_)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
code_space_ =
|
||||
new OldSpace(this, max_old_generation_size_, CODE_SPACE, EXECUTABLE);
|
||||
if (code_space_ == NULL) return false;
|
||||
|
@ -572,7 +572,8 @@ class Heap {
|
||||
// set up already.
|
||||
bool ConfigureHeap(int max_semispace_size,
|
||||
intptr_t max_old_gen_size,
|
||||
intptr_t max_executable_size);
|
||||
intptr_t max_executable_size,
|
||||
intptr_t code_range_size);
|
||||
bool ConfigureHeapDefault();
|
||||
|
||||
// Prepares the heap, setting up memory areas that are needed in the isolate
|
||||
|
@ -133,9 +133,19 @@ CodeRange::CodeRange(Isolate* isolate)
|
||||
}
|
||||
|
||||
|
||||
bool CodeRange::SetUp(const size_t requested) {
|
||||
bool CodeRange::SetUp(size_t requested) {
|
||||
ASSERT(code_range_ == NULL);
|
||||
|
||||
if (requested == 0) {
|
||||
// On 64-bit platform(s), we put all code objects in a 512 MB range of
|
||||
// virtual address space, so that they can call each other with near calls.
|
||||
if (kIs64BitArch) {
|
||||
requested = 512 * MB;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
code_range_ = new VirtualMemory(requested);
|
||||
CHECK(code_range_ != NULL);
|
||||
if (!code_range_->IsReserved()) {
|
||||
@ -146,7 +156,8 @@ bool CodeRange::SetUp(const size_t requested) {
|
||||
|
||||
// We are sure that we have mapped a block of requested addresses.
|
||||
ASSERT(code_range_->size() == requested);
|
||||
LOG(isolate_, NewEvent("CodeRange", code_range_->address(), requested));
|
||||
LOG(isolate_,
|
||||
NewEvent("CodeRange", code_range_->address(), requested));
|
||||
Address base = reinterpret_cast<Address>(code_range_->address());
|
||||
Address aligned_base =
|
||||
RoundUp(reinterpret_cast<Address>(code_range_->address()),
|
||||
|
@ -946,7 +946,7 @@ class CodeRange {
|
||||
// Reserves a range of virtual memory, but does not commit any of it.
|
||||
// Can only be called once, at heap initialization time.
|
||||
// Returns false on failure.
|
||||
bool SetUp(const size_t requested_size);
|
||||
bool SetUp(size_t requested_size);
|
||||
|
||||
// Frees the range of virtual memory, and frees the data structures used to
|
||||
// manage it.
|
||||
|
@ -76,7 +76,7 @@ TEST(MarkingDeque) {
|
||||
TEST(Promotion) {
|
||||
CcTest::InitializeVM();
|
||||
Heap* heap = CcTest::heap();
|
||||
heap->ConfigureHeap(2*256*KB, 1*MB, 1*MB);
|
||||
heap->ConfigureHeap(2*256*KB, 1*MB, 1*MB, 0);
|
||||
|
||||
v8::HandleScope sc(CcTest::isolate());
|
||||
|
||||
@ -101,7 +101,7 @@ TEST(Promotion) {
|
||||
TEST(NoPromotion) {
|
||||
CcTest::InitializeVM();
|
||||
Heap* heap = CcTest::heap();
|
||||
heap->ConfigureHeap(2*256*KB, 1*MB, 1*MB);
|
||||
heap->ConfigureHeap(2*256*KB, 1*MB, 1*MB, 0);
|
||||
|
||||
v8::HandleScope sc(CcTest::isolate());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user