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 = { ...@@ -44,11 +44,11 @@ SOURCES = {
'interpreter-irregexp.cc', 'jsregexp.cc', 'log.cc', 'mark-compact.cc', 'interpreter-irregexp.cc', 'jsregexp.cc', 'log.cc', 'mark-compact.cc',
'messages.cc', 'objects.cc', 'parser.cc', 'property.cc', 'messages.cc', 'objects.cc', 'parser.cc', 'property.cc',
'regexp-macro-assembler.cc', 'regexp-macro-assembler-irregexp.cc', 'regexp-macro-assembler.cc', 'regexp-macro-assembler-irregexp.cc',
'rewriter.cc', 'runtime.cc', 'scanner.cc', 'scopeinfo.cc', 'scopes.cc', 'regexp-stack.cc', 'rewriter.cc', 'runtime.cc', 'scanner.cc',
'serialize.cc', 'snapshot-common.cc', 'spaces.cc', 'string-stream.cc', 'scopeinfo.cc', 'scopes.cc', 'serialize.cc', 'snapshot-common.cc',
'stub-cache.cc', 'token.cc', 'top.cc', 'unicode.cc', 'usage-analyzer.cc', 'spaces.cc', 'string-stream.cc', 'stub-cache.cc', 'token.cc', 'top.cc',
'utils.cc', 'v8-counters.cc', 'v8.cc', 'v8threads.cc', 'variables.cc', 'unicode.cc', 'usage-analyzer.cc', 'utils.cc', 'v8-counters.cc', 'v8.cc',
'zone.cc' 'v8threads.cc', 'variables.cc', 'zone.cc'
], ],
'arch:arm': ['assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc', 'arch:arm': ['assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc',
'cpu-arm.cc', 'debug-arm.cc', 'disasm-arm.cc', 'frames-arm.cc', 'cpu-arm.cc', 'debug-arm.cc', 'disasm-arm.cc', 'frames-arm.cc',
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "runtime.h" #include "runtime.h"
#include "serialize.h" #include "serialize.h"
#include "stub-cache.h" #include "stub-cache.h"
#include "regexp-stack.h"
namespace v8 { namespace internal { namespace v8 { namespace internal {
...@@ -551,6 +552,11 @@ ExternalReference ExternalReference::address_of_stack_guard_limit() { ...@@ -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() { ExternalReference ExternalReference::debug_break() {
return ExternalReference(FUNCTION_ADDR(Debug::Break)); return ExternalReference(FUNCTION_ADDR(Debug::Break));
} }
......
...@@ -442,6 +442,9 @@ class ExternalReference BASE_EMBEDDED { ...@@ -442,6 +442,9 @@ class ExternalReference BASE_EMBEDDED {
// Static variable StackGuard::address_of_limit() // Static variable StackGuard::address_of_limit()
static ExternalReference address_of_stack_guard_limit(); static ExternalReference address_of_stack_guard_limit();
// Static variable RegExpStack::limit_address()
static ExternalReference address_of_regexp_stack_limit();
// Function Debug::Break() // Function Debug::Break()
static ExternalReference debug_break(); static ExternalReference debug_break();
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "regexp-macro-assembler.h" #include "regexp-macro-assembler.h"
#include "regexp-macro-assembler-tracer.h" #include "regexp-macro-assembler-tracer.h"
#include "regexp-macro-assembler-irregexp.h" #include "regexp-macro-assembler-irregexp.h"
#include "regexp-stack.h"
#ifdef ARM #ifdef ARM
#include "regexp-macro-assembler-arm.h" #include "regexp-macro-assembler-arm.h"
...@@ -913,7 +914,7 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp, ...@@ -913,7 +914,7 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
} }
res = RegExpMacroAssemblerIA32::Execute( res = RegExpMacroAssemblerIA32::Execute(
*code, *code,
&address, const_cast<Address*>(&address),
start_offset << char_size_shift, start_offset << char_size_shift,
end_offset << char_size_shift, end_offset << char_size_shift,
offsets_vector, offsets_vector,
...@@ -925,7 +926,7 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp, ...@@ -925,7 +926,7 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
int byte_offset = char_address - reinterpret_cast<Address>(*subject); int byte_offset = char_address - reinterpret_cast<Address>(*subject);
res = RegExpMacroAssemblerIA32::Execute( res = RegExpMacroAssemblerIA32::Execute(
*code, *code,
subject.location(), reinterpret_cast<Address*>(subject.location()),
byte_offset + (start_offset << char_size_shift), byte_offset + (start_offset << char_size_shift),
byte_offset + (end_offset << char_size_shift), byte_offset + (end_offset << char_size_shift),
offsets_vector, offsets_vector,
...@@ -1347,8 +1348,18 @@ int GenerationVariant::FindAffectedRegisters(OutSet* affected_registers) { ...@@ -1347,8 +1348,18 @@ int GenerationVariant::FindAffectedRegisters(OutSet* affected_registers) {
void GenerationVariant::PushAffectedRegisters(RegExpMacroAssembler* assembler, void GenerationVariant::PushAffectedRegisters(RegExpMacroAssembler* assembler,
int max_register, int max_register,
OutSet& affected_registers) { OutSet& affected_registers) {
for (int reg = 0; reg <= max_register; reg++) { // Stay safe and check every half times the limit.
if (affected_registers.Get(reg)) assembler->PushRegister(reg); // (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 { ...@@ -38,6 +38,7 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
RegExpMacroAssemblerIA32(Mode mode, int registers_to_save); RegExpMacroAssemblerIA32(Mode mode, int registers_to_save);
virtual ~RegExpMacroAssemblerIA32(); virtual ~RegExpMacroAssemblerIA32();
virtual int stack_limit_slack();
virtual void AdvanceCurrentPosition(int by); virtual void AdvanceCurrentPosition(int by);
virtual void AdvanceRegister(int reg, int by); virtual void AdvanceRegister(int reg, int by);
virtual void Backtrack(); virtual void Backtrack();
...@@ -53,6 +54,8 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -53,6 +54,8 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
int cp_offset, int cp_offset,
Label* on_failure, Label* on_failure,
bool check_end_of_string); 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 CheckGreedyLoop(Label* on_tos_equals_current_position);
virtual void CheckNotAtStart(Label* on_not_at_start); virtual void CheckNotAtStart(Label* on_not_at_start);
virtual void CheckNotBackReference(int start_reg, Label* on_no_match); virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
...@@ -96,7 +99,8 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -96,7 +99,8 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
virtual void PopRegister(int register_index); virtual void PopRegister(int register_index);
virtual void PushBacktrack(Label* label); virtual void PushBacktrack(Label* label);
virtual void PushCurrentPosition(); 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 ReadCurrentPositionFromRegister(int reg);
virtual void ReadStackPointerFromRegister(int reg); virtual void ReadStackPointerFromRegister(int reg);
virtual void SetRegister(int register_index, int to); virtual void SetRegister(int register_index, int to);
...@@ -104,26 +108,15 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -104,26 +108,15 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset); virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
virtual void WriteStackPointerToRegister(int reg); virtual void WriteStackPointerToRegister(int reg);
template <typename T> static Result Execute(Code* code,
static inline Result Execute(Code* code, Address* input,
T** input, int start_offset,
int start_offset, int end_offset,
int end_offset, int* output,
int* output, bool at_start);
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);
}
private: 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_ebx = sizeof(uint32_t);
static const int kBackup_edi = 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); static const int kBackup_esi = kBackup_edi + sizeof(uint32_t);
...@@ -133,24 +126,30 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -133,24 +126,30 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
static const int kInputEndOffset = kInputStartOffset + sizeof(uint32_t); static const int kInputEndOffset = kInputStartOffset + sizeof(uint32_t);
static const int kRegisterOutput = kInputEndOffset + sizeof(uint32_t); static const int kRegisterOutput = kInputEndOffset + sizeof(uint32_t);
static const int kAtStart = kRegisterOutput + sizeof(uint32_t); static const int kAtStart = kRegisterOutput + sizeof(uint32_t);
static const int kStackHighEnd = kAtStart + sizeof(uint32_t);
// Initial size of code buffer. // Initial size of code buffer.
static const size_t kRegExpCodeSize = 1024; static const size_t kRegExpCodeSize = 1024;
// Initial size of constant buffers allocated during compilation. // Initial size of constant buffers allocated during compilation.
static const int kRegExpConstantsSize = 256; 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; static const int kMaxInlineStringTests = 32;
// Compares two-byte strings case insensitively. // Compares two-byte strings case insensitively.
// Called from generated RegExp code.
static int CaseInsensitiveCompareUC16(uc16** buffer, static int CaseInsensitiveCompareUC16(uc16** buffer,
int byte_offset1, int byte_offset1,
int byte_offset2, int byte_offset2,
size_t byte_length); 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 // Check whether preemption has been requested.
// (and checks if we have hit the stack limit too). void CheckPreemption();
// Check whether we are exceeding the stack limit on the backtrack stack.
void CheckStackLimit(); void CheckStackLimit();
// Called from RegExp if the stack-guard is triggered. // Called from RegExp if the stack-guard is triggered.
...@@ -158,6 +157,12 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -158,6 +157,12 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
// returning. // returning.
static int CheckStackGuardState(Address return_address, Code* re_code); 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 // Checks whether the given offset from the current position is before
// the end of the string. // the end of the string.
void CheckPosition(int cp_offset, Label* on_outside_input); void CheckPosition(int cp_offset, Label* on_outside_input);
...@@ -166,14 +171,18 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -166,14 +171,18 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
Operand register_location(int register_index); Operand register_location(int register_index);
// The register containing the current character after LoadCurrentCharacter. // 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) // 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 // Equivalent to a conditional branch to the label, unless the label
// is NULL, in which case it is a conditional Backtrack. // 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) // Load the address of a "constant buffer" (a slice of a byte array)
// into a register. The address is computed from the ByteArray* address // into a register. The address is computed from the ByteArray* address
...@@ -182,30 +191,50 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -182,30 +191,50 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
// Call and return internally in the generated code in a way that // 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) // is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
void SafeCall(Label* to); inline void SafeCall(Label* to);
void SafeReturn(); 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. // 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], // 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. // 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 // Calls a C function and cleans up the space for arguments allocated
// by FrameAlign. The called function is not allowed to trigger a garbage // by FrameAlign. The called function is not allowed to trigger a garbage
// collection, since that might move the code and invalidate the return // collection, since that might move the code and invalidate the return
// address // address (unless this is somehow accounted for).
void CallCFunction(Address function_address, int num_arguments); inline void CallCFunction(Address function_address, int num_arguments);
MacroAssembler* masm_; MacroAssembler* masm_;
// Constant buffer provider. Allocates external storage for storing // Constant buffer provider. Allocates external storage for storing
// constants. // constants.
ByteArrayProvider constants_; ByteArrayProvider constants_;
// Which mode to generate code for (ASCII or UTF16). // Which mode to generate code for (ASCII or UTF16).
Mode mode_; Mode mode_;
// One greater than maximal register index actually used. // One greater than maximal register index actually used.
int num_registers_; int num_registers_;
// Number of registers to output at the end (the saved registers // Number of registers to output at the end (the saved registers
// are always 0..num_saved_registers_-1) // are always 0..num_saved_registers_-1)
int num_saved_registers_; int num_saved_registers_;
// Labels used internally. // Labels used internally.
Label entry_label_; Label entry_label_;
Label start_label_; Label start_label_;
...@@ -213,6 +242,8 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler { ...@@ -213,6 +242,8 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
Label backtrack_label_; Label backtrack_label_;
Label exit_label_; Label exit_label_;
Label check_preempt_label_; Label check_preempt_label_;
Label stack_overflow_label_;
// Handle used to represent the generated code object itself. // Handle used to represent the generated code object itself.
Handle<Object> self_; Handle<Object> self_;
}; };
......
...@@ -89,7 +89,9 @@ void RegExpMacroAssemblerIrregexp::PopRegister(int register_index) { ...@@ -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); ASSERT(register_index >= 0);
Emit(BC_PUSH_REGISTER); Emit(BC_PUSH_REGISTER);
Emit(register_index); Emit(register_index);
......
...@@ -48,6 +48,8 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler { ...@@ -48,6 +48,8 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
// upon destruction of the assembler. // upon destruction of the assembler.
explicit RegExpMacroAssemblerIrregexp(Vector<byte>); explicit RegExpMacroAssemblerIrregexp(Vector<byte>);
virtual ~RegExpMacroAssemblerIrregexp(); 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 Bind(Label* label);
virtual void EmitOrLink(Label* label); virtual void EmitOrLink(Label* label);
virtual void AdvanceCurrentPosition(int by); // Signed cp change. virtual void AdvanceCurrentPosition(int by); // Signed cp change.
...@@ -59,7 +61,8 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler { ...@@ -59,7 +61,8 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
virtual void Succeed(); virtual void Succeed();
virtual void Fail(); virtual void Fail();
virtual void PopRegister(int register_index); 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 AdvanceRegister(int reg, int by); // r[reg] += by.
virtual void SetRegister(int register_index, int to); virtual void SetRegister(int register_index, int to);
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset); virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
......
...@@ -95,7 +95,8 @@ void RegExpMacroAssemblerTracer::GoTo(Label* label) { ...@@ -95,7 +95,8 @@ void RegExpMacroAssemblerTracer::GoTo(Label* label) {
void RegExpMacroAssemblerTracer::PushBacktrack(Label* label) { void RegExpMacroAssemblerTracer::PushBacktrack(Label* label) {
PrintF(" PushBacktrack(label[%08x]);\n", label); PrintF(" PushBacktrack(label[%08x]);\n",
label);
assembler_->PushBacktrack(label); assembler_->PushBacktrack(label);
} }
...@@ -118,9 +119,13 @@ void RegExpMacroAssemblerTracer::PopRegister(int register_index) { ...@@ -118,9 +119,13 @@ void RegExpMacroAssemblerTracer::PopRegister(int register_index) {
} }
void RegExpMacroAssemblerTracer::PushRegister(int register_index) { void RegExpMacroAssemblerTracer::PushRegister(
PrintF(" PushRegister(register=%d);\n", register_index); int register_index,
assembler_->PushRegister(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 { ...@@ -35,6 +35,7 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
public: public:
explicit RegExpMacroAssemblerTracer(RegExpMacroAssembler* assembler); explicit RegExpMacroAssemblerTracer(RegExpMacroAssembler* assembler);
virtual ~RegExpMacroAssemblerTracer(); virtual ~RegExpMacroAssemblerTracer();
virtual int stack_limit_slack() { return assembler_->stack_limit_slack(); }
virtual void AdvanceCurrentPosition(int by); // Signed cp change. virtual void AdvanceCurrentPosition(int by); // Signed cp change.
virtual void AdvanceRegister(int reg, int by); // r[reg] += by. virtual void AdvanceRegister(int reg, int by); // r[reg] += by.
...@@ -98,7 +99,8 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler { ...@@ -98,7 +99,8 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
virtual void PopRegister(int register_index); virtual void PopRegister(int register_index);
virtual void PushBacktrack(Label* label); virtual void PushBacktrack(Label* label);
virtual void PushCurrentPosition(); 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 ReadCurrentPositionFromRegister(int reg);
virtual void ReadStackPointerFromRegister(int reg); virtual void ReadStackPointerFromRegister(int reg);
virtual void SetRegister(int register_index, int to); virtual void SetRegister(int register_index, int to);
......
...@@ -68,10 +68,11 @@ ArraySlice ByteArrayProvider::GetBuffer(unsigned int size, ...@@ -68,10 +68,11 @@ ArraySlice ByteArrayProvider::GetBuffer(unsigned int size,
return ArraySlice(current_byte_array_, free_offset); return ArraySlice(current_byte_array_, free_offset);
} }
template <typename T> template <typename T>
ArraySlice ByteArrayProvider::GetBuffer(Vector<T> values) { ArraySlice ByteArrayProvider::GetBuffer(Vector<T> values) {
ArraySlice slice = GetBuffer(values.length(), sizeof(T)); ArraySlice slice = GetBuffer(values.length(), sizeof(T));
memcpy(slice.location(), values.start(), values.length() * sizeof(T)); memcpy(slice.location(), values.start(), values.length() * sizeof(T));
return slice; return slice;
} }
} } } } // namespace v8::internal
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
namespace v8 { namespace internal { namespace v8 { namespace internal {
struct DisjunctDecisionRow { struct DisjunctDecisionRow {
RegExpCharacterClass cc; RegExpCharacterClass cc;
Label* on_match; Label* on_match;
...@@ -42,12 +41,24 @@ class RegExpMacroAssembler { ...@@ -42,12 +41,24 @@ class RegExpMacroAssembler {
enum IrregexpImplementation { enum IrregexpImplementation {
kIA32Implementation, kIA32Implementation,
kARMImplementation, kARMImplementation,
kBytecodeImplementation}; kBytecodeImplementation
};
enum StackCheckFlag {
kNoStackLimitCheck = false,
kCheckStackLimit = true
};
RegExpMacroAssembler(); RegExpMacroAssembler();
virtual ~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 AdvanceCurrentPosition(int by) = 0; // Signed cp change.
virtual void AdvanceRegister(int reg, int by) = 0; // r[reg] += by. 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 Backtrack() = 0;
virtual void Bind(Label* label) = 0; virtual void Bind(Label* label) = 0;
// Check the current character against a bitmap. The range of the current // Check the current character against a bitmap. The range of the current
...@@ -145,9 +156,12 @@ class RegExpMacroAssembler { ...@@ -145,9 +156,12 @@ class RegExpMacroAssembler {
int characters = 1) = 0; int characters = 1) = 0;
virtual void PopCurrentPosition() = 0; virtual void PopCurrentPosition() = 0;
virtual void PopRegister(int register_index) = 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 PushBacktrack(Label* label) = 0;
virtual void PushCurrentPosition() = 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 ReadCurrentPositionFromRegister(int reg) = 0;
virtual void ReadStackPointerFromRegister(int reg) = 0; virtual void ReadStackPointerFromRegister(int reg) = 0;
virtual void SetRegister(int register_index, int to) = 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 @@ ...@@ -31,6 +31,7 @@
#include "debug.h" #include "debug.h"
#include "execution.h" #include "execution.h"
#include "v8threads.h" #include "v8threads.h"
#include "regexp-stack.h"
namespace v8 { namespace v8 {
...@@ -125,6 +126,7 @@ bool ThreadManager::RestoreThread() { ...@@ -125,6 +126,7 @@ bool ThreadManager::RestoreThread() {
from = Top::RestoreThread(from); from = Top::RestoreThread(from);
from = Debug::RestoreDebug(from); from = Debug::RestoreDebug(from);
from = StackGuard::RestoreStackGuard(from); from = StackGuard::RestoreStackGuard(from);
from = RegExpStack::RestoreStack(from);
Thread::SetThreadLocal(thread_state_key, NULL); Thread::SetThreadLocal(thread_state_key, NULL);
state->Unlink(); state->Unlink();
state->LinkInto(ThreadState::FREE_LIST); state->LinkInto(ThreadState::FREE_LIST);
...@@ -149,7 +151,8 @@ static int ArchiveSpacePerThread() { ...@@ -149,7 +151,8 @@ static int ArchiveSpacePerThread() {
return HandleScopeImplementer::ArchiveSpacePerThread() + return HandleScopeImplementer::ArchiveSpacePerThread() +
Top::ArchiveSpacePerThread() + Top::ArchiveSpacePerThread() +
Debug::ArchiveSpacePerThread() + Debug::ArchiveSpacePerThread() +
StackGuard::ArchiveSpacePerThread(); StackGuard::ArchiveSpacePerThread() +
RegExpStack::ArchiveSpacePerThread();
} }
...@@ -230,6 +233,7 @@ void ThreadManager::EagerlyArchiveThread() { ...@@ -230,6 +233,7 @@ void ThreadManager::EagerlyArchiveThread() {
to = Top::ArchiveThread(to); to = Top::ArchiveThread(to);
to = Debug::ArchiveDebug(to); to = Debug::ArchiveDebug(to);
to = StackGuard::ArchiveStackGuard(to); to = StackGuard::ArchiveStackGuard(to);
to = RegExpStack::ArchiveStack(to);
lazily_archived_thread_.Initialize(ThreadHandle::INVALID); lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
lazily_archived_thread_state_ = NULL; lazily_archived_thread_state_ = NULL;
} }
......
This diff is collapsed.
...@@ -300,6 +300,10 @@ ...@@ -300,6 +300,10 @@
RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h" RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h"
> >
</File> </File>
<File
RelativePath="..\..\src\regexp-stack.h"
>
</File>
<File <File
RelativePath="..\..\src\assembler.cc" RelativePath="..\..\src\assembler.cc"
> >
...@@ -744,6 +748,10 @@ ...@@ -744,6 +748,10 @@
RelativePath="..\..\src\regexp-macro-assembler-tracer.h" RelativePath="..\..\src\regexp-macro-assembler-tracer.h"
> >
</File> </File>
<File
RelativePath="..\..\src\regexp-stack.cc"
>
</File>
<File <File
RelativePath="..\..\src\rewriter.cc" RelativePath="..\..\src\rewriter.cc"
> >
......
...@@ -296,6 +296,10 @@ ...@@ -296,6 +296,10 @@
RelativePath="..\..\src\assembler-arm.h" RelativePath="..\..\src\assembler-arm.h"
> >
</File> </File>
<File
RelativePath="..\..\src\regexp-stack.h"
>
</File>
<File <File
RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h" RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h"
> >
...@@ -748,6 +752,10 @@ ...@@ -748,6 +752,10 @@
RelativePath="..\..\src\regexp-macro-assembler-tracer.h" RelativePath="..\..\src\regexp-macro-assembler-tracer.h"
> >
</File> </File>
<File
RelativePath="..\..\src\regexp-stack.cc"
>
</File>
<File <File
RelativePath="..\..\src\rewriter.cc" 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