Commit 3b968e02 authored by lrn@chromium.org's avatar lrn@chromium.org

Preemption code for irregexp-native-ia32. Regexps can not only succeede or

fail, but also report a thrown exception.


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@974 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 09e3c761
......@@ -152,6 +152,12 @@ Immediate::Immediate(const char* s) {
}
Immediate::Immediate(Label *internal_offset) {
x_ = reinterpret_cast<int32_t>(internal_offset);
rmode_ = RelocInfo::INTERNAL_REFERENCE;
}
Immediate::Immediate(Handle<Object> handle) {
// Verify all Objects referred by code are NOT in new space.
Object* obj = *handle;
......@@ -200,11 +206,27 @@ void Assembler::emit(uint32_t x, RelocInfo::Mode rmode) {
void Assembler::emit(const Immediate& x) {
if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) {
Label* label = reinterpret_cast<Label*>(x.x_);
emit_code_relative_offset(label);
return;
}
if (x.rmode_ != RelocInfo::NONE) RecordRelocInfo(x.rmode_);
emit(x.x_);
}
void Assembler::emit_code_relative_offset(Label* label) {
if (label->is_bound()) {
int32_t pos;
pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
emit(pos);
} else {
emit_disp(label, Displacement::CODE_RELATIVE);
}
}
void Assembler::emit_w(const Immediate& x) {
ASSERT(x.rmode_ == RelocInfo::NONE);
uint16_t value = static_cast<uint16_t>(x.x_);
......
......@@ -420,29 +420,6 @@ void Assembler::push(const Operand& src) {
}
void Assembler::push(Label* label, RelocInfo::Mode reloc_mode) {
ASSERT_NOT_NULL(label);
EnsureSpace ensure_space(this);
last_pc_ = pc_;
// If reloc_mode == NONE, the label is stored as buffer relative.
ASSERT(reloc_mode == RelocInfo::NONE);
if (label->is_bound()) {
// Index of position relative to Code Object-pointer.
int rel_pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
if (rel_pos >= 0 && rel_pos < 256) {
EMIT(0x6a);
EMIT(rel_pos);
} else {
EMIT(0x68);
emit(rel_pos);
}
} else {
EMIT(0x68);
emit_disp(label, Displacement::CODE_RELATIVE);
}
}
void Assembler::pop(Register dst) {
ASSERT(reloc_info_writer.last_pc() != NULL);
if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
......
......@@ -185,6 +185,10 @@ class Immediate BASE_EMBEDDED {
inline explicit Immediate(Handle<Object> handle);
inline explicit Immediate(Smi* value);
static Immediate CodeRelativeOffset(Label* label) {
return Immediate(label);
}
bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; }
bool is_int8() const {
return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE;
......@@ -194,6 +198,8 @@ class Immediate BASE_EMBEDDED {
}
private:
inline explicit Immediate(Label* value);
int x_;
RelocInfo::Mode rmode_;
......@@ -731,24 +737,6 @@ class Assembler : public Malloced {
private:
// Code buffer:
// The buffer into which code and relocation info are generated.
byte* buffer_;
int buffer_size_;
// True if the assembler owns the buffer, false if buffer is external.
bool own_buffer_;
// code generation
byte* pc_; // the program counter; moves forward
RelocInfoWriter reloc_info_writer;
// push-pop elimination
byte* last_pc_;
// source position information
int last_position_;
int last_statement_position_;
byte* addr_at(int pos) { return buffer_ + pos; }
byte byte_at(int pos) { return buffer_[pos]; }
uint32_t long_at(int pos) {
......@@ -766,6 +754,9 @@ class Assembler : public Malloced {
inline void emit(const Immediate& x);
inline void emit_w(const Immediate& x);
// Emit the code-object-relative offset of the label's position
inline void emit_code_relative_offset(Label* label);
// instruction generation
void emit_arith_b(int op1, int op2, Register dst, int imm8);
......@@ -794,6 +785,24 @@ class Assembler : public Malloced {
friend class CodePatcher;
friend class EnsureSpace;
// Code buffer:
// The buffer into which code and relocation info are generated.
byte* buffer_;
int buffer_size_;
// True if the assembler owns the buffer, false if buffer is external.
bool own_buffer_;
// code generation
byte* pc_; // the program counter; moves forward
RelocInfoWriter reloc_info_writer;
// push-pop elimination
byte* last_pc_;
// source position information
int last_position_;
int last_statement_position_;
};
......
......@@ -38,6 +38,9 @@
#include "simulator-ia32.h"
#endif
#include "debug.h"
#include "v8threads.h"
namespace v8 { namespace internal {
......@@ -500,6 +503,69 @@ Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
}
static Object* RuntimePreempt() {
// Clear the preempt request flag.
StackGuard::Continue(PREEMPT);
ContextSwitcher::PreemptionReceived();
{
v8::Unlocker unlocker;
Thread::YieldCPU();
}
return Heap::undefined_value();
}
Object* Execution::DebugBreakHelper() {
// Just continue if breaks are disabled.
if (Debug::disable_break()) {
return Heap::undefined_value();
}
// Don't break in system functions. If the current function is
// either in the builtins object of some context or is in the debug
// context just return with the debug break stack guard active.
JavaScriptFrameIterator it;
JavaScriptFrame* frame = it.frame();
Object* fun = frame->function();
if (fun->IsJSFunction()) {
GlobalObject* global = JSFunction::cast(fun)->context()->global();
if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
return Heap::undefined_value();
}
}
// Clear the debug request flag.
StackGuard::Continue(DEBUGBREAK);
HandleScope scope;
// Enter the debugger. Just continue if we fail to enter the debugger.
EnterDebugger debugger;
if (debugger.FailedToEnter()) {
return Heap::undefined_value();
}
// Notify the debug event listeners.
Debugger::OnDebugBreak(Factory::undefined_value());
// Return to continue execution.
return Heap::undefined_value();
}
Object* Execution::HandleStackGuardInterrupt() {
if (StackGuard::IsDebugBreak()) DebugBreakHelper();
if (StackGuard::IsPreempted()) RuntimePreempt();
if (StackGuard::IsInterrupted()) {
// interrupt
StackGuard::Continue(INTERRUPT);
return Top::StackOverflow();
}
return Heap::undefined_value();
}
// --- G C E x t e n s i o n ---
const char* GCExtension::kSource = "native function gc();";
......
......@@ -118,6 +118,12 @@ class Execution : public AllStatic {
Handle<Object> pos,
Handle<Object> is_global);
static Object* DebugBreakHelper();
// If the stack guard is triggered, but it is not an actual
// stack overflow, then handle the interruption accordingly.
static Object* HandleStackGuardInterrupt();
// Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as functions.
static Handle<Object> GetFunctionDelegate(Handle<Object> object);
......
......@@ -309,7 +309,7 @@ Handle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp,
return AtomExec(regexp, subject, index);
case JSRegExp::IRREGEXP: {
Handle<Object> result = IrregexpExec(regexp, subject, index);
if (!result.is_null()) {
if (!result.is_null() || Top::has_pending_exception()) {
return result;
}
// We couldn't handle the regexp using Irregexp, so fall back
......@@ -339,12 +339,13 @@ Handle<Object> RegExpImpl::ExecGlobal(Handle<JSRegExp> regexp,
return AtomExecGlobal(regexp, subject);
case JSRegExp::IRREGEXP: {
Handle<Object> result = IrregexpExecGlobal(regexp, subject);
if (!result.is_null()) {
if (!result.is_null() || Top::has_pending_exception()) {
return result;
}
// We couldn't handle the regexp using Irregexp, so fall back
// on JSCRE.
// Reset the JSRegExp to use JSCRE.
// Empty handle as result but no exception thrown means that
// the regexp contains features not yet handled by the irregexp
// compiler.
// We have to fall back on JSCRE. Reset the JSRegExp to use JSCRE.
JscrePrepare(regexp,
Handle<String>(regexp->Pattern()),
regexp->GetFlags());
......@@ -683,6 +684,12 @@ Handle<Object> RegExpImpl::JscreExecGlobal(Handle<JSRegExp> regexp,
// Irregexp implementation.
// Retrieves a compiled version of the regexp for either ASCII or non-ASCII
// strings. If the compiled version doesn't already exist, it is compiled
// from the source pattern.
// Irregexp is not feature complete yet. If there is something in the
// regexp that the compiler cannot currently handle, an empty
// handle is returned, but no exception is thrown.
static Handle<FixedArray> GetCompiledIrregexp(Handle<JSRegExp> re,
bool is_ascii) {
ASSERT(re->DataAt(JSRegExp::kIrregexpDataIndex)->IsFixedArray());
......@@ -912,6 +919,8 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
bool is_ascii = flatshape.IsAsciiRepresentation();
int char_size_shift = is_ascii ? 0 : 1;
RegExpMacroAssemblerIA32::Result res;
if (flatshape.IsExternal()) {
const byte* address;
if (is_ascii) {
......@@ -921,7 +930,7 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
ExternalTwoByteString* ext = ExternalTwoByteString::cast(*subject);
address = reinterpret_cast<const byte*>(ext->resource()->data());
}
rc = RegExpMacroAssemblerIA32::Execute(
res = RegExpMacroAssemblerIA32::Execute(
*code,
&address,
start_offset << char_size_shift,
......@@ -933,7 +942,7 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
is_ascii ? SeqAsciiString::cast(*subject)->GetCharsAddress()
: SeqTwoByteString::cast(*subject)->GetCharsAddress();
int byte_offset = char_address - reinterpret_cast<Address>(*subject);
rc = RegExpMacroAssemblerIA32::Execute(
res = RegExpMacroAssemblerIA32::Execute(
*code,
subject.location(),
byte_offset + (start_offset << char_size_shift),
......@@ -942,6 +951,12 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
previous_index == 0);
}
if (res == RegExpMacroAssemblerIA32::EXCEPTION) {
ASSERT(Top::has_pending_exception());
return Handle<Object>::null();
}
rc = (res == RegExpMacroAssemblerIA32::SUCCESS);
if (rc) {
// Capture values are relative to start_offset only.
for (int i = 0; i < offsets_vector_length; i++) {
......
......@@ -107,6 +107,7 @@ RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() {
start_label_.Unuse();
success_label_.Unuse();
exit_label_.Unuse();
check_preempt_label_.Unuse();
}
......@@ -126,9 +127,7 @@ void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) {
void RegExpMacroAssemblerIA32::Backtrack() {
__ pop(ecx);
__ add(Operand(ecx), Immediate(self_));
__ jmp(Operand(ecx));
SafeReturn();
}
......@@ -215,6 +214,7 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
constant_buffer.at<char>(i) = static_cast<char>(str[i]);
}
} else {
ASSERT(mode_ == UC16);
memcpy(constant_buffer.location(),
str.start(),
str.length() * sizeof(uc16));
......@@ -292,21 +292,12 @@ void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
__ pop(esi);
__ sub(edi, Operand(esi));
} else {
// store state
ASSERT(mode_ == UC16);
__ push(esi);
__ push(edi);
__ push(ecx);
// align stack
int frameAlignment = OS::ActivationFrameAlignment();
if (frameAlignment != 0) {
__ mov(ebx, esp);
__ sub(Operand(esp), Immediate(5 * kPointerSize)); // args + esp.
ASSERT(IsPowerOf2(frameAlignment));
__ and_(esp, -frameAlignment);
__ mov(Operand(esp, 4 * kPointerSize), ebx);
} else {
__ sub(Operand(esp), Immediate(4 * kPointerSize));
}
const int four_arguments = 4;
FrameAlign(four_arguments);
// Put arguments on stack.
__ mov(Operand(esp, 3 * kPointerSize), ecx);
__ mov(ebx, Operand(ebp, kInputEndOffset));
......@@ -317,17 +308,11 @@ void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
__ mov(eax, Operand(ebp, kInputBuffer));
__ mov(Operand(esp, 0 * kPointerSize), eax);
Address function_address = FUNCTION_ADDR(&CaseInsensitiveCompareUC16);
__ mov(Operand(eax),
Immediate(reinterpret_cast<int32_t>(function_address)));
__ call(Operand(eax));
if (frameAlignment != 0) {
__ mov(esp, Operand(esp, 4 * kPointerSize));
} else {
__ add(Operand(esp), Immediate(4 * sizeof(int32_t)));
}
CallCFunction(function_address, four_arguments);
__ pop(ecx);
__ pop(edi);
__ pop(esi);
__ or_(eax, Operand(eax));
BranchOrBacktrack(zero, on_no_match);
__ add(edi, Operand(ecx));
......@@ -536,25 +521,25 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
// Exit code:
// Success
__ bind(&success_label_);
if (num_saved_registers_ > 0) {
// copy captures to output
__ mov(ebx, Operand(ebp, kRegisterOutput));
__ mov(ecx, Operand(ebp, kInputEndOffset));
__ sub(ecx, Operand(ebp, kInputStartOffset));
for (int i = 0; i < num_saved_registers_; i++) {
__ mov(eax, register_location(i));
__ add(eax, Operand(ecx)); // Convert to index from start, not end.
if (char_size() > 1) {
ASSERT(char_size() == 2);
__ sar(eax, 1); // Convert to character index, not byte.
if (success_label_.is_linked()) {
// Success
__ bind(&success_label_);
if (num_saved_registers_ > 0) {
// copy captures to output
__ mov(ebx, Operand(ebp, kRegisterOutput));
__ mov(ecx, Operand(ebp, kInputEndOffset));
__ sub(ecx, Operand(ebp, kInputStartOffset));
for (int i = 0; i < num_saved_registers_; i++) {
__ mov(eax, register_location(i));
__ add(eax, Operand(ecx)); // Convert to index from start, not end.
if (mode_ == UC16) {
__ sar(eax, 1); // Convert byte index to character index.
}
__ mov(Operand(ebx, i * kPointerSize), eax);
}
__ mov(Operand(ebx, i * kPointerSize), eax);
}
__ mov(eax, Immediate(1));
}
__ mov(eax, Immediate(1));
// Exit and return eax
__ bind(&exit_label_);
__ leave();
......@@ -563,6 +548,47 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
__ pop(esi);
__ ret(0);
// Preempt-code
if (check_preempt_label_.is_linked()) {
__ bind(&check_preempt_label_);
// TODO(lrn): call C function to check the stack guard and return current
// stack state (0 = ok, positive = out of stack, negative = preempt).
// Then dispatch to an action depending on state, and loop.
__ push(edi);
Label retry;
Label stack_overflow;
__ bind(&retry);
int num_arguments = 2;
FrameAlign(num_arguments);
__ mov(Operand(esp, 1 * kPointerSize), Immediate(self_));
__ lea(eax, Operand(esp, -kPointerSize));
__ mov(Operand(esp, 0 * kPointerSize), eax);
CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments);
ExternalReference stack_guard_limit =
ExternalReference::address_of_stack_guard_limit();
__ or_(eax, Operand(eax));
__ j(not_equal, &stack_overflow);
__ cmp(esp, Operand::StaticVariable(stack_guard_limit));
__ j(below_equal, &retry);
__ pop(edi);
// String might have moved: Recompute esi from scratch.
__ mov(esi, Operand(esp, kInputBuffer));
__ mov(esi, Operand(esi, 0));
__ add(esi, Operand(esp, kInputEndOffset));
SafeReturn();
__ bind(&stack_overflow);
// Exit with result -1 to signal thrown exception.
__ mov(eax, -1);
__ jmp(&exit_label_);
}
CodeDesc code_desc;
masm_->GetCode(&code_desc);
Handle<Code> code = Factory::NewCode(code_desc,
......@@ -622,8 +648,8 @@ void RegExpMacroAssemblerIA32::PopRegister(int register_index) {
void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) {
// CheckStackLimit(); // Not ready yet.
__ push(label, RelocInfo::NONE);
__ push(Immediate::CodeRelativeOffset(label));
CheckStackLimit();
}
......@@ -710,6 +736,38 @@ int RegExpMacroAssemblerIA32::CaseInsensitiveCompareUC16(uc16** buffer,
}
int RegExpMacroAssemblerIA32::CheckStackGuardState(Address return_address,
Code* re_code) {
if (StackGuard::IsStackOverflow()) {
Top::StackOverflow();
return 1;
}
// If not real stack overflow the stack guard was used to interrupt
// execution for another purpose.
// Prepare for possible GC.
Handle<Code> code_handle(re_code);
#ifdef DEBUG
CHECK(re_code->instruction_start() <= return_address);
CHECK(return_address <=
re_code->instruction_start() + re_code->instruction_size());
#endif
Object* result = Execution::HandleStackGuardInterrupt();
if (*code_handle != re_code) { // Return address no longer valid
int delta = *code_handle - re_code;
*reinterpret_cast<int32_t*>(return_address) += delta;
}
if (result->IsException()) {
return 1;
}
return 0;
}
Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
ASSERT(register_index < (1<<30));
if (num_registers_ <= register_index) {
......@@ -750,51 +808,74 @@ void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition,
}
void RegExpMacroAssemblerIA32::SafeCall(Label* to) {
Label return_to;
__ push(Immediate::CodeRelativeOffset(&return_to));
__ jmp(to);
__ bind(&return_to);
}
void RegExpMacroAssemblerIA32::SafeReturn() {
__ pop(ecx);
__ add(Operand(ecx), Immediate(self_));
__ jmp(Operand(ecx));
}
void RegExpMacroAssemblerIA32::CheckStackLimit() {
if (FLAG_check_stack) {
// Check for preemption first.
Label no_preempt;
Label retry_preempt;
// Check for preemption.
ExternalReference stack_guard_limit =
ExternalReference::address_of_stack_guard_limit();
__ cmp(esp, Operand::StaticVariable(stack_guard_limit));
__ j(above, &no_preempt, taken);
__ push(edi); // Current position.
__ push(edx); // Current character.
// Restore original edi, esi.
__ mov(edi, Operand(ebp, kBackup_edi));
__ mov(esi, Operand(ebp, kBackup_esi));
__ bind(&retry_preempt);
// simulate stack for Runtime call.
__ push(eax);
__ push(Immediate(Smi::FromInt(0))); // Dummy receiver
__ CallRuntime(Runtime::kStackGuard, 1);
__ pop(eax);
__ cmp(esp, Operand::StaticVariable(stack_guard_limit));
__ j(below_equal, &retry_preempt);
__ pop(edx);
__ pop(edi);
__ mov(esi, Operand(ebp, kInputBuffer));
__ mov(esi, Operand(esi, 0));
__ add(esi, Operand(ebp, kInputEndOffset));
SafeCall(&check_preempt_label_);
__ bind(&no_preempt);
}
}
void RegExpMacroAssemblerIA32::FrameAlign(int num_arguments) {
int frameAlignment = OS::ActivationFrameAlignment();
if (frameAlignment != 0) {
// Make stack end at alignment and make room for num_arguments words
// and the original value of esp.
__ mov(ebx, esp);
__ sub(Operand(esp), Immediate((num_arguments + 1) * kPointerSize));
ASSERT(IsPowerOf2(frameAlignment));
__ and_(esp, -frameAlignment);
__ mov(Operand(esp, num_arguments * kPointerSize), ebx);
} else {
__ sub(Operand(esp), Immediate(num_arguments * kPointerSize));
}
}
void RegExpMacroAssemblerIA32::CallCFunction(Address function_address,
int num_arguments) {
__ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(function_address)));
__ call(Operand(eax));
if (OS::ActivationFrameAlignment() != 0) {
__ mov(esp, Operand(esp, num_arguments * kPointerSize));
} else {
__ add(Operand(esp), Immediate(num_arguments * sizeof(int32_t)));
}
}
void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset) {
if (mode_ == ASCII) {
__ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset));
return;
} else {
ASSERT(mode_ == UC16);
__ movzx_w(current_character(),
Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
}
ASSERT(mode_ == UC16);
__ movzx_w(current_character(),
Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
}
......
......@@ -33,7 +33,8 @@ namespace v8 { namespace internal {
class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
public:
// Type of input string to generate code for.
enum Mode {ASCII = 1, UC16 = 2};
enum Mode { ASCII = 1, UC16 = 2 };
enum Result { EXCEPTION = -1, FAILURE = 0, SUCCESS = 1 };
RegExpMacroAssemblerIA32(Mode mode, int registers_to_save);
virtual ~RegExpMacroAssemblerIA32();
......@@ -92,16 +93,21 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
virtual void WriteStackPointerToRegister(int reg);
template <typename T>
static inline bool Execute(Code* code,
T** input,
int start_offset,
int end_offset,
int* output,
bool at_start) {
typedef bool (*matcher)(T**, int, int, int*, int);
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;
return matcher_func(input, start_offset, end_offset, output, at_start_val);
int result = matcher_func(input,
start_offset,
end_offset,
output,
at_start_val);
return (result < 0) ? EXCEPTION : (result ? SUCCESS : FAILURE);
}
private:
......@@ -129,6 +135,11 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
int byte_offset2,
size_t byte_length);
// Called from RegExp if the stack-guard is triggered.
// If the code object is relocated, the return address is fixed before
// returning.
static int CheckStackGuardState(Address return_address, Code* re_code);
// The ebp-relative location of a regexp register.
Operand register_location(int register_index);
......@@ -151,6 +162,21 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
// (and checks if we have hit the stack limit too).
void CheckStackLimit();
// 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();
// 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);
// 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);
MacroAssembler* masm_;
// Constant buffer provider. Allocates external storage for storing
// constants.
......@@ -167,6 +193,7 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
Label start_label_;
Label success_label_;
Label exit_label_;
Label check_preempt_label_;
// Handle used to represent the generated code object itself.
Handle<Object> self_;
};
......
......@@ -3664,61 +3664,9 @@ static Object* Runtime_StackOverflow(Arguments args) {
}
static Object* RuntimePreempt(Arguments args) {
// Clear the preempt request flag.
StackGuard::Continue(PREEMPT);
ContextSwitcher::PreemptionReceived();
{
v8::Unlocker unlocker;
Thread::YieldCPU();
}
return Heap::undefined_value();
}
static Object* DebugBreakHelper() {
// Just continue if breaks are disabled.
if (Debug::disable_break()) {
return Heap::undefined_value();
}
// Don't break in system functions. If the current function is
// either in the builtins object of some context or is in the debug
// context just return with the debug break stack guard active.
JavaScriptFrameIterator it;
JavaScriptFrame* frame = it.frame();
Object* fun = frame->function();
if (fun->IsJSFunction()) {
GlobalObject* global = JSFunction::cast(fun)->context()->global();
if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
return Heap::undefined_value();
}
}
// Clear the debug request flag.
StackGuard::Continue(DEBUGBREAK);
HandleScope scope;
// Enter the debugger. Just continue if we fail to enter the debugger.
EnterDebugger debugger;
if (debugger.FailedToEnter()) {
return Heap::undefined_value();
}
// Notify the debug event listeners.
Debugger::OnDebugBreak(Factory::undefined_value());
// Return to continue execution.
return Heap::undefined_value();
}
static Object* Runtime_DebugBreak(Arguments args) {
ASSERT(args.length() == 0);
return DebugBreakHelper();
return Execution::DebugBreakHelper();
}
......@@ -3728,16 +3676,7 @@ static Object* Runtime_StackGuard(Arguments args) {
// First check if this is a real stack overflow.
if (StackGuard::IsStackOverflow()) return Runtime_StackOverflow(args);
// If not real stack overflow the stack guard was used to interrupt
// execution for another purpose.
if (StackGuard::IsDebugBreak()) DebugBreakHelper();
if (StackGuard::IsPreempted()) RuntimePreempt(args);
if (StackGuard::IsInterrupted()) {
// interrupt
StackGuard::Continue(INTERRUPT);
return Top::StackOverflow();
}
return Heap::undefined_value();
return Execution::HandleStackGuardInterrupt();
}
......
This diff is collapsed.
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