From 2c872c26fdaae8de7747ba27ee137eff80af5ba2 Mon Sep 17 00:00:00 2001 From: "serya@chromium.org" Date: Thu, 25 Feb 2010 12:18:55 +0000 Subject: [PATCH] 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 --- src/ia32/codegen-ia32.cc | 53 +++++++++++-------------- src/ia32/macro-assembler-ia32.cc | 35 ++++++++++++++++ src/ia32/macro-assembler-ia32.h | 17 ++++++++ src/ia32/regexp-macro-assembler-ia32.cc | 43 +++----------------- src/ia32/regexp-macro-assembler-ia32.h | 15 ------- src/x64/codegen-x64.cc | 17 ++------ 6 files changed, 85 insertions(+), 95 deletions(-) diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index 312d6e7357..816f16ad2a 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -5743,21 +5743,12 @@ void CodeGenerator::GenerateRandomPositiveSmi(ZoneList* args) { ASSERT(args->length() == 0); frame_->SpillAll(); - // Make sure the frame is aligned like the OS expects. - static const int kFrameAlignment = OS::ActivationFrameAlignment(); - if (kFrameAlignment > 0) { - ASSERT(IsPowerOf2(kFrameAlignment)); - __ mov(edi, Operand(esp)); // Save in callee-saved register. - __ and_(esp, -kFrameAlignment); - } + int num_arguments = 0; + __ PrepareCallCFunction(num_arguments, eax); // Call V8::RandomPositiveSmi(). - __ call(FUNCTION_ADDR(V8::RandomPositiveSmi), RelocInfo::RUNTIME_ENTRY); - - // Restore stack pointer from callee-saved register edi. - if (kFrameAlignment > 0) { - __ mov(esp, Operand(edi)); - } + __ CallCFunction(ExternalReference::random_positive_smi_function(), + num_arguments); Result result = allocator_->Allocate(eax); frame_->Push(&result); @@ -9207,48 +9198,50 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { // All checks done. Now push arguments for native regexp code. __ 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. - __ push(Immediate(1)); + __ mov(Operand(esp, 6 * kPointerSize), Immediate(1)); // Argument 6: Start (high end) of backtracking stack memory area. __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); - __ push(ecx); + __ mov(Operand(esp, 5 * kPointerSize), ecx); // 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 3: Start of string data - Label push_two_byte, push_rest; + Label setup_two_byte, setup_rest; __ test(edi, Operand(edi)); __ 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)); - __ push(ecx); // Argument 4. + __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); - __ push(ecx); // Argument 3. - __ jmp(&push_rest); + __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. + __ jmp(&setup_rest); - __ bind(&push_two_byte); + __ bind(&setup_two_byte); __ 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)); - __ push(ecx); // Argument 3. + __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. - __ bind(&push_rest); + __ bind(&setup_rest); // Argument 2: Previous index. - __ push(ebx); + __ mov(Operand(esp, 1 * kPointerSize), ebx); // Argument 1: Subject string. - __ push(eax); + __ mov(Operand(esp, 0 * kPointerSize), eax); // Locate the code entry and call it. __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); - __ call(Operand(edx)); - // Remove arguments. - __ add(Operand(esp), Immediate(7 * kPointerSize)); + __ CallCFunction(edx, kRegExpExecuteArguments); // Check the result. Label success; diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index 834430b683..6adb8e7d6e 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -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) : address_(address), size_(size), masm_(address, size + Assembler::kGap) { // Create a new macro assembler pointing to the address of the code to patch. diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index e37bd18609..a284b63676 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -377,6 +377,23 @@ class MacroAssembler: public Assembler { int num_arguments, 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); // Pops a handle scope using the specified scratch register and diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc index f6da693797..e5edf74f5e 100644 --- a/src/ia32/regexp-macro-assembler-ia32.cc +++ b/src/ia32/regexp-macro-assembler-ia32.cc @@ -325,7 +325,7 @@ void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( __ push(ebx); const int argument_count = 3; - FrameAlign(argument_count, ecx); + __ PrepareCallCFunction(argument_count, ecx); // Put arguments into allocated stack area, last argument highest on stack. // Parameters are // Address byte_offset1 - Address captured substring's start. @@ -346,7 +346,7 @@ void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( ExternalReference compare = ExternalReference::re_case_insensitive_compare_uc16(); - CallCFunction(compare, argument_count); + __ CallCFunction(compare, argument_count); // Pop original values before reacting on result value. __ pop(ebx); __ pop(backtrack_stackpointer()); @@ -785,12 +785,12 @@ Handle RegExpMacroAssemblerIA32::GetCode(Handle source) { // Call GrowStack(backtrack_stackpointer()) int num_arguments = 2; - FrameAlign(num_arguments, ebx); + __ PrepareCallCFunction(num_arguments, ebx); __ lea(eax, Operand(ebp, kStackHighEnd)); __ mov(Operand(esp, 1 * kPointerSize), eax); __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer()); 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 // must exit with a stack-overflow exception. __ or_(eax, Operand(eax)); @@ -952,7 +952,7 @@ void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) { int num_arguments = 3; - FrameAlign(num_arguments, scratch); + __ PrepareCallCFunction(num_arguments, scratch); // RegExp code frame pointer. __ mov(Operand(esp, 2 * kPointerSize), ebp); // Code* of self. @@ -962,7 +962,7 @@ void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) { __ mov(Operand(esp, 0 * kPointerSize), eax); ExternalReference check_stack_guard = 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, int characters) { if (mode_ == ASCII) { diff --git a/src/ia32/regexp-macro-assembler-ia32.h b/src/ia32/regexp-macro-assembler-ia32.h index d9866b72b9..0d5e272dcf 100644 --- a/src/ia32/regexp-macro-assembler-ia32.h +++ b/src/ia32/regexp-macro-assembler-ia32.h @@ -187,21 +187,6 @@ class RegExpMacroAssemblerIA32: public NativeRegExpMacroAssembler { // (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. - // 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_; // Which mode to generate code for (ASCII or UC16). diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index e8fcb14000..c8dd0b66f8 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -3958,21 +3958,12 @@ void CodeGenerator::GenerateRandomPositiveSmi(ZoneList* args) { frame_->SpillAll(); __ push(rsi); - // Make sure the frame is aligned like the OS expects. - static const int kFrameAlignment = OS::ActivationFrameAlignment(); - if (kFrameAlignment > 0) { - ASSERT(IsPowerOf2(kFrameAlignment)); - __ movq(rbx, rsp); // Save in AMD-64 abi callee-saved register. - __ and_(rsp, Immediate(-kFrameAlignment)); - } + int num_arguments = 0; + __ PrepareCallCFunction(num_arguments); // Call V8::RandomPositiveSmi(). - __ Call(FUNCTION_ADDR(V8::RandomPositiveSmi), RelocInfo::RUNTIME_ENTRY); - - // Restore stack pointer from callee-saved register. - if (kFrameAlignment > 0) { - __ movq(rsp, rbx); - } + __ CallCFunction(ExternalReference::random_positive_smi_function(), + num_arguments); __ pop(rsi); Result result = allocator_->Allocate(rax);