| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 | 
| 6 | 6 | 
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" | 
| 8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" | 
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" | 
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" | 
| (...skipping 1889 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1900   __ mov_b(scratch, Operand(src, 0)); | 1900   __ mov_b(scratch, Operand(src, 0)); | 
| 1901   __ mov_b(Operand(dest, 0), scratch); | 1901   __ mov_b(Operand(dest, 0), scratch); | 
| 1902   __ inc(src); | 1902   __ inc(src); | 
| 1903   __ inc(dest); | 1903   __ inc(dest); | 
| 1904   __ dec(count); | 1904   __ dec(count); | 
| 1905   __ j(not_zero, &loop); | 1905   __ j(not_zero, &loop); | 
| 1906 | 1906 | 
| 1907   __ bind(&done); | 1907   __ bind(&done); | 
| 1908 } | 1908 } | 
| 1909 | 1909 | 
|  | 1910 | 
|  | 1911 void SubStringStub::Generate(MacroAssembler* masm) { | 
|  | 1912   Label runtime; | 
|  | 1913 | 
|  | 1914   // Stack frame on entry. | 
|  | 1915   //  esp[0]: return address | 
|  | 1916   //  esp[4]: to | 
|  | 1917   //  esp[8]: from | 
|  | 1918   //  esp[12]: string | 
|  | 1919 | 
|  | 1920   // Make sure first argument is a string. | 
|  | 1921   __ mov(eax, Operand(esp, 3 * kPointerSize)); | 
|  | 1922   STATIC_ASSERT(kSmiTag == 0); | 
|  | 1923   __ JumpIfSmi(eax, &runtime); | 
|  | 1924   Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); | 
|  | 1925   __ j(NegateCondition(is_string), &runtime); | 
|  | 1926 | 
|  | 1927   // eax: string | 
|  | 1928   // ebx: instance type | 
|  | 1929 | 
|  | 1930   // Calculate length of sub string using the smi values. | 
|  | 1931   __ mov(ecx, Operand(esp, 1 * kPointerSize));  // To index. | 
|  | 1932   __ JumpIfNotSmi(ecx, &runtime); | 
|  | 1933   __ mov(edx, Operand(esp, 2 * kPointerSize));  // From index. | 
|  | 1934   __ JumpIfNotSmi(edx, &runtime); | 
|  | 1935   __ sub(ecx, edx); | 
|  | 1936   __ cmp(ecx, FieldOperand(eax, String::kLengthOffset)); | 
|  | 1937   Label not_original_string; | 
|  | 1938   // Shorter than original string's length: an actual substring. | 
|  | 1939   __ j(below, ¬_original_string, Label::kNear); | 
|  | 1940   // Longer than original string's length or negative: unsafe arguments. | 
|  | 1941   __ j(above, &runtime); | 
|  | 1942   // Return original string. | 
|  | 1943   Counters* counters = isolate()->counters(); | 
|  | 1944   __ IncrementCounter(counters->sub_string_native(), 1); | 
|  | 1945   __ ret(3 * kPointerSize); | 
|  | 1946   __ bind(¬_original_string); | 
|  | 1947 | 
|  | 1948   Label single_char; | 
|  | 1949   __ cmp(ecx, Immediate(Smi::FromInt(1))); | 
|  | 1950   __ j(equal, &single_char); | 
|  | 1951 | 
|  | 1952   // eax: string | 
|  | 1953   // ebx: instance type | 
|  | 1954   // ecx: sub string length (smi) | 
|  | 1955   // edx: from index (smi) | 
|  | 1956   // Deal with different string types: update the index if necessary | 
|  | 1957   // and put the underlying string into edi. | 
|  | 1958   Label underlying_unpacked, sliced_string, seq_or_external_string; | 
|  | 1959   // If the string is not indirect, it can only be sequential or external. | 
|  | 1960   STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); | 
|  | 1961   STATIC_ASSERT(kIsIndirectStringMask != 0); | 
|  | 1962   __ test(ebx, Immediate(kIsIndirectStringMask)); | 
|  | 1963   __ j(zero, &seq_or_external_string, Label::kNear); | 
|  | 1964 | 
|  | 1965   Factory* factory = isolate()->factory(); | 
|  | 1966   __ test(ebx, Immediate(kSlicedNotConsMask)); | 
|  | 1967   __ j(not_zero, &sliced_string, Label::kNear); | 
|  | 1968   // Cons string.  Check whether it is flat, then fetch first part. | 
|  | 1969   // Flat cons strings have an empty second part. | 
|  | 1970   __ cmp(FieldOperand(eax, ConsString::kSecondOffset), | 
|  | 1971          factory->empty_string()); | 
|  | 1972   __ j(not_equal, &runtime); | 
|  | 1973   __ mov(edi, FieldOperand(eax, ConsString::kFirstOffset)); | 
|  | 1974   // Update instance type. | 
|  | 1975   __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset)); | 
|  | 1976   __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 
|  | 1977   __ jmp(&underlying_unpacked, Label::kNear); | 
|  | 1978 | 
|  | 1979   __ bind(&sliced_string); | 
|  | 1980   // Sliced string.  Fetch parent and adjust start index by offset. | 
|  | 1981   __ add(edx, FieldOperand(eax, SlicedString::kOffsetOffset)); | 
|  | 1982   __ mov(edi, FieldOperand(eax, SlicedString::kParentOffset)); | 
|  | 1983   // Update instance type. | 
|  | 1984   __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset)); | 
|  | 1985   __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 
|  | 1986   __ jmp(&underlying_unpacked, Label::kNear); | 
|  | 1987 | 
|  | 1988   __ bind(&seq_or_external_string); | 
|  | 1989   // Sequential or external string.  Just move string to the expected register. | 
|  | 1990   __ mov(edi, eax); | 
|  | 1991 | 
|  | 1992   __ bind(&underlying_unpacked); | 
|  | 1993 | 
|  | 1994   if (FLAG_string_slices) { | 
|  | 1995     Label copy_routine; | 
|  | 1996     // edi: underlying subject string | 
|  | 1997     // ebx: instance type of underlying subject string | 
|  | 1998     // edx: adjusted start index (smi) | 
|  | 1999     // ecx: length (smi) | 
|  | 2000     __ cmp(ecx, Immediate(Smi::FromInt(SlicedString::kMinLength))); | 
|  | 2001     // Short slice.  Copy instead of slicing. | 
|  | 2002     __ j(less, ©_routine); | 
|  | 2003     // Allocate new sliced string.  At this point we do not reload the instance | 
|  | 2004     // type including the string encoding because we simply rely on the info | 
|  | 2005     // provided by the original string.  It does not matter if the original | 
|  | 2006     // string's encoding is wrong because we always have to recheck encoding of | 
|  | 2007     // the newly created string's parent anyways due to externalized strings. | 
|  | 2008     Label two_byte_slice, set_slice_header; | 
|  | 2009     STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); | 
|  | 2010     STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); | 
|  | 2011     __ test(ebx, Immediate(kStringEncodingMask)); | 
|  | 2012     __ j(zero, &two_byte_slice, Label::kNear); | 
|  | 2013     __ AllocateOneByteSlicedString(eax, ebx, no_reg, &runtime); | 
|  | 2014     __ jmp(&set_slice_header, Label::kNear); | 
|  | 2015     __ bind(&two_byte_slice); | 
|  | 2016     __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime); | 
|  | 2017     __ bind(&set_slice_header); | 
|  | 2018     __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx); | 
|  | 2019     __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset), | 
|  | 2020            Immediate(String::kEmptyHashField)); | 
|  | 2021     __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi); | 
|  | 2022     __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx); | 
|  | 2023     __ IncrementCounter(counters->sub_string_native(), 1); | 
|  | 2024     __ ret(3 * kPointerSize); | 
|  | 2025 | 
|  | 2026     __ bind(©_routine); | 
|  | 2027   } | 
|  | 2028 | 
|  | 2029   // edi: underlying subject string | 
|  | 2030   // ebx: instance type of underlying subject string | 
|  | 2031   // edx: adjusted start index (smi) | 
|  | 2032   // ecx: length (smi) | 
|  | 2033   // The subject string can only be external or sequential string of either | 
|  | 2034   // encoding at this point. | 
|  | 2035   Label two_byte_sequential, runtime_drop_two, sequential_string; | 
|  | 2036   STATIC_ASSERT(kExternalStringTag != 0); | 
|  | 2037   STATIC_ASSERT(kSeqStringTag == 0); | 
|  | 2038   __ test_b(ebx, Immediate(kExternalStringTag)); | 
|  | 2039   __ j(zero, &sequential_string); | 
|  | 2040 | 
|  | 2041   // Handle external string. | 
|  | 2042   // Rule out short external strings. | 
|  | 2043   STATIC_ASSERT(kShortExternalStringTag != 0); | 
|  | 2044   __ test_b(ebx, Immediate(kShortExternalStringMask)); | 
|  | 2045   __ j(not_zero, &runtime); | 
|  | 2046   __ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset)); | 
|  | 2047   // Move the pointer so that offset-wise, it looks like a sequential string. | 
|  | 2048   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 
|  | 2049   __ sub(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 
|  | 2050 | 
|  | 2051   __ bind(&sequential_string); | 
|  | 2052   // Stash away (adjusted) index and (underlying) string. | 
|  | 2053   __ push(edx); | 
|  | 2054   __ push(edi); | 
|  | 2055   __ SmiUntag(ecx); | 
|  | 2056   STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 
|  | 2057   __ test_b(ebx, Immediate(kStringEncodingMask)); | 
|  | 2058   __ j(zero, &two_byte_sequential); | 
|  | 2059 | 
|  | 2060   // Sequential one byte string.  Allocate the result. | 
|  | 2061   __ AllocateOneByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two); | 
|  | 2062 | 
|  | 2063   // eax: result string | 
|  | 2064   // ecx: result string length | 
|  | 2065   // Locate first character of result. | 
|  | 2066   __ mov(edi, eax); | 
|  | 2067   __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 
|  | 2068   // Load string argument and locate character of sub string start. | 
|  | 2069   __ pop(edx); | 
|  | 2070   __ pop(ebx); | 
|  | 2071   __ SmiUntag(ebx); | 
|  | 2072   __ lea(edx, FieldOperand(edx, ebx, times_1, SeqOneByteString::kHeaderSize)); | 
|  | 2073 | 
|  | 2074   // eax: result string | 
|  | 2075   // ecx: result length | 
|  | 2076   // edi: first character of result | 
|  | 2077   // edx: character of sub string start | 
|  | 2078   StringHelper::GenerateCopyCharacters( | 
|  | 2079       masm, edi, edx, ecx, ebx, String::ONE_BYTE_ENCODING); | 
|  | 2080   __ IncrementCounter(counters->sub_string_native(), 1); | 
|  | 2081   __ ret(3 * kPointerSize); | 
|  | 2082 | 
|  | 2083   __ bind(&two_byte_sequential); | 
|  | 2084   // Sequential two-byte string.  Allocate the result. | 
|  | 2085   __ AllocateTwoByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two); | 
|  | 2086 | 
|  | 2087   // eax: result string | 
|  | 2088   // ecx: result string length | 
|  | 2089   // Locate first character of result. | 
|  | 2090   __ mov(edi, eax); | 
|  | 2091   __ add(edi, | 
|  | 2092          Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 
|  | 2093   // Load string argument and locate character of sub string start. | 
|  | 2094   __ pop(edx); | 
|  | 2095   __ pop(ebx); | 
|  | 2096   // As from is a smi it is 2 times the value which matches the size of a two | 
|  | 2097   // byte character. | 
|  | 2098   STATIC_ASSERT(kSmiTag == 0); | 
|  | 2099   STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 
|  | 2100   __ lea(edx, FieldOperand(edx, ebx, times_1, SeqTwoByteString::kHeaderSize)); | 
|  | 2101 | 
|  | 2102   // eax: result string | 
|  | 2103   // ecx: result length | 
|  | 2104   // edi: first character of result | 
|  | 2105   // edx: character of sub string start | 
|  | 2106   StringHelper::GenerateCopyCharacters( | 
|  | 2107       masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING); | 
|  | 2108   __ IncrementCounter(counters->sub_string_native(), 1); | 
|  | 2109   __ ret(3 * kPointerSize); | 
|  | 2110 | 
|  | 2111   // Drop pushed values on the stack before tail call. | 
|  | 2112   __ bind(&runtime_drop_two); | 
|  | 2113   __ Drop(2); | 
|  | 2114 | 
|  | 2115   // Just jump to runtime to create the sub string. | 
|  | 2116   __ bind(&runtime); | 
|  | 2117   __ TailCallRuntime(Runtime::kSubString); | 
|  | 2118 | 
|  | 2119   __ bind(&single_char); | 
|  | 2120   // eax: string | 
|  | 2121   // ebx: instance type | 
|  | 2122   // ecx: sub string length (smi) | 
|  | 2123   // edx: from index (smi) | 
|  | 2124   StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime, | 
|  | 2125                                   &runtime, RECEIVER_IS_STRING); | 
|  | 2126   generator.GenerateFast(masm); | 
|  | 2127   __ ret(3 * kPointerSize); | 
|  | 2128   generator.SkipSlow(masm, &runtime); | 
|  | 2129 } | 
|  | 2130 | 
| 1910 void ToStringStub::Generate(MacroAssembler* masm) { | 2131 void ToStringStub::Generate(MacroAssembler* masm) { | 
| 1911   // The ToString stub takes one argument in eax. | 2132   // The ToString stub takes one argument in eax. | 
| 1912   Label is_number; | 2133   Label is_number; | 
| 1913   __ JumpIfSmi(eax, &is_number, Label::kNear); | 2134   __ JumpIfSmi(eax, &is_number, Label::kNear); | 
| 1914 | 2135 | 
| 1915   Label not_string; | 2136   Label not_string; | 
| 1916   __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi); | 2137   __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi); | 
| 1917   // eax: receiver | 2138   // eax: receiver | 
| 1918   // edi: receiver map | 2139   // edi: receiver map | 
| 1919   __ j(above_equal, ¬_string, Label::kNear); | 2140   __ j(above_equal, ¬_string, Label::kNear); | 
| (...skipping 3162 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5082                            kStackUnwindSpace, nullptr, return_value_operand, | 5303                            kStackUnwindSpace, nullptr, return_value_operand, | 
| 5083                            NULL); | 5304                            NULL); | 
| 5084 } | 5305 } | 
| 5085 | 5306 | 
| 5086 #undef __ | 5307 #undef __ | 
| 5087 | 5308 | 
| 5088 }  // namespace internal | 5309 }  // namespace internal | 
| 5089 }  // namespace v8 | 5310 }  // namespace v8 | 
| 5090 | 5311 | 
| 5091 #endif  // V8_TARGET_ARCH_X87 | 5312 #endif  // V8_TARGET_ARCH_X87 | 
| OLD | NEW | 
|---|