Revision: 5003
Author: [email protected]
Date: Thu Jul 1 14:55:46 2010
Log: [Isolates] RegExpStack and memory allocation limits
regexp-stack:
-> Split RegExpStackState from RegExpStack. RegExpStacks can be allocated
at will, while there is only one RegExpStackState per isolate.
platform-linux/platform-macos:
-> Protect lowest_ever_allocated and highest_ever_allocated with
a mutex (limit_mutex) that is initialized in OS::Setup.
Review URL: http://codereview.chromium.org/2807031
http://code.google.com/p/v8/source/detail?r=5003
Modified:
/branches/experimental/isolates/src/assembler.cc
/branches/experimental/isolates/src/isolate.cc
/branches/experimental/isolates/src/isolate.h
/branches/experimental/isolates/src/platform-linux.cc
/branches/experimental/isolates/src/platform-macos.cc
/branches/experimental/isolates/src/platform-win32.cc
/branches/experimental/isolates/src/regexp-macro-assembler.cc
/branches/experimental/isolates/src/regexp-stack.cc
/branches/experimental/isolates/src/regexp-stack.h
/branches/experimental/isolates/src/v8threads.cc
/branches/experimental/isolates/test/cctest/test-alloc.cc
/branches/experimental/isolates/test/cctest/test-assembler-x64.cc
/branches/experimental/isolates/test/cctest/test-platform-linux.cc
/branches/experimental/isolates/test/cctest/test-serialize.cc
/branches/experimental/isolates/test/cctest/test-spaces.cc
/branches/experimental/isolates/test/cctest/test-utils.cc
=======================================
--- /branches/experimental/isolates/src/assembler.cc Tue Jun 29 18:06:08
2010
+++ /branches/experimental/isolates/src/assembler.cc Thu Jul 1 14:55:46
2010
@@ -629,7 +629,8 @@
ExternalReference ExternalReference::address_of_regexp_stack_limit() {
- return ExternalReference(RegExpStack::limit_address());
+ return ExternalReference(
+ Isolate::Current()->regexp_stack()->limit_address());
}
@@ -715,11 +716,13 @@
}
ExternalReference
ExternalReference::address_of_regexp_stack_memory_address() {
- return ExternalReference(RegExpStack::memory_address());
+ return ExternalReference(
+ Isolate::Current()->regexp_stack()->memory_address());
}
ExternalReference ExternalReference::address_of_regexp_stack_memory_size()
{
- return ExternalReference(RegExpStack::memory_size_address());
+ return ExternalReference(
+ Isolate::Current()->regexp_stack()->memory_size_address());
}
#endif // V8_INTERPRETED_REGEXP
=======================================
--- /branches/experimental/isolates/src/isolate.cc Thu Jul 1 11:02:03 2010
+++ /branches/experimental/isolates/src/isolate.cc Thu Jul 1 14:55:46 2010
@@ -37,6 +37,7 @@
#include "heap-profiler.h"
#include "isolate.h"
#include "log.h"
+#include "regexp-stack.h"
#include "serialize.h"
#include "scanner.h"
#include "scopeinfo.h"
@@ -253,7 +254,9 @@
context_switcher_(NULL),
thread_manager_(NULL),
ast_sentinels_(NULL),
+ inline_runtime_functions_table_(NULL),
string_tracker_(NULL),
+ regexp_stack_(NULL),
frame_element_constant_list_(0),
result_constant_list_(0) {
memset(isolate_addresses_, 0,
@@ -336,6 +339,9 @@
delete scanner_character_classes_;
scanner_character_classes_ = NULL;
+ delete regexp_stack_;
+ regexp_stack_ = NULL;
+
delete inline_runtime_functions_table_;
inline_runtime_functions_table_ = NULL;
@@ -448,6 +454,8 @@
stub_cache_ = new StubCache();
ast_sentinels_ = new AstSentinels();
inline_runtime_functions_table_ = new InlineRuntimeFunctionsTable();
+ regexp_stack_ = new RegExpStack();
+ regexp_stack_->isolate_ = this;
#ifdef ENABLE_DEBUGGER_SUPPORT
debugger_ = new Debugger();
=======================================
--- /branches/experimental/isolates/src/isolate.h Thu Jul 1 11:02:03 2010
+++ /branches/experimental/isolates/src/isolate.h Thu Jul 1 14:55:46 2010
@@ -67,6 +67,7 @@
class NoAllocationStringAllocator;
class PreallocatedMemoryThread;
class ProducerHeapProfile;
+class RegExpStack;
class SaveContext;
class StubCache;
class StringInputBuffer;
@@ -662,6 +663,8 @@
regexp_macro_assembler_canonicalize() {
return ®exp_macro_assembler_canonicalize_;
}
+
+ RegExpStack* regexp_stack() { return regexp_stack_; }
unibrow::Mapping<unibrow::Ecma262Canonicalize>*
interp_canonicalize_mapping() {
@@ -800,6 +803,7 @@
StaticResource<StringInputBuffer> objects_string_input_buffer_;
unibrow::Mapping<unibrow::Ecma262Canonicalize>
regexp_macro_assembler_canonicalize_;
+ RegExpStack* regexp_stack_;
unibrow::Mapping<unibrow::Ecma262Canonicalize>
interp_canonicalize_mapping_;
ZoneObjectList frame_element_constant_list_;
ZoneObjectList result_constant_list_;
=======================================
--- /branches/experimental/isolates/src/platform-linux.cc Thu Jun 24
09:41:05 2010
+++ /branches/experimental/isolates/src/platform-linux.cc Thu Jul 1
14:55:46 2010
@@ -70,6 +70,9 @@
double ceiling(double x) {
return ceil(x);
}
+
+
+static Mutex* limit_mutex = NULL;
void OS::Setup() {
@@ -80,6 +83,7 @@
// call this setup code within the same millisecond.
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
srandom(static_cast<unsigned int>(seed));
+ limit_mutex = CreateMutex();
}
@@ -215,6 +219,9 @@
static void UpdateAllocatedSpaceLimits(void* address, int size) {
+ ASSERT(limit_mutex != NULL);
+ ScopedLock lock(limit_mutex);
+
lowest_ever_allocated = Min(lowest_ever_allocated, address);
highest_ever_allocated =
Max(highest_ever_allocated,
=======================================
--- /branches/experimental/isolates/src/platform-macos.cc Fri May 21
22:27:19 2010
+++ /branches/experimental/isolates/src/platform-macos.cc Thu Jul 1
14:55:46 2010
@@ -85,6 +85,9 @@
return ceil(x);
}
}
+
+
+static Mutex* limit_mutex = NULL;
void OS::Setup() {
@@ -95,6 +98,7 @@
// call this setup code within the same millisecond.
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
srandom(static_cast<unsigned int>(seed));
+ limit_mutex = CreateMutex();
}
@@ -108,6 +112,9 @@
static void UpdateAllocatedSpaceLimits(void* address, int size) {
+ ASSERT(limit_mutex != NULL);
+ ScopedLock lock(limit_mutex);
+
lowest_ever_allocated = Min(lowest_ever_allocated, address);
highest_ever_allocated =
Max(highest_ever_allocated,
=======================================
--- /branches/experimental/isolates/src/platform-win32.cc Fri May 21
22:27:19 2010
+++ /branches/experimental/isolates/src/platform-win32.cc Thu Jul 1
14:55:46 2010
@@ -222,6 +222,10 @@
double ceiling(double x) {
return ceil(x);
}
+
+
+static Mutex* limit_mutex = NULL;
+
#ifdef _WIN64
typedef double (*ModuloFunction)(double, double);
@@ -590,6 +594,7 @@
// call this setup code within the same millisecond.
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
srand(static_cast<unsigned int>(seed));
+ limit_mutex = CreateMutex();
}
@@ -791,6 +796,9 @@
static void UpdateAllocatedSpaceLimits(void* address, int size) {
+ ASSERT(limit_mutex != NULL);
+ ScopedLock lock(limit_mutex);
+
lowest_ever_allocated = Min(lowest_ever_allocated, address);
highest_ever_allocated =
Max(highest_ever_allocated,
=======================================
--- /branches/experimental/isolates/src/regexp-macro-assembler.cc Tue Jun
29 11:05:31 2010
+++ /branches/experimental/isolates/src/regexp-macro-assembler.cc Thu Jul
1 14:55:46 2010
@@ -156,13 +156,14 @@
const byte* input_start,
const byte* input_end,
int* output) {
+ Isolate* isolate = Isolate::Current();
typedef int (*matcher)(String*, int, const byte*,
const byte*, int*, Address, int);
matcher matcher_func = FUNCTION_CAST<matcher>(code->entry());
// Ensure that the minimum stack has been allocated.
- RegExpStack stack;
- Address stack_base = RegExpStack::stack_base();
+ RegExpStackScope stack_scope(isolate);
+ Address stack_base = stack_scope.stack()->stack_base();
int direct_call = 0;
int result = CALL_GENERATED_REGEXP_CODE(matcher_func,
@@ -176,10 +177,10 @@
ASSERT(result <= SUCCESS);
ASSERT(result >= RETRY);
- if (result == EXCEPTION && !Isolate::Current()->has_pending_exception())
{
+ if (result == EXCEPTION && !isolate->has_pending_exception()) {
// We detected a stack overflow (on the backtrack stack) in RegExp
code,
// but haven't created the exception yet.
- Isolate::Current()->StackOverflow();
+ isolate->StackOverflow();
}
return static_cast<Result>(result);
}
@@ -243,12 +244,13 @@
Address NativeRegExpMacroAssembler::GrowStack(Address stack_pointer,
Address* stack_base) {
- size_t size = RegExpStack::stack_capacity();
- Address old_stack_base = RegExpStack::stack_base();
+ RegExpStack* regexp_stack = Isolate::Current()->regexp_stack();
+ size_t size = regexp_stack->stack_capacity();
+ Address old_stack_base = regexp_stack->stack_base();
ASSERT(old_stack_base == *stack_base);
ASSERT(stack_pointer <= old_stack_base);
ASSERT(static_cast<size_t>(old_stack_base - stack_pointer) <= size);
- Address new_stack_base = RegExpStack::EnsureCapacity(size * 2);
+ Address new_stack_base = regexp_stack->EnsureCapacity(size * 2);
if (new_stack_base == NULL) {
return NULL;
}
=======================================
--- /branches/experimental/isolates/src/regexp-stack.cc Mon Jun 21 10:40:11
2010
+++ /branches/experimental/isolates/src/regexp-stack.cc Thu Jul 1 14:55:46
2010
@@ -31,15 +31,26 @@
namespace v8 {
namespace internal {
-RegExpStack::RegExpStack() {
+RegExpStackScope::RegExpStackScope(Isolate* isolate)
+ : regexp_stack_(isolate->regexp_stack()) {
// Initialize, if not already initialized.
- RegExpStack::EnsureCapacity(0);
+ regexp_stack_->EnsureCapacity(0);
}
-RegExpStack::~RegExpStack() {
+RegExpStackScope::~RegExpStackScope() {
+ ASSERT(Isolate::Current() == regexp_stack_->isolate_);
// Reset the buffer if it has grown.
- RegExpStack::Reset();
+ regexp_stack_->Reset();
+}
+
+
+RegExpStack::RegExpStack()
+ : isolate_(NULL) {
+}
+
+
+RegExpStack::~RegExpStack() {
}
@@ -69,9 +80,9 @@
void RegExpStack::ThreadLocal::Free() {
- if (thread_local_.memory_size_ > 0) {
- DeleteArray(thread_local_.memory_);
- thread_local_ = ThreadLocal();
+ if (memory_size_ > 0) {
+ DeleteArray(memory_);
+ Clear();
}
}
@@ -97,6 +108,4 @@
}
-RegExpStack::ThreadLocal RegExpStack::thread_local_;
-
}} // namespace v8::internal
=======================================
--- /branches/experimental/isolates/src/regexp-stack.h Wed Jan 6 03:09:30
2010
+++ /branches/experimental/isolates/src/regexp-stack.h Thu Jul 1 14:55:46
2010
@@ -31,11 +31,30 @@
namespace v8 {
namespace internal {
+class RegExpStack;
+
// Maintains a per-v8thread stack area that can be used by irregexp
// implementation for its backtracking stack.
// Since there is only one stack area, the Irregexp implementation is not
// re-entrant. I.e., no regular expressions may be executed in the same
thread
// during a preempted Irregexp execution.
+class RegExpStackScope {
+ public:
+ // Create and delete an instance to control the life-time of a growing
stack.
+
+ // Initializes the stack memory area if necessary.
+ explicit RegExpStackScope(Isolate* isolate);
+ ~RegExpStackScope(); // Releases the stack if it has grown.
+
+ RegExpStack* stack() const { return regexp_stack_; }
+
+ private:
+ RegExpStack* regexp_stack_;
+
+ DISALLOW_COPY_AND_ASSIGN(RegExpStackScope);
+};
+
+
class RegExpStack {
public:
// Number of allocated locations on the stack below the limit.
@@ -43,39 +62,37 @@
// check.
static const int kStackLimitSlack = 32;
- // Create and delete an instance to control the life-time of a growing
stack.
- RegExpStack(); // Initializes the stack memory area if necessary.
- ~RegExpStack(); // Releases the stack if it has grown.
-
// Gives the top of the memory used as stack.
- static Address stack_base() {
+ Address stack_base() {
ASSERT(thread_local_.memory_size_ != 0);
return thread_local_.memory_ + thread_local_.memory_size_;
}
// The total size of the memory allocated for the stack.
- static size_t stack_capacity() { return thread_local_.memory_size_; }
+ size_t stack_capacity() { return thread_local_.memory_size_; }
// If the stack pointer gets below the limit, we should react and
// either grow the stack or report an out-of-stack exception.
// There is only a limited number of locations below the stack limit,
// so users of the stack should check the stack limit during any
// sequence of pushes longer that this.
- static Address* limit_address() { return &(thread_local_.limit_); }
+ Address* limit_address() { return &(thread_local_.limit_); }
// Ensures that there is a memory area with at least the specified size.
// If passing zero, the default/minimum size buffer is allocated.
- static Address EnsureCapacity(size_t size);
+ Address EnsureCapacity(size_t size);
// Thread local archiving.
static int ArchiveSpacePerThread() {
- return static_cast<int>(sizeof(thread_local_));
- }
- static char* ArchiveStack(char* to);
- static char* RestoreStack(char* from);
- static void FreeThreadResources() { thread_local_.Free(); }
-
+ return static_cast<int>(sizeof(ThreadLocal));
+ }
+ char* ArchiveStack(char* to);
+ char* RestoreStack(char* from);
+ void FreeThreadResources() { thread_local_.Free(); }
private:
+ RegExpStack();
+ ~RegExpStack();
+
// Artificial limit used when no memory has been allocated.
static const uintptr_t kMemoryTop = static_cast<uintptr_t>(-1);
@@ -87,35 +104,42 @@
// Structure holding the allocated memory, size and limit.
struct ThreadLocal {
- ThreadLocal()
- : memory_(NULL),
- memory_size_(0),
- limit_(reinterpret_cast<Address>(kMemoryTop)) {}
+ ThreadLocal() { Clear(); }
// If memory_size_ > 0 then memory_ must be non-NULL.
Address memory_;
size_t memory_size_;
Address limit_;
+ void Clear() {
+ memory_ = NULL;
+ memory_size_ = 0;
+ limit_ = reinterpret_cast<Address>(kMemoryTop);
+ }
void Free();
};
// Address of allocated memory.
- static Address memory_address() {
+ Address memory_address() {
return reinterpret_cast<Address>(&thread_local_.memory_);
}
// Address of size of allocated memory.
- static Address memory_size_address() {
+ Address memory_size_address() {
return reinterpret_cast<Address>(&thread_local_.memory_size_);
}
// Resets the buffer if it has grown beyond the default/minimum size.
// After this, the buffer is either the default size, or it is empty, so
// you have to call EnsureCapacity before using it again.
- static void Reset();
-
- static ThreadLocal thread_local_;
+ void Reset();
+
+ ThreadLocal thread_local_;
+ Isolate* isolate_;
friend class ExternalReference;
+ friend class Isolate;
+ friend class RegExpStackScope;
+
+ DISALLOW_COPY_AND_ASSIGN(RegExpStack);
};
}} // namespace v8::internal
=======================================
--- /branches/experimental/isolates/src/v8threads.cc Tue Jun 29 13:01:19
2010
+++ /branches/experimental/isolates/src/v8threads.cc Thu Jul 1 14:55:46
2010
@@ -163,7 +163,7 @@
from = isolate_->debug()->RestoreDebug(from);
#endif
from = isolate_->stack_guard()->RestoreStackGuard(from);
- from = RegExpStack::RestoreStack(from);
+ from = isolate_->regexp_stack()->RestoreStack(from);
from = isolate_->bootstrapper()->RestoreState(from);
Thread::SetThreadLocal(thread_state_key_, NULL);
if (state->terminate_on_restore()) {
@@ -307,7 +307,7 @@
to = isolate_->debug()->ArchiveDebug(to);
#endif
to = isolate_->stack_guard()->ArchiveStackGuard(to);
- to = RegExpStack::ArchiveStack(to);
+ to = isolate_->regexp_stack()->ArchiveStack(to);
to = isolate_->bootstrapper()->ArchiveState(to);
lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
lazily_archived_thread_state_ = NULL;
@@ -321,7 +321,7 @@
isolate_->debug()->FreeThreadResources();
#endif
isolate_->stack_guard()->FreeThreadResources();
- RegExpStack::FreeThreadResources();
+ isolate_->regexp_stack()->FreeThreadResources();
isolate_->bootstrapper()->FreeThreadResources();
}
=======================================
--- /branches/experimental/isolates/test/cctest/test-alloc.cc Fri Jun 25
15:32:52 2010
+++ /branches/experimental/isolates/test/cctest/test-alloc.cc Thu Jul 1
14:55:46 2010
@@ -185,6 +185,7 @@
TEST(CodeRange) {
const int code_range_size = 16*MB;
+ OS::Setup();
Isolate::Current()->code_range()->Setup(code_range_size);
int current_allocated = 0;
int total_allocated = 0;
=======================================
--- /branches/experimental/isolates/test/cctest/test-assembler-x64.cc Wed
Nov 11 01:50:06 2009
+++ /branches/experimental/isolates/test/cctest/test-assembler-x64.cc Thu
Jul 1 14:55:46 2010
@@ -80,6 +80,7 @@
TEST(AssemblerX64ReturnOperation) {
+ OS::Setup();
// Allocate an executable page of memory.
size_t actual_size;
byte* buffer =
static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -101,6 +102,7 @@
}
TEST(AssemblerX64StackOperations) {
+ OS::Setup();
// Allocate an executable page of memory.
size_t actual_size;
byte* buffer =
static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -132,6 +134,7 @@
}
TEST(AssemblerX64ArithmeticOperations) {
+ OS::Setup();
// Allocate an executable page of memory.
size_t actual_size;
byte* buffer =
static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -153,6 +156,7 @@
}
TEST(AssemblerX64ImulOperation) {
+ OS::Setup();
// Allocate an executable page of memory.
size_t actual_size;
byte* buffer =
static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -180,6 +184,7 @@
}
TEST(AssemblerX64MemoryOperands) {
+ OS::Setup();
// Allocate an executable page of memory.
size_t actual_size;
byte* buffer =
static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -213,6 +218,7 @@
}
TEST(AssemblerX64ControlFlow) {
+ OS::Setup();
// Allocate an executable page of memory.
size_t actual_size;
byte* buffer =
static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -241,6 +247,7 @@
}
TEST(AssemblerX64LoopImmediates) {
+ OS::Setup();
// Allocate an executable page of memory.
size_t actual_size;
byte* buffer =
static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
=======================================
--- /branches/experimental/isolates/test/cctest/test-platform-linux.cc Tue
Sep 9 13:08:45 2008
+++ /branches/experimental/isolates/test/cctest/test-platform-linux.cc Thu
Jul 1 14:55:46 2010
@@ -67,6 +67,7 @@
TEST(VirtualMemory) {
+ OS::Setup();
VirtualMemory* vm = new VirtualMemory(1 * MB);
CHECK(vm->IsReserved());
void* block_addr = vm->address();
=======================================
--- /branches/experimental/isolates/test/cctest/test-serialize.cc Thu Jul
1 11:02:03 2010
+++ /branches/experimental/isolates/test/cctest/test-serialize.cc Thu Jul
1 14:55:46 2010
@@ -106,6 +106,7 @@
TEST(ExternalReferenceEncoder) {
+ OS::Setup();
i::Isolate::Current()->stats_table()->SetCounterFunction(counter_function);
HEAP->Setup(false);
ExternalReferenceEncoder encoder;
@@ -147,6 +148,7 @@
TEST(ExternalReferenceDecoder) {
+ OS::Setup();
i::Isolate::Current()->stats_table()->SetCounterFunction(counter_function);
HEAP->Setup(false);
ExternalReferenceDecoder decoder;
=======================================
--- /branches/experimental/isolates/test/cctest/test-spaces.cc Mon Jun 21
15:48:21 2010
+++ /branches/experimental/isolates/test/cctest/test-spaces.cc Thu Jul 1
14:55:46 2010
@@ -90,6 +90,7 @@
TEST(MemoryAllocator) {
+ OS::Setup();
Isolate* isolate = Isolate::Current();
CHECK(isolate->heap()->ConfigureHeapDefault());
@@ -151,6 +152,7 @@
TEST(NewSpace) {
+ OS::Setup();
CHECK(HEAP->ConfigureHeapDefault());
CHECK(Isolate::Current()->memory_allocator()->Setup(HEAP->MaxReserved()));
@@ -177,6 +179,7 @@
TEST(OldSpace) {
+ OS::Setup();
CHECK(HEAP->ConfigureHeapDefault());
CHECK(Isolate::Current()->memory_allocator()->Setup(HEAP->MaxReserved()));
@@ -206,6 +209,7 @@
TEST(LargeObjectSpace) {
+ OS::Setup();
CHECK(HEAP->Setup(false));
LargeObjectSpace* lo = HEAP->lo_space();
=======================================
--- /branches/experimental/isolates/test/cctest/test-utils.cc Wed Jun 9
16:02:44 2010
+++ /branches/experimental/isolates/test/cctest/test-utils.cc Thu Jul 1
14:55:46 2010
@@ -103,6 +103,7 @@
TEST(MemCopy) {
+ OS::Setup();
const int N = kMinComplexMemCopy + 128;
Vector<byte> buffer1 = Vector<byte>::New(N);
Vector<byte> buffer2 = Vector<byte>::New(N);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev