| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 3847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3858 __ SmiUntag(ebx); // Previous index from smi. | 3858 __ SmiUntag(ebx); // Previous index from smi. |
| 3859 | 3859 |
| 3860 // eax: subject string | 3860 // eax: subject string |
| 3861 // ebx: previous index | 3861 // ebx: previous index |
| 3862 // edx: code | 3862 // edx: code |
| 3863 // edi: encoding of subject string (1 if ascii 0 if two_byte); | 3863 // edi: encoding of subject string (1 if ascii 0 if two_byte); |
| 3864 // All checks done. Now push arguments for native regexp code. | 3864 // All checks done. Now push arguments for native regexp code. |
| 3865 __ IncrementCounter(&Counters::regexp_entry_native, 1); | 3865 __ IncrementCounter(&Counters::regexp_entry_native, 1); |
| 3866 | 3866 |
| 3867 static const int kRegExpExecuteArguments = 7; | 3867 static const int kRegExpExecuteArguments = 7; |
| 3868 __ PrepareCallCFunction(kRegExpExecuteArguments, ecx); | 3868 __ EnterApiExitFrame(kRegExpExecuteArguments); |
| 3869 | 3869 |
| 3870 // Argument 7: Indicate that this is a direct call from JavaScript. | 3870 // Argument 7: Indicate that this is a direct call from JavaScript. |
| 3871 __ mov(Operand(esp, 6 * kPointerSize), Immediate(1)); | 3871 __ mov(Operand(esp, 6 * kPointerSize), Immediate(1)); |
| 3872 | 3872 |
| 3873 // Argument 6: Start (high end) of backtracking stack memory area. | 3873 // Argument 6: Start (high end) of backtracking stack memory area. |
| 3874 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); | 3874 __ mov(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_address)); |
| 3875 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); | 3875 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
| 3876 __ mov(Operand(esp, 5 * kPointerSize), ecx); | 3876 __ mov(Operand(esp, 5 * kPointerSize), ecx); |
| 3877 | 3877 |
| 3878 // Argument 5: static offsets vector buffer. | 3878 // Argument 5: static offsets vector buffer. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3903 __ bind(&setup_rest); | 3903 __ bind(&setup_rest); |
| 3904 | 3904 |
| 3905 // Argument 2: Previous index. | 3905 // Argument 2: Previous index. |
| 3906 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 3906 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
| 3907 | 3907 |
| 3908 // Argument 1: Subject string. | 3908 // Argument 1: Subject string. |
| 3909 __ mov(Operand(esp, 0 * kPointerSize), eax); | 3909 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 3910 | 3910 |
| 3911 // Locate the code entry and call it. | 3911 // Locate the code entry and call it. |
| 3912 __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); | 3912 __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 3913 __ CallCFunction(edx, kRegExpExecuteArguments); | 3913 __ call(Operand(edx)); |
| 3914 |
| 3915 // Drop arguments and come back to JS mode. |
| 3916 __ LeaveApiExitFrame(); |
| 3914 | 3917 |
| 3915 // Check the result. | 3918 // Check the result. |
| 3916 Label success; | 3919 Label success; |
| 3917 __ cmp(eax, NativeRegExpMacroAssembler::SUCCESS); | 3920 __ cmp(eax, NativeRegExpMacroAssembler::SUCCESS); |
| 3918 __ j(equal, &success, taken); | 3921 __ j(equal, &success, taken); |
| 3919 Label failure; | 3922 Label failure; |
| 3920 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); | 3923 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); |
| 3921 __ j(equal, &failure, taken); | 3924 __ j(equal, &failure, taken); |
| 3922 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); | 3925 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); |
| 3923 // If not exception it can only be retry. Handle that in the runtime system. | 3926 // If not exception it can only be retry. Handle that in the runtime system. |
| 3924 __ j(not_equal, &runtime); | 3927 __ j(not_equal, &runtime); |
| 3925 // Result must now be exception. If there is no pending exception already a | 3928 // Result must now be exception. If there is no pending exception already a |
| 3926 // stack overflow (on the backtrack stack) was detected in RegExp code but | 3929 // stack overflow (on the backtrack stack) was detected in RegExp code but |
| 3927 // haven't created the exception yet. Handle that in the runtime system. | 3930 // haven't created the exception yet. Handle that in the runtime system. |
| 3928 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 3931 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 3929 ExternalReference pending_exception(Top::k_pending_exception_address); | 3932 ExternalReference pending_exception(Top::k_pending_exception_address); |
| 3930 __ mov(eax, | 3933 __ mov(edx, |
| 3931 Operand::StaticVariable(ExternalReference::the_hole_value_location())); | 3934 Operand::StaticVariable(ExternalReference::the_hole_value_location())); |
| 3932 __ cmp(eax, Operand::StaticVariable(pending_exception)); | 3935 __ mov(eax, Operand::StaticVariable(pending_exception)); |
| 3936 __ cmp(edx, Operand(eax)); |
| 3933 __ j(equal, &runtime); | 3937 __ j(equal, &runtime); |
| 3938 // For exception, throw the exception again. |
| 3939 |
| 3940 // Clear the pending exception variable. |
| 3941 __ mov(Operand::StaticVariable(pending_exception), edx); |
| 3942 |
| 3943 // Special handling of termination exceptions which are uncatchable |
| 3944 // by javascript code. |
| 3945 __ cmp(eax, Factory::termination_exception()); |
| 3946 Label throw_termination_exception; |
| 3947 __ j(equal, &throw_termination_exception); |
| 3948 |
| 3949 // Handle normal exception by following handler chain. |
| 3950 __ Throw(eax); |
| 3951 |
| 3952 __ bind(&throw_termination_exception); |
| 3953 __ ThrowUncatchable(TERMINATION, eax); |
| 3954 |
| 3934 __ bind(&failure); | 3955 __ bind(&failure); |
| 3935 // For failure and exception return null. | 3956 // For failure to match, return null. |
| 3936 __ mov(Operand(eax), Factory::null_value()); | 3957 __ mov(Operand(eax), Factory::null_value()); |
| 3937 __ ret(4 * kPointerSize); | 3958 __ ret(4 * kPointerSize); |
| 3938 | 3959 |
| 3939 // Load RegExp data. | 3960 // Load RegExp data. |
| 3940 __ bind(&success); | 3961 __ bind(&success); |
| 3941 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 3962 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
| 3942 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 3963 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
| 3943 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); | 3964 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); |
| 3944 // Calculate number of capture registers (number_of_captures + 1) * 2. | 3965 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 3945 STATIC_ASSERT(kSmiTag == 0); | 3966 STATIC_ASSERT(kSmiTag == 0); |
| (...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4599 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); | 4620 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); |
| 4600 __ Set(eax, Immediate(argc_)); | 4621 __ Set(eax, Immediate(argc_)); |
| 4601 __ Set(ebx, Immediate(0)); | 4622 __ Set(ebx, Immediate(0)); |
| 4602 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); | 4623 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
| 4603 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); | 4624 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); |
| 4604 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 4625 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
| 4605 } | 4626 } |
| 4606 | 4627 |
| 4607 | 4628 |
| 4608 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 4629 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| 4609 // eax holds the exception. | 4630 __ Throw(eax); |
| 4610 | |
| 4611 // Adjust this code if not the case. | |
| 4612 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | |
| 4613 | |
| 4614 // Drop the sp to the top of the handler. | |
| 4615 ExternalReference handler_address(Top::k_handler_address); | |
| 4616 __ mov(esp, Operand::StaticVariable(handler_address)); | |
| 4617 | |
| 4618 // Restore next handler and frame pointer, discard handler state. | |
| 4619 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 4620 __ pop(Operand::StaticVariable(handler_address)); | |
| 4621 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize); | |
| 4622 __ pop(ebp); | |
| 4623 __ pop(edx); // Remove state. | |
| 4624 | |
| 4625 // Before returning we restore the context from the frame pointer if | |
| 4626 // not NULL. The frame pointer is NULL in the exception handler of | |
| 4627 // a JS entry frame. | |
| 4628 __ Set(esi, Immediate(0)); // Tentatively set context pointer to NULL. | |
| 4629 NearLabel skip; | |
| 4630 __ cmp(ebp, 0); | |
| 4631 __ j(equal, &skip, not_taken); | |
| 4632 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 4633 __ bind(&skip); | |
| 4634 | |
| 4635 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 4636 __ ret(0); | |
| 4637 } | 4631 } |
| 4638 | 4632 |
| 4639 | 4633 |
| 4640 void CEntryStub::GenerateCore(MacroAssembler* masm, | 4634 void CEntryStub::GenerateCore(MacroAssembler* masm, |
| 4641 Label* throw_normal_exception, | 4635 Label* throw_normal_exception, |
| 4642 Label* throw_termination_exception, | 4636 Label* throw_termination_exception, |
| 4643 Label* throw_out_of_memory_exception, | 4637 Label* throw_out_of_memory_exception, |
| 4644 bool do_gc, | 4638 bool do_gc, |
| 4645 bool always_allocate_scope) { | 4639 bool always_allocate_scope) { |
| 4646 // eax: result parameter for PerformGC, if any | 4640 // eax: result parameter for PerformGC, if any |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4733 // Handle normal exception. | 4727 // Handle normal exception. |
| 4734 __ jmp(throw_normal_exception); | 4728 __ jmp(throw_normal_exception); |
| 4735 | 4729 |
| 4736 // Retry. | 4730 // Retry. |
| 4737 __ bind(&retry); | 4731 __ bind(&retry); |
| 4738 } | 4732 } |
| 4739 | 4733 |
| 4740 | 4734 |
| 4741 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, | 4735 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
| 4742 UncatchableExceptionType type) { | 4736 UncatchableExceptionType type) { |
| 4743 // Adjust this code if not the case. | 4737 __ ThrowUncatchable(type, eax); |
| 4744 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | |
| 4745 | |
| 4746 // Drop sp to the top stack handler. | |
| 4747 ExternalReference handler_address(Top::k_handler_address); | |
| 4748 __ mov(esp, Operand::StaticVariable(handler_address)); | |
| 4749 | |
| 4750 // Unwind the handlers until the ENTRY handler is found. | |
| 4751 NearLabel loop, done; | |
| 4752 __ bind(&loop); | |
| 4753 // Load the type of the current stack handler. | |
| 4754 const int kStateOffset = StackHandlerConstants::kStateOffset; | |
| 4755 __ cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY)); | |
| 4756 __ j(equal, &done); | |
| 4757 // Fetch the next handler in the list. | |
| 4758 const int kNextOffset = StackHandlerConstants::kNextOffset; | |
| 4759 __ mov(esp, Operand(esp, kNextOffset)); | |
| 4760 __ jmp(&loop); | |
| 4761 __ bind(&done); | |
| 4762 | |
| 4763 // Set the top handler address to next handler past the current ENTRY handler. | |
| 4764 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 4765 __ pop(Operand::StaticVariable(handler_address)); | |
| 4766 | |
| 4767 if (type == OUT_OF_MEMORY) { | |
| 4768 // Set external caught exception to false. | |
| 4769 ExternalReference external_caught(Top::k_external_caught_exception_address); | |
| 4770 __ mov(eax, false); | |
| 4771 __ mov(Operand::StaticVariable(external_caught), eax); | |
| 4772 | |
| 4773 // Set pending exception and eax to out of memory exception. | |
| 4774 ExternalReference pending_exception(Top::k_pending_exception_address); | |
| 4775 __ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); | |
| 4776 __ mov(Operand::StaticVariable(pending_exception), eax); | |
| 4777 } | |
| 4778 | |
| 4779 // Clear the context pointer. | |
| 4780 __ Set(esi, Immediate(0)); | |
| 4781 | |
| 4782 // Restore fp from handler and discard handler state. | |
| 4783 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize); | |
| 4784 __ pop(ebp); | |
| 4785 __ pop(edx); // State. | |
| 4786 | |
| 4787 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 4788 __ ret(0); | |
| 4789 } | 4738 } |
| 4790 | 4739 |
| 4791 | 4740 |
| 4792 void CEntryStub::Generate(MacroAssembler* masm) { | 4741 void CEntryStub::Generate(MacroAssembler* masm) { |
| 4793 // eax: number of arguments including receiver | 4742 // eax: number of arguments including receiver |
| 4794 // ebx: pointer to C function (C callee-saved) | 4743 // ebx: pointer to C function (C callee-saved) |
| 4795 // ebp: frame pointer (restored after C call) | 4744 // ebp: frame pointer (restored after C call) |
| 4796 // esp: stack pointer (restored after C call) | 4745 // esp: stack pointer (restored after C call) |
| 4797 // esi: current context (C callee-saved) | 4746 // esi: current context (C callee-saved) |
| 4798 // edi: JS function of the caller (C callee-saved) | 4747 // edi: JS function of the caller (C callee-saved) |
| (...skipping 1688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6487 // Do a tail call to the rewritten stub. | 6436 // Do a tail call to the rewritten stub. |
| 6488 __ jmp(Operand(edi)); | 6437 __ jmp(Operand(edi)); |
| 6489 } | 6438 } |
| 6490 | 6439 |
| 6491 | 6440 |
| 6492 #undef __ | 6441 #undef __ |
| 6493 | 6442 |
| 6494 } } // namespace v8::internal | 6443 } } // namespace v8::internal |
| 6495 | 6444 |
| 6496 #endif // V8_TARGET_ARCH_IA32 | 6445 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |