| 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 1906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1917 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); | 1917 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); |
| 1918 // Calculate number of capture registers (number_of_captures + 1) * 2. | 1918 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 1919 __ leal(rdx, Operand(rdx, rdx, times_1, 2)); | 1919 __ leal(rdx, Operand(rdx, rdx, times_1, 2)); |
| 1920 // Check that the static offsets vector buffer is large enough. | 1920 // Check that the static offsets vector buffer is large enough. |
| 1921 __ cmpl(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize)); | 1921 __ cmpl(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize)); |
| 1922 __ j(above, &runtime); | 1922 __ j(above, &runtime); |
| 1923 | 1923 |
| 1924 // rcx: RegExp data (FixedArray) | 1924 // rcx: RegExp data (FixedArray) |
| 1925 // rdx: Number of capture registers | 1925 // rdx: Number of capture registers |
| 1926 // Check that the second argument is a string. | 1926 // Check that the second argument is a string. |
| 1927 __ movq(rax, Operand(rsp, kSubjectOffset)); | 1927 __ movq(rdi, Operand(rsp, kSubjectOffset)); |
| 1928 __ JumpIfSmi(rax, &runtime); | 1928 __ JumpIfSmi(rdi, &runtime); |
| 1929 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); | 1929 Condition is_string = masm->IsObjectStringType(rdi, rbx, rbx); |
| 1930 __ j(NegateCondition(is_string), &runtime); | 1930 __ j(NegateCondition(is_string), &runtime); |
| 1931 | 1931 |
| 1932 // rax: Subject string. | 1932 // rdi: Subject string. |
| 1933 // rcx: RegExp data (FixedArray). | 1933 // rax: RegExp data (FixedArray). |
| 1934 // rdx: Number of capture registers. | 1934 // rdx: Number of capture registers. |
| 1935 // Check that the third argument is a positive smi less than the string | 1935 // Check that the third argument is a positive smi less than the string |
| 1936 // length. A negative value will be greater (unsigned comparison). | 1936 // length. A negative value will be greater (unsigned comparison). |
| 1937 __ movq(rbx, Operand(rsp, kPreviousIndexOffset)); | 1937 __ movq(rbx, Operand(rsp, kPreviousIndexOffset)); |
| 1938 __ JumpIfNotSmi(rbx, &runtime); | 1938 __ JumpIfNotSmi(rbx, &runtime); |
| 1939 __ SmiCompare(rbx, FieldOperand(rax, String::kLengthOffset)); | 1939 __ SmiCompare(rbx, FieldOperand(rdi, String::kLengthOffset)); |
| 1940 __ j(above_equal, &runtime); | 1940 __ j(above_equal, &runtime); |
| 1941 | 1941 |
| 1942 // rcx: RegExp data (FixedArray) | 1942 // rax: RegExp data (FixedArray) |
| 1943 // rdx: Number of capture registers | 1943 // rdx: Number of capture registers |
| 1944 // Check that the fourth object is a JSArray object. | 1944 // Check that the fourth object is a JSArray object. |
| 1945 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 1945 __ movq(rdi, Operand(rsp, kLastMatchInfoOffset)); |
| 1946 __ JumpIfSmi(rax, &runtime); | 1946 __ JumpIfSmi(rdi, &runtime); |
| 1947 __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister); | 1947 __ CmpObjectType(rdi, JS_ARRAY_TYPE, kScratchRegister); |
| 1948 __ j(not_equal, &runtime); | 1948 __ j(not_equal, &runtime); |
| 1949 // Check that the JSArray is in fast case. | 1949 // Check that the JSArray is in fast case. |
| 1950 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); | 1950 __ movq(rbx, FieldOperand(rdi, JSArray::kElementsOffset)); |
| 1951 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); | 1951 __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); |
| 1952 __ Cmp(rax, Factory::fixed_array_map()); | 1952 __ Cmp(rdi, Factory::fixed_array_map()); |
| 1953 __ j(not_equal, &runtime); | 1953 __ j(not_equal, &runtime); |
| 1954 // Check that the last match info has space for the capture registers and the | 1954 // Check that the last match info has space for the capture registers and the |
| 1955 // additional information. Ensure no overflow in add. | 1955 // additional information. Ensure no overflow in add. |
| 1956 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); | 1956 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); |
| 1957 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); | 1957 __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset)); |
| 1958 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); | 1958 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); |
| 1959 __ cmpl(rdx, rax); | 1959 __ cmpl(rdx, rdi); |
| 1960 __ j(greater, &runtime); | 1960 __ j(greater, &runtime); |
| 1961 | 1961 |
| 1962 // rcx: RegExp data (FixedArray) | 1962 // rax: RegExp data (FixedArray) |
| 1963 // Check the representation and encoding of the subject string. | 1963 // Check the representation and encoding of the subject string. |
| 1964 NearLabel seq_ascii_string, seq_two_byte_string, check_code; | 1964 NearLabel seq_ascii_string, seq_two_byte_string, check_code; |
| 1965 __ movq(rax, Operand(rsp, kSubjectOffset)); | 1965 __ movq(rdi, Operand(rsp, kSubjectOffset)); |
| 1966 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 1966 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
| 1967 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 1967 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
| 1968 // First check for flat two byte string. | 1968 // First check for flat two byte string. |
| 1969 __ andb(rbx, Immediate( | 1969 __ andb(rbx, Immediate( |
| 1970 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask)); | 1970 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask)); |
| 1971 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 1971 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |
| 1972 __ j(zero, &seq_two_byte_string); | 1972 __ j(zero, &seq_two_byte_string); |
| 1973 // Any other flat string must be a flat ascii string. | 1973 // Any other flat string must be a flat ascii string. |
| 1974 __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask)); | 1974 __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask)); |
| 1975 __ j(zero, &seq_ascii_string); | 1975 __ j(zero, &seq_ascii_string); |
| 1976 | 1976 |
| 1977 // Check for flat cons string. | 1977 // Check for flat cons string. |
| 1978 // A flat cons string is a cons string where the second part is the empty | 1978 // A flat cons string is a cons string where the second part is the empty |
| 1979 // string. In that case the subject string is just the first part of the cons | 1979 // string. In that case the subject string is just the first part of the cons |
| 1980 // string. Also in this case the first part of the cons string is known to be | 1980 // string. Also in this case the first part of the cons string is known to be |
| 1981 // a sequential string or an external string. | 1981 // a sequential string or an external string. |
| 1982 STATIC_ASSERT(kExternalStringTag !=0); | 1982 STATIC_ASSERT(kExternalStringTag !=0); |
| 1983 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); | 1983 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); |
| 1984 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag)); | 1984 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag)); |
| 1985 __ j(not_zero, &runtime); | 1985 __ j(not_zero, &runtime); |
| 1986 // String is a cons string. | 1986 // String is a cons string. |
| 1987 __ movq(rdx, FieldOperand(rax, ConsString::kSecondOffset)); | 1987 __ movq(rdx, FieldOperand(rdi, ConsString::kSecondOffset)); |
| 1988 __ Cmp(rdx, Factory::empty_string()); | 1988 __ Cmp(rdx, Factory::empty_string()); |
| 1989 __ j(not_equal, &runtime); | 1989 __ j(not_equal, &runtime); |
| 1990 __ movq(rax, FieldOperand(rax, ConsString::kFirstOffset)); | 1990 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); |
| 1991 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 1991 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
| 1992 // String is a cons string with empty second part. | 1992 // String is a cons string with empty second part. |
| 1993 // rax: first part of cons string. | 1993 // rdi: first part of cons string. |
| 1994 // rbx: map of first part of cons string. | 1994 // rbx: map of first part of cons string. |
| 1995 // Is first part a flat two byte string? | 1995 // Is first part a flat two byte string? |
| 1996 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), | 1996 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), |
| 1997 Immediate(kStringRepresentationMask | kStringEncodingMask)); | 1997 Immediate(kStringRepresentationMask | kStringEncodingMask)); |
| 1998 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | 1998 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
| 1999 __ j(zero, &seq_two_byte_string); | 1999 __ j(zero, &seq_two_byte_string); |
| 2000 // Any other flat string must be ascii. | 2000 // Any other flat string must be ascii. |
| 2001 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), | 2001 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), |
| 2002 Immediate(kStringRepresentationMask)); | 2002 Immediate(kStringRepresentationMask)); |
| 2003 __ j(not_zero, &runtime); | 2003 __ j(not_zero, &runtime); |
| 2004 | 2004 |
| 2005 __ bind(&seq_ascii_string); | 2005 __ bind(&seq_ascii_string); |
| 2006 // rax: subject string (sequential ascii) | 2006 // rdi: subject string (sequential ascii) |
| 2007 // rcx: RegExp data (FixedArray) | 2007 // rax: RegExp data (FixedArray) |
| 2008 __ movq(r11, FieldOperand(rcx, JSRegExp::kDataAsciiCodeOffset)); | 2008 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset)); |
| 2009 __ Set(rdi, 1); // Type is ascii. | 2009 __ Set(rcx, 1); // Type is ascii. |
| 2010 __ jmp(&check_code); | 2010 __ jmp(&check_code); |
| 2011 | 2011 |
| 2012 __ bind(&seq_two_byte_string); | 2012 __ bind(&seq_two_byte_string); |
| 2013 // rax: subject string (flat two-byte) | 2013 // rdi: subject string (flat two-byte) |
| 2014 // rcx: RegExp data (FixedArray) | 2014 // rax: RegExp data (FixedArray) |
| 2015 __ movq(r11, FieldOperand(rcx, JSRegExp::kDataUC16CodeOffset)); | 2015 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); |
| 2016 __ Set(rdi, 0); // Type is two byte. | 2016 __ Set(rcx, 0); // Type is two byte. |
| 2017 | 2017 |
| 2018 __ bind(&check_code); | 2018 __ bind(&check_code); |
| 2019 // Check that the irregexp code has been generated for the actual string | 2019 // Check that the irregexp code has been generated for the actual string |
| 2020 // encoding. If it has, the field contains a code object otherwise it contains | 2020 // encoding. If it has, the field contains a code object otherwise it contains |
| 2021 // the hole. | 2021 // the hole. |
| 2022 __ CmpObjectType(r11, CODE_TYPE, kScratchRegister); | 2022 __ CmpObjectType(r11, CODE_TYPE, kScratchRegister); |
| 2023 __ j(not_equal, &runtime); | 2023 __ j(not_equal, &runtime); |
| 2024 | 2024 |
| 2025 // rax: subject string | 2025 // rdi: subject string |
| 2026 // rdi: encoding of subject string (1 if ascii, 0 if two_byte); | 2026 // rcx: encoding of subject string (1 if ascii, 0 if two_byte); |
| 2027 // r11: code | 2027 // r11: code |
| 2028 // Load used arguments before starting to push arguments for call to native | 2028 // Load used arguments before starting to push arguments for call to native |
| 2029 // RegExp code to avoid handling changing stack height. | 2029 // RegExp code to avoid handling changing stack height. |
| 2030 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); | 2030 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); |
| 2031 | 2031 |
| 2032 // rax: subject string | 2032 // rdi: subject string |
| 2033 // rbx: previous index | 2033 // rbx: previous index |
| 2034 // rdi: encoding of subject string (1 if ascii 0 if two_byte); | 2034 // rcx: encoding of subject string (1 if ascii 0 if two_byte); |
| 2035 // r11: code | 2035 // r11: code |
| 2036 // All checks done. Now push arguments for native regexp code. | 2036 // All checks done. Now push arguments for native regexp code. |
| 2037 __ IncrementCounter(&Counters::regexp_entry_native, 1); | 2037 __ IncrementCounter(&Counters::regexp_entry_native, 1); |
| 2038 | 2038 |
| 2039 // rsi is caller save on Windows and used to pass parameter on Linux. | |
| 2040 __ push(rsi); | |
| 2041 | |
| 2042 static const int kRegExpExecuteArguments = 7; | 2039 static const int kRegExpExecuteArguments = 7; |
| 2043 __ PrepareCallCFunction(kRegExpExecuteArguments); | |
| 2044 int argument_slots_on_stack = | 2040 int argument_slots_on_stack = |
| 2045 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); | 2041 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); |
| 2042 __ EnterApiExitFrame(argument_slots_on_stack); // Clobbers rax! |
| 2046 | 2043 |
| 2047 // Argument 7: Indicate that this is a direct call from JavaScript. | 2044 // Argument 7: Indicate that this is a direct call from JavaScript. |
| 2048 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), | 2045 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), |
| 2049 Immediate(1)); | 2046 Immediate(1)); |
| 2050 | 2047 |
| 2051 // Argument 6: Start (high end) of backtracking stack memory area. | 2048 // Argument 6: Start (high end) of backtracking stack memory area. |
| 2052 __ movq(kScratchRegister, address_of_regexp_stack_memory_address); | 2049 __ movq(kScratchRegister, address_of_regexp_stack_memory_address); |
| 2053 __ movq(r9, Operand(kScratchRegister, 0)); | 2050 __ movq(r9, Operand(kScratchRegister, 0)); |
| 2054 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); | 2051 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); |
| 2055 __ addq(r9, Operand(kScratchRegister, 0)); | 2052 __ addq(r9, Operand(kScratchRegister, 0)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2072 Register arg2 = rdx; | 2069 Register arg2 = rdx; |
| 2073 Register arg1 = rcx; | 2070 Register arg1 = rcx; |
| 2074 #else | 2071 #else |
| 2075 Register arg4 = rcx; | 2072 Register arg4 = rcx; |
| 2076 Register arg3 = rdx; | 2073 Register arg3 = rdx; |
| 2077 Register arg2 = rsi; | 2074 Register arg2 = rsi; |
| 2078 Register arg1 = rdi; | 2075 Register arg1 = rdi; |
| 2079 #endif | 2076 #endif |
| 2080 | 2077 |
| 2081 // Keep track on aliasing between argX defined above and the registers used. | 2078 // Keep track on aliasing between argX defined above and the registers used. |
| 2082 // rax: subject string | 2079 // rdi: subject string |
| 2083 // rbx: previous index | 2080 // rbx: previous index |
| 2084 // rdi: encoding of subject string (1 if ascii 0 if two_byte); | 2081 // rcx: encoding of subject string (1 if ascii 0 if two_byte); |
| 2085 // r11: code | 2082 // r11: code |
| 2086 | 2083 |
| 2087 // Argument 4: End of string data | 2084 // Argument 4: End of string data |
| 2088 // Argument 3: Start of string data | 2085 // Argument 3: Start of string data |
| 2089 NearLabel setup_two_byte, setup_rest; | 2086 NearLabel setup_two_byte, setup_rest; |
| 2090 __ testb(rdi, rdi); | 2087 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. |
| 2091 __ j(zero, &setup_two_byte); | 2088 __ j(zero, &setup_two_byte); |
| 2092 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); | 2089 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); |
| 2093 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize)); | 2090 __ lea(arg4, FieldOperand(rdi, rcx, times_1, SeqAsciiString::kHeaderSize)); |
| 2094 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize)); | 2091 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize)); |
| 2095 __ jmp(&setup_rest); | 2092 __ jmp(&setup_rest); |
| 2096 __ bind(&setup_two_byte); | 2093 __ bind(&setup_two_byte); |
| 2097 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); | 2094 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); |
| 2098 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize)); | 2095 __ lea(arg4, FieldOperand(rdi, rcx, times_2, SeqTwoByteString::kHeaderSize)); |
| 2099 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize)); | 2096 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); |
| 2100 | 2097 |
| 2101 __ bind(&setup_rest); | 2098 __ bind(&setup_rest); |
| 2102 // Argument 2: Previous index. | 2099 // Argument 2: Previous index. |
| 2103 __ movq(arg2, rbx); | 2100 __ movq(arg2, rbx); |
| 2104 | 2101 |
| 2105 // Argument 1: Subject string. | 2102 // Argument 1: Subject string. |
| 2106 __ movq(arg1, rax); | 2103 #ifdef WIN64_ |
| 2104 __ movq(arg1, rdi); |
| 2105 #else |
| 2106 // Already there in AMD64 calling convention. |
| 2107 ASSERT(arg1.is(rdi)); |
| 2108 #endif |
| 2107 | 2109 |
| 2108 // Locate the code entry and call it. | 2110 // Locate the code entry and call it. |
| 2109 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 2111 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 2110 __ CallCFunction(r11, kRegExpExecuteArguments); | 2112 __ call(r11); |
| 2111 | 2113 |
| 2112 // rsi is caller save, as it is used to pass parameter. | 2114 __ LeaveApiExitFrame(); |
| 2113 __ pop(rsi); | |
| 2114 | 2115 |
| 2115 // Check the result. | 2116 // Check the result. |
| 2116 NearLabel success; | 2117 NearLabel success; |
| 2118 Label exception; |
| 2117 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS)); | 2119 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS)); |
| 2118 __ j(equal, &success); | 2120 __ j(equal, &success); |
| 2119 NearLabel failure; | 2121 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); |
| 2122 __ j(equal, &exception); |
| 2120 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); | 2123 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); |
| 2121 __ j(equal, &failure); | 2124 // If none of the above, it can only be retry. |
| 2122 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); | 2125 // Handle that in the runtime system. |
| 2123 // If not exception it can only be retry. Handle that in the runtime system. | |
| 2124 __ j(not_equal, &runtime); | 2126 __ j(not_equal, &runtime); |
| 2125 // Result must now be exception. If there is no pending exception already a | 2127 |
| 2126 // stack overflow (on the backtrack stack) was detected in RegExp code but | 2128 // For failure return null. |
| 2127 // haven't created the exception yet. Handle that in the runtime system. | 2129 __ LoadRoot(rax, Heap::kNullValueRootIndex); |
| 2128 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | |
| 2129 ExternalReference pending_exception_address(Top::k_pending_exception_address); | |
| 2130 __ movq(kScratchRegister, pending_exception_address); | |
| 2131 __ Cmp(kScratchRegister, Factory::the_hole_value()); | |
| 2132 __ j(equal, &runtime); | |
| 2133 __ bind(&failure); | |
| 2134 // For failure and exception return null. | |
| 2135 __ Move(rax, Factory::null_value()); | |
| 2136 __ ret(4 * kPointerSize); | 2130 __ ret(4 * kPointerSize); |
| 2137 | 2131 |
| 2138 // Load RegExp data. | 2132 // Load RegExp data. |
| 2139 __ bind(&success); | 2133 __ bind(&success); |
| 2140 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | 2134 __ movq(rax, Operand(rsp, kJSRegExpOffset)); |
| 2141 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); | 2135 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); |
| 2142 __ SmiToInteger32(rax, | 2136 __ SmiToInteger32(rax, |
| 2143 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); | 2137 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); |
| 2144 // Calculate number of capture registers (number_of_captures + 1) * 2. | 2138 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 2145 __ leal(rdx, Operand(rax, rax, times_1, 2)); | 2139 __ leal(rdx, Operand(rax, rax, times_1, 2)); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2186 times_pointer_size, | 2180 times_pointer_size, |
| 2187 RegExpImpl::kFirstCaptureOffset), | 2181 RegExpImpl::kFirstCaptureOffset), |
| 2188 rdi); | 2182 rdi); |
| 2189 __ jmp(&next_capture); | 2183 __ jmp(&next_capture); |
| 2190 __ bind(&done); | 2184 __ bind(&done); |
| 2191 | 2185 |
| 2192 // Return last match info. | 2186 // Return last match info. |
| 2193 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 2187 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); |
| 2194 __ ret(4 * kPointerSize); | 2188 __ ret(4 * kPointerSize); |
| 2195 | 2189 |
| 2190 __ bind(&exception); |
| 2191 // Result must now be exception. If there is no pending exception already a |
| 2192 // stack overflow (on the backtrack stack) was detected in RegExp code but |
| 2193 // haven't created the exception yet. Handle that in the runtime system. |
| 2194 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 2195 ExternalReference pending_exception_address(Top::k_pending_exception_address); |
| 2196 __ movq(rbx, pending_exception_address); |
| 2197 __ movq(rax, Operand(rbx, 0)); |
| 2198 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); |
| 2199 __ cmpq(rax, rdx); |
| 2200 __ j(equal, &runtime); |
| 2201 __ movq(Operand(rbx, 0), rdx); |
| 2202 |
| 2203 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); |
| 2204 NearLabel termination_exception; |
| 2205 __ j(equal, &termination_exception); |
| 2206 __ Throw(rax); |
| 2207 |
| 2208 __ bind(&termination_exception); |
| 2209 __ ThrowUncatchable(TERMINATION, rax); |
| 2210 |
| 2196 // Do the runtime call to execute the regexp. | 2211 // Do the runtime call to execute the regexp. |
| 2197 __ bind(&runtime); | 2212 __ bind(&runtime); |
| 2198 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 2213 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 2199 #endif // V8_INTERPRETED_REGEXP | 2214 #endif // V8_INTERPRETED_REGEXP |
| 2200 } | 2215 } |
| 2201 | 2216 |
| 2202 | 2217 |
| 2203 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { | 2218 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { |
| 2204 const int kMaxInlineLength = 100; | 2219 const int kMaxInlineLength = 100; |
| 2205 Label slowcase; | 2220 Label slowcase; |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2734 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi); | 2749 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi); |
| 2735 __ Set(rax, argc_); | 2750 __ Set(rax, argc_); |
| 2736 __ Set(rbx, 0); | 2751 __ Set(rbx, 0); |
| 2737 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); | 2752 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); |
| 2738 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); | 2753 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); |
| 2739 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 2754 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
| 2740 } | 2755 } |
| 2741 | 2756 |
| 2742 | 2757 |
| 2743 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 2758 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| 2744 // Check that stack should contain next handler, frame pointer, state and | 2759 // Throw exception in eax. |
| 2745 // return address in that order. | 2760 __ Throw(rax); |
| 2746 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == | |
| 2747 StackHandlerConstants::kStateOffset); | |
| 2748 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == | |
| 2749 StackHandlerConstants::kPCOffset); | |
| 2750 | |
| 2751 ExternalReference handler_address(Top::k_handler_address); | |
| 2752 __ movq(kScratchRegister, handler_address); | |
| 2753 __ movq(rsp, Operand(kScratchRegister, 0)); | |
| 2754 // get next in chain | |
| 2755 __ pop(rcx); | |
| 2756 __ movq(Operand(kScratchRegister, 0), rcx); | |
| 2757 __ pop(rbp); // pop frame pointer | |
| 2758 __ pop(rdx); // remove state | |
| 2759 | |
| 2760 // Before returning we restore the context from the frame pointer if not NULL. | |
| 2761 // The frame pointer is NULL in the exception handler of a JS entry frame. | |
| 2762 __ Set(rsi, 0); // Tentatively set context pointer to NULL | |
| 2763 NearLabel skip; | |
| 2764 __ cmpq(rbp, Immediate(0)); | |
| 2765 __ j(equal, &skip); | |
| 2766 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 2767 __ bind(&skip); | |
| 2768 __ ret(0); | |
| 2769 } | 2761 } |
| 2770 | 2762 |
| 2771 | 2763 |
| 2772 void CEntryStub::GenerateCore(MacroAssembler* masm, | 2764 void CEntryStub::GenerateCore(MacroAssembler* masm, |
| 2773 Label* throw_normal_exception, | 2765 Label* throw_normal_exception, |
| 2774 Label* throw_termination_exception, | 2766 Label* throw_termination_exception, |
| 2775 Label* throw_out_of_memory_exception, | 2767 Label* throw_out_of_memory_exception, |
| 2776 bool do_gc, | 2768 bool do_gc, |
| 2777 bool always_allocate_scope) { | 2769 bool always_allocate_scope) { |
| 2778 // rax: result parameter for PerformGC, if any. | 2770 // rax: result parameter for PerformGC, if any. |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2900 // Handle normal exception. | 2892 // Handle normal exception. |
| 2901 __ jmp(throw_normal_exception); | 2893 __ jmp(throw_normal_exception); |
| 2902 | 2894 |
| 2903 // Retry. | 2895 // Retry. |
| 2904 __ bind(&retry); | 2896 __ bind(&retry); |
| 2905 } | 2897 } |
| 2906 | 2898 |
| 2907 | 2899 |
| 2908 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, | 2900 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
| 2909 UncatchableExceptionType type) { | 2901 UncatchableExceptionType type) { |
| 2910 // Fetch top stack handler. | 2902 __ ThrowUncatchable(type, rax); |
| 2911 ExternalReference handler_address(Top::k_handler_address); | |
| 2912 __ movq(kScratchRegister, handler_address); | |
| 2913 __ movq(rsp, Operand(kScratchRegister, 0)); | |
| 2914 | |
| 2915 // Unwind the handlers until the ENTRY handler is found. | |
| 2916 NearLabel loop, done; | |
| 2917 __ bind(&loop); | |
| 2918 // Load the type of the current stack handler. | |
| 2919 const int kStateOffset = StackHandlerConstants::kStateOffset; | |
| 2920 __ cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY)); | |
| 2921 __ j(equal, &done); | |
| 2922 // Fetch the next handler in the list. | |
| 2923 const int kNextOffset = StackHandlerConstants::kNextOffset; | |
| 2924 __ movq(rsp, Operand(rsp, kNextOffset)); | |
| 2925 __ jmp(&loop); | |
| 2926 __ bind(&done); | |
| 2927 | |
| 2928 // Set the top handler address to next handler past the current ENTRY handler. | |
| 2929 __ movq(kScratchRegister, handler_address); | |
| 2930 __ pop(Operand(kScratchRegister, 0)); | |
| 2931 | |
| 2932 if (type == OUT_OF_MEMORY) { | |
| 2933 // Set external caught exception to false. | |
| 2934 ExternalReference external_caught(Top::k_external_caught_exception_address); | |
| 2935 __ movq(rax, Immediate(false)); | |
| 2936 __ store_rax(external_caught); | |
| 2937 | |
| 2938 // Set pending exception and rax to out of memory exception. | |
| 2939 ExternalReference pending_exception(Top::k_pending_exception_address); | |
| 2940 __ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); | |
| 2941 __ store_rax(pending_exception); | |
| 2942 } | |
| 2943 | |
| 2944 // Clear the context pointer. | |
| 2945 __ Set(rsi, 0); | |
| 2946 | |
| 2947 // Restore registers from handler. | |
| 2948 STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize == | |
| 2949 StackHandlerConstants::kFPOffset); | |
| 2950 __ pop(rbp); // FP | |
| 2951 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == | |
| 2952 StackHandlerConstants::kStateOffset); | |
| 2953 __ pop(rdx); // State | |
| 2954 | |
| 2955 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == | |
| 2956 StackHandlerConstants::kPCOffset); | |
| 2957 __ ret(0); | |
| 2958 } | 2903 } |
| 2959 | 2904 |
| 2960 | 2905 |
| 2961 void CEntryStub::Generate(MacroAssembler* masm) { | 2906 void CEntryStub::Generate(MacroAssembler* masm) { |
| 2962 // rax: number of arguments including receiver | 2907 // rax: number of arguments including receiver |
| 2963 // rbx: pointer to C function (C callee-saved) | 2908 // rbx: pointer to C function (C callee-saved) |
| 2964 // rbp: frame pointer of calling JS frame (restored after C call) | 2909 // rbp: frame pointer of calling JS frame (restored after C call) |
| 2965 // rsp: stack pointer (restored after C call) | 2910 // rsp: stack pointer (restored after C call) |
| 2966 // rsi: current context (restored) | 2911 // rsi: current context (restored) |
| 2967 | 2912 |
| (...skipping 1422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4390 | 4335 |
| 4391 // Do a tail call to the rewritten stub. | 4336 // Do a tail call to the rewritten stub. |
| 4392 __ jmp(rdi); | 4337 __ jmp(rdi); |
| 4393 } | 4338 } |
| 4394 | 4339 |
| 4395 #undef __ | 4340 #undef __ |
| 4396 | 4341 |
| 4397 } } // namespace v8::internal | 4342 } } // namespace v8::internal |
| 4398 | 4343 |
| 4399 #endif // V8_TARGET_ARCH_X64 | 4344 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |