AllignFrame/CallCFuntion moved from regexp-macro-assembler-ia32 to macro-assembler-ia32 (like in x64 version).
Review URL: http://codereview.chromium.org/657080 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3947 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
fc382f0ffa
commit
2c872c26fd
@ -5743,21 +5743,12 @@ void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) {
|
|||||||
ASSERT(args->length() == 0);
|
ASSERT(args->length() == 0);
|
||||||
frame_->SpillAll();
|
frame_->SpillAll();
|
||||||
|
|
||||||
// Make sure the frame is aligned like the OS expects.
|
int num_arguments = 0;
|
||||||
static const int kFrameAlignment = OS::ActivationFrameAlignment();
|
__ PrepareCallCFunction(num_arguments, eax);
|
||||||
if (kFrameAlignment > 0) {
|
|
||||||
ASSERT(IsPowerOf2(kFrameAlignment));
|
|
||||||
__ mov(edi, Operand(esp)); // Save in callee-saved register.
|
|
||||||
__ and_(esp, -kFrameAlignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call V8::RandomPositiveSmi().
|
// Call V8::RandomPositiveSmi().
|
||||||
__ call(FUNCTION_ADDR(V8::RandomPositiveSmi), RelocInfo::RUNTIME_ENTRY);
|
__ CallCFunction(ExternalReference::random_positive_smi_function(),
|
||||||
|
num_arguments);
|
||||||
// Restore stack pointer from callee-saved register edi.
|
|
||||||
if (kFrameAlignment > 0) {
|
|
||||||
__ mov(esp, Operand(edi));
|
|
||||||
}
|
|
||||||
|
|
||||||
Result result = allocator_->Allocate(eax);
|
Result result = allocator_->Allocate(eax);
|
||||||
frame_->Push(&result);
|
frame_->Push(&result);
|
||||||
@ -9207,48 +9198,50 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|||||||
// All checks done. Now push arguments for native regexp code.
|
// All checks done. Now push arguments for native regexp code.
|
||||||
__ IncrementCounter(&Counters::regexp_entry_native, 1);
|
__ IncrementCounter(&Counters::regexp_entry_native, 1);
|
||||||
|
|
||||||
|
static const int kRegExpExecuteArguments = 7;
|
||||||
|
__ PrepareCallCFunction(kRegExpExecuteArguments, ecx);
|
||||||
|
|
||||||
// Argument 7: Indicate that this is a direct call from JavaScript.
|
// Argument 7: Indicate that this is a direct call from JavaScript.
|
||||||
__ push(Immediate(1));
|
__ mov(Operand(esp, 6 * kPointerSize), Immediate(1));
|
||||||
|
|
||||||
// Argument 6: Start (high end) of backtracking stack memory area.
|
// Argument 6: Start (high end) of backtracking stack memory area.
|
||||||
__ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address));
|
__ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address));
|
||||||
__ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
|
__ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
|
||||||
__ push(ecx);
|
__ mov(Operand(esp, 5 * kPointerSize), ecx);
|
||||||
|
|
||||||
// Argument 5: static offsets vector buffer.
|
// Argument 5: static offsets vector buffer.
|
||||||
__ push(Immediate(ExternalReference::address_of_static_offsets_vector()));
|
__ mov(Operand(esp, 4 * kPointerSize),
|
||||||
|
Immediate(ExternalReference::address_of_static_offsets_vector()));
|
||||||
|
|
||||||
// Argument 4: End of string data
|
// Argument 4: End of string data
|
||||||
// Argument 3: Start of string data
|
// Argument 3: Start of string data
|
||||||
Label push_two_byte, push_rest;
|
Label setup_two_byte, setup_rest;
|
||||||
__ test(edi, Operand(edi));
|
__ test(edi, Operand(edi));
|
||||||
__ mov(edi, FieldOperand(eax, String::kLengthOffset));
|
__ mov(edi, FieldOperand(eax, String::kLengthOffset));
|
||||||
__ j(zero, &push_two_byte);
|
__ j(zero, &setup_two_byte);
|
||||||
__ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize));
|
__ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize));
|
||||||
__ push(ecx); // Argument 4.
|
__ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
|
||||||
__ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
|
__ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
|
||||||
__ push(ecx); // Argument 3.
|
__ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
|
||||||
__ jmp(&push_rest);
|
__ jmp(&setup_rest);
|
||||||
|
|
||||||
__ bind(&push_two_byte);
|
__ bind(&setup_two_byte);
|
||||||
__ lea(ecx, FieldOperand(eax, edi, times_2, SeqTwoByteString::kHeaderSize));
|
__ lea(ecx, FieldOperand(eax, edi, times_2, SeqTwoByteString::kHeaderSize));
|
||||||
__ push(ecx); // Argument 4.
|
__ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
|
||||||
__ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
|
__ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
|
||||||
__ push(ecx); // Argument 3.
|
__ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
|
||||||
|
|
||||||
__ bind(&push_rest);
|
__ bind(&setup_rest);
|
||||||
|
|
||||||
// Argument 2: Previous index.
|
// Argument 2: Previous index.
|
||||||
__ push(ebx);
|
__ mov(Operand(esp, 1 * kPointerSize), ebx);
|
||||||
|
|
||||||
// Argument 1: Subject string.
|
// Argument 1: Subject string.
|
||||||
__ push(eax);
|
__ mov(Operand(esp, 0 * kPointerSize), eax);
|
||||||
|
|
||||||
// Locate the code entry and call it.
|
// Locate the code entry and call it.
|
||||||
__ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag));
|
__ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag));
|
||||||
__ call(Operand(edx));
|
__ CallCFunction(edx, kRegExpExecuteArguments);
|
||||||
// Remove arguments.
|
|
||||||
__ add(Operand(esp), Immediate(7 * kPointerSize));
|
|
||||||
|
|
||||||
// Check the result.
|
// Check the result.
|
||||||
Label success;
|
Label success;
|
||||||
|
@ -1622,6 +1622,41 @@ void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
|
||||||
|
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(scratch, esp);
|
||||||
|
sub(Operand(esp), Immediate((num_arguments + 1) * kPointerSize));
|
||||||
|
ASSERT(IsPowerOf2(frameAlignment));
|
||||||
|
and_(esp, -frameAlignment);
|
||||||
|
mov(Operand(esp, num_arguments * kPointerSize), scratch);
|
||||||
|
} else {
|
||||||
|
sub(Operand(esp), Immediate(num_arguments * kPointerSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::CallCFunction(ExternalReference function,
|
||||||
|
int num_arguments) {
|
||||||
|
// Trashing eax is ok as it will be the return value.
|
||||||
|
mov(Operand(eax), Immediate(function));
|
||||||
|
CallCFunction(eax, num_arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::CallCFunction(Register function,
|
||||||
|
int num_arguments) {
|
||||||
|
call(Operand(function));
|
||||||
|
if (OS::ActivationFrameAlignment() != 0) {
|
||||||
|
mov(esp, Operand(esp, num_arguments * kPointerSize));
|
||||||
|
} else {
|
||||||
|
add(Operand(esp), Immediate(num_arguments * sizeof(int32_t)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CodePatcher::CodePatcher(byte* address, int size)
|
CodePatcher::CodePatcher(byte* address, int size)
|
||||||
: address_(address), size_(size), masm_(address, size + Assembler::kGap) {
|
: address_(address), size_(size), masm_(address, size + Assembler::kGap) {
|
||||||
// Create a new macro assembler pointing to the address of the code to patch.
|
// Create a new macro assembler pointing to the address of the code to patch.
|
||||||
|
@ -377,6 +377,23 @@ class MacroAssembler: public Assembler {
|
|||||||
int num_arguments,
|
int num_arguments,
|
||||||
int result_size);
|
int result_size);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
// Some compilers/platforms require the stack to be aligned when calling
|
||||||
|
// C++ code.
|
||||||
|
// Needs a scratch register to do some arithmetic. This register will be
|
||||||
|
// trashed.
|
||||||
|
void PrepareCallCFunction(int num_arguments, Register scratch);
|
||||||
|
|
||||||
|
// Calls a C function and cleans up the space for arguments allocated
|
||||||
|
// by PrepareCallCFunction. The called function is not allowed to trigger a
|
||||||
|
// garbage collection, since that might move the code and invalidate the
|
||||||
|
// return address (unless this is somehow accounted for by the called
|
||||||
|
// function).
|
||||||
|
void CallCFunction(ExternalReference function, int num_arguments);
|
||||||
|
void CallCFunction(Register function, int num_arguments);
|
||||||
|
|
||||||
void PushHandleScope(Register scratch);
|
void PushHandleScope(Register scratch);
|
||||||
|
|
||||||
// Pops a handle scope using the specified scratch register and
|
// Pops a handle scope using the specified scratch register and
|
||||||
|
@ -325,7 +325,7 @@ void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
|
|||||||
__ push(ebx);
|
__ push(ebx);
|
||||||
|
|
||||||
const int argument_count = 3;
|
const int argument_count = 3;
|
||||||
FrameAlign(argument_count, ecx);
|
__ PrepareCallCFunction(argument_count, ecx);
|
||||||
// Put arguments into allocated stack area, last argument highest on stack.
|
// Put arguments into allocated stack area, last argument highest on stack.
|
||||||
// Parameters are
|
// Parameters are
|
||||||
// Address byte_offset1 - Address captured substring's start.
|
// Address byte_offset1 - Address captured substring's start.
|
||||||
@ -346,7 +346,7 @@ void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
|
|||||||
|
|
||||||
ExternalReference compare =
|
ExternalReference compare =
|
||||||
ExternalReference::re_case_insensitive_compare_uc16();
|
ExternalReference::re_case_insensitive_compare_uc16();
|
||||||
CallCFunction(compare, argument_count);
|
__ CallCFunction(compare, argument_count);
|
||||||
// Pop original values before reacting on result value.
|
// Pop original values before reacting on result value.
|
||||||
__ pop(ebx);
|
__ pop(ebx);
|
||||||
__ pop(backtrack_stackpointer());
|
__ pop(backtrack_stackpointer());
|
||||||
@ -785,12 +785,12 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
|
|||||||
|
|
||||||
// Call GrowStack(backtrack_stackpointer())
|
// Call GrowStack(backtrack_stackpointer())
|
||||||
int num_arguments = 2;
|
int num_arguments = 2;
|
||||||
FrameAlign(num_arguments, ebx);
|
__ PrepareCallCFunction(num_arguments, ebx);
|
||||||
__ lea(eax, Operand(ebp, kStackHighEnd));
|
__ lea(eax, Operand(ebp, kStackHighEnd));
|
||||||
__ mov(Operand(esp, 1 * kPointerSize), eax);
|
__ mov(Operand(esp, 1 * kPointerSize), eax);
|
||||||
__ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer());
|
__ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer());
|
||||||
ExternalReference grow_stack = ExternalReference::re_grow_stack();
|
ExternalReference grow_stack = ExternalReference::re_grow_stack();
|
||||||
CallCFunction(grow_stack, num_arguments);
|
__ CallCFunction(grow_stack, num_arguments);
|
||||||
// If return NULL, we have failed to grow the stack, and
|
// If return NULL, we have failed to grow the stack, and
|
||||||
// must exit with a stack-overflow exception.
|
// must exit with a stack-overflow exception.
|
||||||
__ or_(eax, Operand(eax));
|
__ or_(eax, Operand(eax));
|
||||||
@ -952,7 +952,7 @@ void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
|
|||||||
|
|
||||||
void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
|
void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
|
||||||
int num_arguments = 3;
|
int num_arguments = 3;
|
||||||
FrameAlign(num_arguments, scratch);
|
__ PrepareCallCFunction(num_arguments, scratch);
|
||||||
// RegExp code frame pointer.
|
// RegExp code frame pointer.
|
||||||
__ mov(Operand(esp, 2 * kPointerSize), ebp);
|
__ mov(Operand(esp, 2 * kPointerSize), ebp);
|
||||||
// Code* of self.
|
// Code* of self.
|
||||||
@ -962,7 +962,7 @@ void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
|
|||||||
__ mov(Operand(esp, 0 * kPointerSize), eax);
|
__ mov(Operand(esp, 0 * kPointerSize), eax);
|
||||||
ExternalReference check_stack_guard =
|
ExternalReference check_stack_guard =
|
||||||
ExternalReference::re_check_stack_guard_state();
|
ExternalReference::re_check_stack_guard_state();
|
||||||
CallCFunction(check_stack_guard, num_arguments);
|
__ CallCFunction(check_stack_guard, num_arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1153,37 +1153,6 @@ void RegExpMacroAssemblerIA32::CheckStackLimit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerIA32::FrameAlign(int num_arguments, Register scratch) {
|
|
||||||
// TODO(lrn): Since we no longer use the system stack arbitrarily (but we do
|
|
||||||
// use it, e.g., for SafeCall), we know the number of elements on the stack
|
|
||||||
// since the last frame alignment. We might be able to do this simpler then.
|
|
||||||
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(scratch, esp);
|
|
||||||
__ sub(Operand(esp), Immediate((num_arguments + 1) * kPointerSize));
|
|
||||||
ASSERT(IsPowerOf2(frameAlignment));
|
|
||||||
__ and_(esp, -frameAlignment);
|
|
||||||
__ mov(Operand(esp, num_arguments * kPointerSize), scratch);
|
|
||||||
} else {
|
|
||||||
__ sub(Operand(esp), Immediate(num_arguments * kPointerSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerIA32::CallCFunction(ExternalReference function,
|
|
||||||
int num_arguments) {
|
|
||||||
__ mov(Operand(eax), Immediate(function));
|
|
||||||
__ 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,
|
void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset,
|
||||||
int characters) {
|
int characters) {
|
||||||
if (mode_ == ASCII) {
|
if (mode_ == ASCII) {
|
||||||
|
@ -187,21 +187,6 @@ class RegExpMacroAssemblerIA32: public NativeRegExpMacroAssembler {
|
|||||||
// (ecx) and increments it by a word size.
|
// (ecx) and increments it by a word size.
|
||||||
inline void Pop(Register target);
|
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.
|
|
||||||
// Some compilers/platforms require the stack to be aligned when calling
|
|
||||||
// C++ code.
|
|
||||||
// Needs a scratch register to do some arithmetic. This register will be
|
|
||||||
// trashed.
|
|
||||||
inline void FrameAlign(int num_arguments, Register scratch);
|
|
||||||
|
|
||||||
// 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 (unless this is somehow accounted for).
|
|
||||||
inline void CallCFunction(ExternalReference function, int num_arguments);
|
|
||||||
|
|
||||||
MacroAssembler* masm_;
|
MacroAssembler* masm_;
|
||||||
|
|
||||||
// Which mode to generate code for (ASCII or UC16).
|
// Which mode to generate code for (ASCII or UC16).
|
||||||
|
@ -3958,21 +3958,12 @@ void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) {
|
|||||||
frame_->SpillAll();
|
frame_->SpillAll();
|
||||||
__ push(rsi);
|
__ push(rsi);
|
||||||
|
|
||||||
// Make sure the frame is aligned like the OS expects.
|
int num_arguments = 0;
|
||||||
static const int kFrameAlignment = OS::ActivationFrameAlignment();
|
__ PrepareCallCFunction(num_arguments);
|
||||||
if (kFrameAlignment > 0) {
|
|
||||||
ASSERT(IsPowerOf2(kFrameAlignment));
|
|
||||||
__ movq(rbx, rsp); // Save in AMD-64 abi callee-saved register.
|
|
||||||
__ and_(rsp, Immediate(-kFrameAlignment));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call V8::RandomPositiveSmi().
|
// Call V8::RandomPositiveSmi().
|
||||||
__ Call(FUNCTION_ADDR(V8::RandomPositiveSmi), RelocInfo::RUNTIME_ENTRY);
|
__ CallCFunction(ExternalReference::random_positive_smi_function(),
|
||||||
|
num_arguments);
|
||||||
// Restore stack pointer from callee-saved register.
|
|
||||||
if (kFrameAlignment > 0) {
|
|
||||||
__ movq(rsp, rbx);
|
|
||||||
}
|
|
||||||
|
|
||||||
__ pop(rsi);
|
__ pop(rsi);
|
||||||
Result result = allocator_->Allocate(rax);
|
Result result = allocator_->Allocate(rax);
|
||||||
|
Loading…
Reference in New Issue
Block a user