Index: src/x64/code-stubs-x64.cc |
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc |
index 4b4531eb689dbb5b78709a7ecede24e3b303c0dc..a335b37ded6a4dd9772a430299e6fde2c0aee35e 100644 |
--- a/src/x64/code-stubs-x64.cc |
+++ b/src/x64/code-stubs-x64.cc |
@@ -2268,46 +2268,46 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
// rcx: RegExp data (FixedArray) |
// rdx: Number of capture registers |
// Check that the second argument is a string. |
- __ movq(rax, Operand(rsp, kSubjectOffset)); |
- __ JumpIfSmi(rax, &runtime); |
- Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); |
+ __ movq(rdi, Operand(rsp, kSubjectOffset)); |
+ __ JumpIfSmi(rdi, &runtime); |
+ Condition is_string = masm->IsObjectStringType(rdi, rbx, rbx); |
__ j(NegateCondition(is_string), &runtime); |
- // rax: Subject string. |
- // rcx: RegExp data (FixedArray). |
+ // rdi: Subject string. |
+ // rax: RegExp data (FixedArray). |
// rdx: Number of capture registers. |
// Check that the third argument is a positive smi less than the string |
// length. A negative value will be greater (unsigned comparison). |
__ movq(rbx, Operand(rsp, kPreviousIndexOffset)); |
__ JumpIfNotSmi(rbx, &runtime); |
- __ SmiCompare(rbx, FieldOperand(rax, String::kLengthOffset)); |
+ __ SmiCompare(rbx, FieldOperand(rdi, String::kLengthOffset)); |
__ j(above_equal, &runtime); |
- // rcx: RegExp data (FixedArray) |
+ // rax: RegExp data (FixedArray) |
// rdx: Number of capture registers |
// Check that the fourth object is a JSArray object. |
- __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); |
- __ JumpIfSmi(rax, &runtime); |
- __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister); |
+ __ movq(rdi, Operand(rsp, kLastMatchInfoOffset)); |
+ __ JumpIfSmi(rdi, &runtime); |
+ __ CmpObjectType(rdi, JS_ARRAY_TYPE, kScratchRegister); |
__ j(not_equal, &runtime); |
// Check that the JSArray is in fast case. |
- __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); |
- __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); |
- __ Cmp(rax, Factory::fixed_array_map()); |
+ __ movq(rbx, FieldOperand(rdi, JSArray::kElementsOffset)); |
+ __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); |
+ __ Cmp(rdi, Factory::fixed_array_map()); |
__ j(not_equal, &runtime); |
// Check that the last match info has space for the capture registers and the |
// additional information. Ensure no overflow in add. |
STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); |
- __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); |
+ __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset)); |
__ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); |
- __ cmpl(rdx, rax); |
+ __ cmpl(rdx, rdi); |
__ j(greater, &runtime); |
- // rcx: RegExp data (FixedArray) |
+ // rax: RegExp data (FixedArray) |
// Check the representation and encoding of the subject string. |
NearLabel seq_ascii_string, seq_two_byte_string, check_code; |
- __ movq(rax, Operand(rsp, kSubjectOffset)); |
- __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
+ __ movq(rdi, Operand(rsp, kSubjectOffset)); |
+ __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
__ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
// First check for flat two byte string. |
__ andb(rbx, Immediate( |
@@ -2328,13 +2328,13 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
__ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag)); |
__ j(not_zero, &runtime); |
// String is a cons string. |
- __ movq(rdx, FieldOperand(rax, ConsString::kSecondOffset)); |
+ __ movq(rdx, FieldOperand(rdi, ConsString::kSecondOffset)); |
__ Cmp(rdx, Factory::empty_string()); |
__ j(not_equal, &runtime); |
- __ movq(rax, FieldOperand(rax, ConsString::kFirstOffset)); |
- __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
+ __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); |
+ __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
// String is a cons string with empty second part. |
- // rax: first part of cons string. |
+ // rdi: first part of cons string. |
// rbx: map of first part of cons string. |
// Is first part a flat two byte string? |
__ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), |
@@ -2347,17 +2347,17 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
__ j(not_zero, &runtime); |
__ bind(&seq_ascii_string); |
- // rax: subject string (sequential ascii) |
- // rcx: RegExp data (FixedArray) |
- __ movq(r11, FieldOperand(rcx, JSRegExp::kDataAsciiCodeOffset)); |
- __ Set(rdi, 1); // Type is ascii. |
+ // rdi: subject string (sequential ascii) |
+ // rax: RegExp data (FixedArray) |
+ __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset)); |
+ __ Set(rcx, 1); // Type is ascii. |
__ jmp(&check_code); |
__ bind(&seq_two_byte_string); |
- // rax: subject string (flat two-byte) |
- // rcx: RegExp data (FixedArray) |
- __ movq(r11, FieldOperand(rcx, JSRegExp::kDataUC16CodeOffset)); |
- __ Set(rdi, 0); // Type is two byte. |
+ // rdi: subject string (flat two-byte) |
+ // rax: RegExp data (FixedArray) |
+ __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); |
+ __ Set(rcx, 0); // Type is two byte. |
__ bind(&check_code); |
// Check that the irregexp code has been generated for the actual string |
@@ -2366,27 +2366,24 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
__ CmpObjectType(r11, CODE_TYPE, kScratchRegister); |
__ j(not_equal, &runtime); |
- // rax: subject string |
- // rdi: encoding of subject string (1 if ascii, 0 if two_byte); |
+ // rdi: subject string |
+ // rcx: encoding of subject string (1 if ascii, 0 if two_byte); |
// r11: code |
// Load used arguments before starting to push arguments for call to native |
// RegExp code to avoid handling changing stack height. |
__ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); |
- // rax: subject string |
+ // rdi: subject string |
// rbx: previous index |
- // rdi: encoding of subject string (1 if ascii 0 if two_byte); |
+ // rcx: encoding of subject string (1 if ascii 0 if two_byte); |
// r11: code |
// All checks done. Now push arguments for native regexp code. |
__ IncrementCounter(&Counters::regexp_entry_native, 1); |
- // rsi is caller save on Windows and used to pass parameter on Linux. |
- __ push(rsi); |
- |
static const int kRegExpExecuteArguments = 7; |
- __ PrepareCallCFunction(kRegExpExecuteArguments); |
int argument_slots_on_stack = |
masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); |
+ __ EnterApiExitFrame(argument_slots_on_stack); // Clobbers rax! |
// Argument 7: Indicate that this is a direct call from JavaScript. |
__ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), |
@@ -2423,60 +2420,57 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
#endif |
// Keep track on aliasing between argX defined above and the registers used. |
- // rax: subject string |
+ // rdi: subject string |
// rbx: previous index |
- // rdi: encoding of subject string (1 if ascii 0 if two_byte); |
+ // rcx: encoding of subject string (1 if ascii 0 if two_byte); |
// r11: code |
// Argument 4: End of string data |
// Argument 3: Start of string data |
NearLabel setup_two_byte, setup_rest; |
- __ testb(rdi, rdi); |
+ __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. |
__ j(zero, &setup_two_byte); |
- __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); |
- __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize)); |
- __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize)); |
+ __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); |
+ __ lea(arg4, FieldOperand(rdi, rcx, times_1, SeqAsciiString::kHeaderSize)); |
+ __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize)); |
__ jmp(&setup_rest); |
__ bind(&setup_two_byte); |
- __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); |
- __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize)); |
- __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize)); |
+ __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); |
+ __ lea(arg4, FieldOperand(rdi, rcx, times_2, SeqTwoByteString::kHeaderSize)); |
+ __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); |
__ bind(&setup_rest); |
// Argument 2: Previous index. |
__ movq(arg2, rbx); |
// Argument 1: Subject string. |
- __ movq(arg1, rax); |
+#ifdef WIN64_ |
+ __ movq(arg1, rdi); |
+#else |
+ // Already there in AMD64 calling convention. |
+ ASSERT(arg1.is(rdi)); |
+#endif |
// Locate the code entry and call it. |
__ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
- __ CallCFunction(r11, kRegExpExecuteArguments); |
+ __ call(r11); |
- // rsi is caller save, as it is used to pass parameter. |
- __ pop(rsi); |
+ __ LeaveApiExitFrame(); |
// Check the result. |
NearLabel success; |
+ Label exception; |
__ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS)); |
__ j(equal, &success); |
- NearLabel failure; |
- __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); |
- __ j(equal, &failure); |
__ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); |
- // If not exception it can only be retry. Handle that in the runtime system. |
+ __ j(equal, &exception); |
+ __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); |
+ // If none of the above, it can only be retry. |
+ // Handle that in the runtime system. |
__ j(not_equal, &runtime); |
- // Result must now be exception. If there is no pending exception already a |
- // stack overflow (on the backtrack stack) was detected in RegExp code but |
- // haven't created the exception yet. Handle that in the runtime system. |
- // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
- ExternalReference pending_exception_address(Top::k_pending_exception_address); |
- __ movq(kScratchRegister, pending_exception_address); |
- __ Cmp(kScratchRegister, Factory::the_hole_value()); |
- __ j(equal, &runtime); |
- __ bind(&failure); |
- // For failure and exception return null. |
- __ Move(rax, Factory::null_value()); |
+ |
+ // For failure return null. |
+ __ LoadRoot(rax, Heap::kNullValueRootIndex); |
__ ret(4 * kPointerSize); |
// Load RegExp data. |
@@ -2537,6 +2531,27 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
__ movq(rax, Operand(rsp, kLastMatchInfoOffset)); |
__ ret(4 * kPointerSize); |
+ __ bind(&exception); |
+ // Result must now be exception. If there is no pending exception already a |
+ // stack overflow (on the backtrack stack) was detected in RegExp code but |
+ // haven't created the exception yet. Handle that in the runtime system. |
+ // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
+ ExternalReference pending_exception_address(Top::k_pending_exception_address); |
+ __ movq(rbx, pending_exception_address); |
+ __ movq(rax, Operand(rbx, 0)); |
+ __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); |
+ __ cmpq(rax, rdx); |
+ __ j(equal, &runtime); |
+ __ movq(Operand(rbx, 0), rdx); |
+ |
+ __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); |
+ NearLabel termination_exception; |
+ __ j(equal, &termination_exception); |
+ __ Throw(rax); |
+ |
+ __ bind(&termination_exception); |
+ __ ThrowUncatchable(TERMINATION, rax); |
+ |
// Do the runtime call to execute the regexp. |
__ bind(&runtime); |
__ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
@@ -3085,31 +3100,8 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { |
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
- // Check that stack should contain next handler, frame pointer, state and |
- // return address in that order. |
- STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == |
- StackHandlerConstants::kStateOffset); |
- STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == |
- StackHandlerConstants::kPCOffset); |
- |
- ExternalReference handler_address(Top::k_handler_address); |
- __ movq(kScratchRegister, handler_address); |
- __ movq(rsp, Operand(kScratchRegister, 0)); |
- // get next in chain |
- __ pop(rcx); |
- __ movq(Operand(kScratchRegister, 0), rcx); |
- __ pop(rbp); // pop frame pointer |
- __ pop(rdx); // remove state |
- |
- // Before returning we restore the context from the frame pointer if not NULL. |
- // The frame pointer is NULL in the exception handler of a JS entry frame. |
- __ Set(rsi, 0); // Tentatively set context pointer to NULL |
- NearLabel skip; |
- __ cmpq(rbp, Immediate(0)); |
- __ j(equal, &skip); |
- __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
- __ bind(&skip); |
- __ ret(0); |
+ // Throw exception in eax. |
+ __ Throw(rax); |
} |
@@ -3251,54 +3243,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm, |
void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
UncatchableExceptionType type) { |
- // Fetch top stack handler. |
- ExternalReference handler_address(Top::k_handler_address); |
- __ movq(kScratchRegister, handler_address); |
- __ movq(rsp, Operand(kScratchRegister, 0)); |
- |
- // Unwind the handlers until the ENTRY handler is found. |
- NearLabel loop, done; |
- __ bind(&loop); |
- // Load the type of the current stack handler. |
- const int kStateOffset = StackHandlerConstants::kStateOffset; |
- __ cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY)); |
- __ j(equal, &done); |
- // Fetch the next handler in the list. |
- const int kNextOffset = StackHandlerConstants::kNextOffset; |
- __ movq(rsp, Operand(rsp, kNextOffset)); |
- __ jmp(&loop); |
- __ bind(&done); |
- |
- // Set the top handler address to next handler past the current ENTRY handler. |
- __ movq(kScratchRegister, handler_address); |
- __ pop(Operand(kScratchRegister, 0)); |
- |
- if (type == OUT_OF_MEMORY) { |
- // Set external caught exception to false. |
- ExternalReference external_caught(Top::k_external_caught_exception_address); |
- __ movq(rax, Immediate(false)); |
- __ store_rax(external_caught); |
- |
- // Set pending exception and rax to out of memory exception. |
- ExternalReference pending_exception(Top::k_pending_exception_address); |
- __ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); |
- __ store_rax(pending_exception); |
- } |
- |
- // Clear the context pointer. |
- __ Set(rsi, 0); |
- |
- // Restore registers from handler. |
- STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize == |
- StackHandlerConstants::kFPOffset); |
- __ pop(rbp); // FP |
- STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == |
- StackHandlerConstants::kStateOffset); |
- __ pop(rdx); // State |
- |
- STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == |
- StackHandlerConstants::kPCOffset); |
- __ ret(0); |
+ __ ThrowUncatchable(type, rax); |
} |