Commit 21d28657 authored by lrn@chromium.org's avatar lrn@chromium.org

Separately growing stack for irregexp ia32 backtrack stack.


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1053 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent cb94595c
......@@ -44,11 +44,11 @@ SOURCES = {
'interpreter-irregexp.cc', 'jsregexp.cc', 'log.cc', 'mark-compact.cc',
'messages.cc', 'objects.cc', 'parser.cc', 'property.cc',
'regexp-macro-assembler.cc', 'regexp-macro-assembler-irregexp.cc',
'rewriter.cc', 'runtime.cc', 'scanner.cc', 'scopeinfo.cc', 'scopes.cc',
'serialize.cc', 'snapshot-common.cc', 'spaces.cc', 'string-stream.cc',
'stub-cache.cc', 'token.cc', 'top.cc', 'unicode.cc', 'usage-analyzer.cc',
'utils.cc', 'v8-counters.cc', 'v8.cc', 'v8threads.cc', 'variables.cc',
'zone.cc'
'regexp-stack.cc', 'rewriter.cc', 'runtime.cc', 'scanner.cc',
'scopeinfo.cc', 'scopes.cc', 'serialize.cc', 'snapshot-common.cc',
'spaces.cc', 'string-stream.cc', 'stub-cache.cc', 'token.cc', 'top.cc',
'unicode.cc', 'usage-analyzer.cc', 'utils.cc', 'v8-counters.cc', 'v8.cc',
'v8threads.cc', 'variables.cc', 'zone.cc'
],
'arch:arm': ['assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc',
'cpu-arm.cc', 'debug-arm.cc', 'disasm-arm.cc', 'frames-arm.cc',
......
......@@ -41,6 +41,7 @@
#include "runtime.h"
#include "serialize.h"
#include "stub-cache.h"
#include "regexp-stack.h"
namespace v8 { namespace internal {
......@@ -551,6 +552,11 @@ ExternalReference ExternalReference::address_of_stack_guard_limit() {
}
ExternalReference ExternalReference::address_of_regexp_stack_limit() {
return ExternalReference(RegExpStack::limit_address());
}
ExternalReference ExternalReference::debug_break() {
return ExternalReference(FUNCTION_ADDR(Debug::Break));
}
......
......@@ -442,6 +442,9 @@ class ExternalReference BASE_EMBEDDED {
// Static variable StackGuard::address_of_limit()
static ExternalReference address_of_stack_guard_limit();
// Static variable RegExpStack::limit_address()
static ExternalReference address_of_regexp_stack_limit();
// Function Debug::Break()
static ExternalReference debug_break();
......
......@@ -40,6 +40,7 @@
#include "regexp-macro-assembler.h"
#include "regexp-macro-assembler-tracer.h"
#include "regexp-macro-assembler-irregexp.h"
#include "regexp-stack.h"
#ifdef ARM
#include "regexp-macro-assembler-arm.h"
......@@ -913,7 +914,7 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
}
res = RegExpMacroAssemblerIA32::Execute(
*code,
&address,
const_cast<Address*>(&address),
start_offset << char_size_shift,
end_offset << char_size_shift,
offsets_vector,
......@@ -925,7 +926,7 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
int byte_offset = char_address - reinterpret_cast<Address>(*subject);
res = RegExpMacroAssemblerIA32::Execute(
*code,
subject.location(),
reinterpret_cast<Address*>(subject.location()),
byte_offset + (start_offset << char_size_shift),
byte_offset + (end_offset << char_size_shift),
offsets_vector,
......@@ -1347,8 +1348,18 @@ int GenerationVariant::FindAffectedRegisters(OutSet* affected_registers) {
void GenerationVariant::PushAffectedRegisters(RegExpMacroAssembler* assembler,
int max_register,
OutSet& affected_registers) {
for (int reg = 0; reg <= max_register; reg++) {
if (affected_registers.Get(reg)) assembler->PushRegister(reg);
// Stay safe and check every half times the limit.
// (Round up in case the limit is 1).
int push_limit = (assembler->stack_limit_slack() + 1) / 2;
for (int reg = 0, pushes = 0; reg <= max_register; reg++) {
if (affected_registers.Get(reg)) {
pushes++;
RegExpMacroAssembler::StackCheckFlag check_stack_limit =
(pushes % push_limit) == 0 ?
RegExpMacroAssembler::kCheckStackLimit :
RegExpMacroAssembler::kNoStackLimitCheck;
assembler->PushRegister(reg, check_stack_limit);
}
}
}
......
This diff is collapsed.
......@@ -38,6 +38,7 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
RegExpMacroAssemblerIA32(Mode mode, int registers_to_save);
virtual ~RegExpMacroAssemblerIA32();
virtual int stack_limit_slack();
virtual void AdvanceCurrentPosition(int by);
virtual void AdvanceRegister(int reg, int by);
virtual void Backtrack();
......@@ -53,6 +54,8 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
int cp_offset,
Label* on_failure,
bool check_end_of_string);
// A "greedy loop" is a loop that is both greedy and with a simple
// body. It has a particularly simple implementation.
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
virtual void CheckNotAtStart(Label* on_not_at_start);
virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
......@@ -96,7 +99,8 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
virtual void PopRegister(int register_index);
virtual void PushBacktrack(Label* label);
virtual void PushCurrentPosition();
virtual void PushRegister(int register_index);
virtual void PushRegister(int register_index,
StackCheckFlag check_stack_limit);
virtual void ReadCurrentPositionFromRegister(int reg);
virtual void ReadStackPointerFromRegister(int reg);
virtual void SetRegister(int register_index, int to);
......@@ -104,26 +108,15 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
virtual void WriteStackPointerToRegister(int reg);
template <typename T>
static inline Result Execute(Code* code,
T** input,
int start_offset,
int end_offset,
int* output,
bool at_start) {
typedef int (*matcher)(T**, int, int, int*, int);
matcher matcher_func = FUNCTION_CAST<matcher>(code->entry());
int at_start_val = at_start ? 1 : 0;
int result = matcher_func(input,
start_offset,
end_offset,
output,
at_start_val);
return (result < 0) ? EXCEPTION : (result ? SUCCESS : FAILURE);
}
static Result Execute(Code* code,
Address* input,
int start_offset,
int end_offset,
int* output,
bool at_start);
private:
// Offsets from ebp of arguments to function.
// Offsets from ebp of arguments to function and stored registers.
static const int kBackup_ebx = sizeof(uint32_t);
static const int kBackup_edi = kBackup_ebx + sizeof(uint32_t);
static const int kBackup_esi = kBackup_edi + sizeof(uint32_t);
......@@ -133,24 +126,30 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
static const int kInputEndOffset = kInputStartOffset + sizeof(uint32_t);
static const int kRegisterOutput = kInputEndOffset + sizeof(uint32_t);
static const int kAtStart = kRegisterOutput + sizeof(uint32_t);
static const int kStackHighEnd = kAtStart + sizeof(uint32_t);
// Initial size of code buffer.
static const size_t kRegExpCodeSize = 1024;
// Initial size of constant buffers allocated during compilation.
static const int kRegExpConstantsSize = 256;
// Only unroll loops up to this length. TODO(lrn): Actually use this.
// Only unroll loops up to this length.
static const int kMaxInlineStringTests = 32;
// Compares two-byte strings case insensitively.
// Called from generated RegExp code.
static int CaseInsensitiveCompareUC16(uc16** buffer,
int byte_offset1,
int byte_offset2,
size_t byte_length);
void LoadCurrentCharacterUnchecked(int cp_offset, int characters);
// Load a number of characters at the given offset from the
// current position, into the current-character register.
void LoadCurrentCharacterUnchecked(int cp_offset, int character_count);
// Adds code that checks whether preemption has been requested
// (and checks if we have hit the stack limit too).
// Check whether preemption has been requested.
void CheckPreemption();
// Check whether we are exceeding the stack limit on the backtrack stack.
void CheckStackLimit();
// Called from RegExp if the stack-guard is triggered.
......@@ -158,6 +157,12 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
// returning.
static int CheckStackGuardState(Address return_address, Code* re_code);
// Called from RegExp if the backtrack stack limit is hit.
// Tries to expand the stack. Returns the new stack-top pointer if
// successful, or 0 if unable to grow the stack.
// This function must not trigger a garbage collection.
static Address GrowStack(Address stack_top);
// Checks whether the given offset from the current position is before
// the end of the string.
void CheckPosition(int cp_offset, Label* on_outside_input);
......@@ -166,14 +171,18 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
Operand register_location(int register_index);
// The register containing the current character after LoadCurrentCharacter.
Register current_character();
inline Register current_character() { return edx; }
// The register containing the backtrack stack top. Provides a meaningful
// name to the register.
inline Register backtrack_stackpointer() { return ecx; }
// Byte size of chars in the string to match (decided by the Mode argument)
size_t char_size();
inline size_t char_size() { return static_cast<size_t>(mode_); }
// Equivalent to a conditional branch to the label, unless the label
// is NULL, in which case it is a conditional Backtrack.
void BranchOrBacktrack(Condition condition, Label* to);
void BranchOrBacktrack(Condition condition, Label* to, Hint hint = no_hint);
// Load the address of a "constant buffer" (a slice of a byte array)
// into a register. The address is computed from the ByteArray* address
......@@ -182,30 +191,50 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
// Call and return internally in the generated code in a way that
// is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
void SafeCall(Label* to);
void SafeReturn();
inline void SafeCall(Label* to);
inline void SafeReturn();
// Pushes the value of a register on the backtrack stack. Decrements the
// stack pointer (ecx) by a word size and stores the register's value there.
inline void Push(Register source);
// Pushes a value on the backtrack stack. Decrements the stack pointer (ecx)
// by a word size and stores the value there.
inline void Push(Immediate value);
// Pops a value from the backtrack stack. Reads the word at the stack pointer
// (ecx) and increments it by a word size.
inline void Pop(Register target);
// Before calling a C-function from generated code, align arguments on stack.
// After aligning the frame, arguments must be stored in esp[0], esp[4],
// etc., not pushed. The argument count assumes all arguments are word sized.
void FrameAlign(int num_arguments);
// Some compilers/platforms require the stack to be aligned when calling
// C++ code.
inline void FrameAlign(int num_arguments);
// Calls a C function and cleans up the space for arguments allocated
// by FrameAlign. The called function is not allowed to trigger a garbage
// collection, since that might move the code and invalidate the return
// address
void CallCFunction(Address function_address, int num_arguments);
// address (unless this is somehow accounted for).
inline void CallCFunction(Address function_address, int num_arguments);
MacroAssembler* masm_;
// Constant buffer provider. Allocates external storage for storing
// constants.
ByteArrayProvider constants_;
// Which mode to generate code for (ASCII or UTF16).
Mode mode_;
// One greater than maximal register index actually used.
int num_registers_;
// Number of registers to output at the end (the saved registers
// are always 0..num_saved_registers_-1)
int num_saved_registers_;
// Labels used internally.
Label entry_label_;
Label start_label_;
......@@ -213,6 +242,8 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
Label backtrack_label_;
Label exit_label_;
Label check_preempt_label_;
Label stack_overflow_label_;
// Handle used to represent the generated code object itself.
Handle<Object> self_;
};
......
......@@ -89,7 +89,9 @@ void RegExpMacroAssemblerIrregexp::PopRegister(int register_index) {
}
void RegExpMacroAssemblerIrregexp::PushRegister(int register_index) {
void RegExpMacroAssemblerIrregexp::PushRegister(
int register_index,
StackCheckFlag check_stack_limit) {
ASSERT(register_index >= 0);
Emit(BC_PUSH_REGISTER);
Emit(register_index);
......
......@@ -48,6 +48,8 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
// upon destruction of the assembler.
explicit RegExpMacroAssemblerIrregexp(Vector<byte>);
virtual ~RegExpMacroAssemblerIrregexp();
// The byte-code interpreter checks on each push anyway.
virtual int stack_limit_slack() { return 1; }
virtual void Bind(Label* label);
virtual void EmitOrLink(Label* label);
virtual void AdvanceCurrentPosition(int by); // Signed cp change.
......@@ -59,7 +61,8 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
virtual void Succeed();
virtual void Fail();
virtual void PopRegister(int register_index);
virtual void PushRegister(int register_index);
virtual void PushRegister(int register_index,
StackCheckFlag check_stack_limit);
virtual void AdvanceRegister(int reg, int by); // r[reg] += by.
virtual void SetRegister(int register_index, int to);
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
......
......@@ -95,7 +95,8 @@ void RegExpMacroAssemblerTracer::GoTo(Label* label) {
void RegExpMacroAssemblerTracer::PushBacktrack(Label* label) {
PrintF(" PushBacktrack(label[%08x]);\n", label);
PrintF(" PushBacktrack(label[%08x]);\n",
label);
assembler_->PushBacktrack(label);
}
......@@ -118,9 +119,13 @@ void RegExpMacroAssemblerTracer::PopRegister(int register_index) {
}
void RegExpMacroAssemblerTracer::PushRegister(int register_index) {
PrintF(" PushRegister(register=%d);\n", register_index);
assembler_->PushRegister(register_index);
void RegExpMacroAssemblerTracer::PushRegister(
int register_index,
StackCheckFlag check_stack_limit) {
PrintF(" PushRegister(register=%d, %s);\n",
register_index,
check_stack_limit ? "check stack limit" : "");
assembler_->PushRegister(register_index, check_stack_limit);
}
......
......@@ -35,6 +35,7 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
public:
explicit RegExpMacroAssemblerTracer(RegExpMacroAssembler* assembler);
virtual ~RegExpMacroAssemblerTracer();
virtual int stack_limit_slack() { return assembler_->stack_limit_slack(); }
virtual void AdvanceCurrentPosition(int by); // Signed cp change.
virtual void AdvanceRegister(int reg, int by); // r[reg] += by.
......@@ -98,7 +99,8 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
virtual void PopRegister(int register_index);
virtual void PushBacktrack(Label* label);
virtual void PushCurrentPosition();
virtual void PushRegister(int register_index);
virtual void PushRegister(int register_index,
StackCheckFlag check_stack_limit);
virtual void ReadCurrentPositionFromRegister(int reg);
virtual void ReadStackPointerFromRegister(int reg);
virtual void SetRegister(int register_index, int to);
......
......@@ -68,10 +68,11 @@ ArraySlice ByteArrayProvider::GetBuffer(unsigned int size,
return ArraySlice(current_byte_array_, free_offset);
}
template <typename T>
ArraySlice ByteArrayProvider::GetBuffer(Vector<T> values) {
ArraySlice slice = GetBuffer(values.length(), sizeof(T));
memcpy(slice.location(), values.start(), values.length() * sizeof(T));
return slice;
}
} }
} } // namespace v8::internal
......@@ -30,7 +30,6 @@
namespace v8 { namespace internal {
struct DisjunctDecisionRow {
RegExpCharacterClass cc;
Label* on_match;
......@@ -42,12 +41,24 @@ class RegExpMacroAssembler {
enum IrregexpImplementation {
kIA32Implementation,
kARMImplementation,
kBytecodeImplementation};
kBytecodeImplementation
};
enum StackCheckFlag {
kNoStackLimitCheck = false,
kCheckStackLimit = true
};
RegExpMacroAssembler();
virtual ~RegExpMacroAssembler();
// The maximal number of pushes between stack checks. Users must supply
// kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck)
// at least once for every stack_limit() pushes that are executed.
virtual int stack_limit_slack() = 0;
virtual void AdvanceCurrentPosition(int by) = 0; // Signed cp change.
virtual void AdvanceRegister(int reg, int by) = 0; // r[reg] += by.
// Continues execution from the position pushed on the top of the backtrack
// stack by an earlier PushBacktrack(Label*).
virtual void Backtrack() = 0;
virtual void Bind(Label* label) = 0;
// Check the current character against a bitmap. The range of the current
......@@ -145,9 +156,12 @@ class RegExpMacroAssembler {
int characters = 1) = 0;
virtual void PopCurrentPosition() = 0;
virtual void PopRegister(int register_index) = 0;
// Pushes the label on the backtrack stack, so that a following Backtrack
// will go to this label. Always checks the backtrack stack limit.
virtual void PushBacktrack(Label* label) = 0;
virtual void PushCurrentPosition() = 0;
virtual void PushRegister(int register_index) = 0;
virtual void PushRegister(int register_index,
StackCheckFlag check_stack_limit) = 0;
virtual void ReadCurrentPositionFromRegister(int reg) = 0;
virtual void ReadStackPointerFromRegister(int reg) = 0;
virtual void SetRegister(int register_index, int to) = 0;
......
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h"
#include "top.h"
#include "regexp-stack.h"
namespace v8 { namespace internal {
RegExpStack::RegExpStack() {
// Initialize, if not already initialized.
RegExpStack::EnsureCapacity(0);
}
RegExpStack::~RegExpStack() {
// Reset the buffer if it has grown.
RegExpStack::Reset();
}
char* RegExpStack::ArchiveStack(char* to) {
size_t size = sizeof(thread_local_);
memcpy(reinterpret_cast<void*>(to),
&thread_local_,
size);
thread_local_ = ThreadLocal();
return to + size;
}
char* RegExpStack::RestoreStack(char* from) {
size_t size = sizeof(thread_local_);
memcpy(&thread_local_, reinterpret_cast<void*>(from), size);
return from + size;
}
void RegExpStack::Reset() {
if (thread_local_.memory_size_ > kMinimumStackSize) {
DeleteArray(thread_local_.memory_);
thread_local_ = ThreadLocal();
}
}
Address RegExpStack::EnsureCapacity(size_t size) {
if (size > kMaximumStackSize) return NULL;
if (size < kMinimumStackSize) size = kMinimumStackSize;
if (thread_local_.memory_size_ < size) {
Address new_memory = NewArray<byte>(size);
if (thread_local_.memory_size_ > 0) {
// Copy original memory into top of new memory.
memcpy(reinterpret_cast<void*>(
new_memory + size - thread_local_.memory_size_),
reinterpret_cast<void*>(thread_local_.memory_),
thread_local_.memory_size_);
DeleteArray(thread_local_.memory_);
}
thread_local_.memory_ = new_memory;
thread_local_.memory_size_ = size;
thread_local_.limit_ = new_memory + kStackLimitSlack * kPointerSize;
}
return thread_local_.memory_ + thread_local_.memory_size_;
}
RegExpStack::ThreadLocal RegExpStack::thread_local_;
}} // namespace v8::internal
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef REGEXP_STACK_H_
#define REGEXP_STACK_H_
namespace v8 { namespace internal {
// 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 RegExpStack {
public:
// Number of allocated locations on the stack below the limit.
// No sequence of pushes must be longer that this without doing a stack-limit
// 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_top() {
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_; }
// 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_); }
// 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);
// Thread local archiving.
static size_t ArchiveSpacePerThread() { return sizeof(thread_local_); }
static char* ArchiveStack(char* to);
static char* RestoreStack(char* from);
private:
// Artificial limit used when no memory has been allocated.
static const uint32_t kMemoryTop = 0xffffffff;
// Minimal size of allocated stack area.
static const size_t kMinimumStackSize = 1 * KB;
// Maximal size of allocated stack area.
static const size_t kMaximumStackSize = 256 * KB;
// Structure holding the allocated memory, size and limit.
struct ThreadLocal {
ThreadLocal()
: memory_(NULL),
memory_size_(0),
limit_(reinterpret_cast<Address>(kMemoryTop)) {}
// If memory_size_ > 0 then memory_ must be non-NULL.
Address memory_;
size_t memory_size_;
Address limit_;
};
// 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_;
};
}} // namespace v8::internal
#endif /* REGEXP_STACK_H_ */
......@@ -31,6 +31,7 @@
#include "debug.h"
#include "execution.h"
#include "v8threads.h"
#include "regexp-stack.h"
namespace v8 {
......@@ -125,6 +126,7 @@ bool ThreadManager::RestoreThread() {
from = Top::RestoreThread(from);
from = Debug::RestoreDebug(from);
from = StackGuard::RestoreStackGuard(from);
from = RegExpStack::RestoreStack(from);
Thread::SetThreadLocal(thread_state_key, NULL);
state->Unlink();
state->LinkInto(ThreadState::FREE_LIST);
......@@ -149,7 +151,8 @@ static int ArchiveSpacePerThread() {
return HandleScopeImplementer::ArchiveSpacePerThread() +
Top::ArchiveSpacePerThread() +
Debug::ArchiveSpacePerThread() +
StackGuard::ArchiveSpacePerThread();
StackGuard::ArchiveSpacePerThread() +
RegExpStack::ArchiveSpacePerThread();
}
......@@ -230,6 +233,7 @@ void ThreadManager::EagerlyArchiveThread() {
to = Top::ArchiveThread(to);
to = Debug::ArchiveDebug(to);
to = StackGuard::ArchiveStackGuard(to);
to = RegExpStack::ArchiveStack(to);
lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
lazily_archived_thread_state_ = NULL;
}
......
This diff is collapsed.
......@@ -300,6 +300,10 @@
RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h"
>
</File>
<File
RelativePath="..\..\src\regexp-stack.h"
>
</File>
<File
RelativePath="..\..\src\assembler.cc"
>
......@@ -744,6 +748,10 @@
RelativePath="..\..\src\regexp-macro-assembler-tracer.h"
>
</File>
<File
RelativePath="..\..\src\regexp-stack.cc"
>
</File>
<File
RelativePath="..\..\src\rewriter.cc"
>
......
......@@ -296,6 +296,10 @@
RelativePath="..\..\src\assembler-arm.h"
>
</File>
<File
RelativePath="..\..\src\regexp-stack.h"
>
</File>
<File
RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h"
>
......@@ -748,6 +752,10 @@
RelativePath="..\..\src\regexp-macro-assembler-tracer.h"
>
</File>
<File
RelativePath="..\..\src\regexp-stack.cc"
>
</File>
<File
RelativePath="..\..\src\rewriter.cc"
>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment