Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(690)

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 524059: Speed up compares with characters ie single-character strings.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/codegen.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 1881 matching lines...) Expand 10 before | Expand all | Expand 10 after
1892 LikelySmiBinaryOperation(op, operand, &constant_operand, 1892 LikelySmiBinaryOperation(op, operand, &constant_operand,
1893 overwrite_mode); 1893 overwrite_mode);
1894 } 1894 }
1895 break; 1895 break;
1896 } 1896 }
1897 } 1897 }
1898 ASSERT(!operand->is_valid()); 1898 ASSERT(!operand->is_valid());
1899 } 1899 }
1900 1900
1901 1901
1902 static bool CouldBeNaN(const Result& result) {
1903 if (!result.is_constant()) return true;
1904 if (!result.handle()->IsHeapNumber()) return false;
1905 return isnan(HeapNumber::cast(*result.handle())->value());
1906 }
1907
1908
1902 void CodeGenerator::Comparison(AstNode* node, 1909 void CodeGenerator::Comparison(AstNode* node,
1903 Condition cc, 1910 Condition cc,
1904 bool strict, 1911 bool strict,
1905 ControlDestination* dest) { 1912 ControlDestination* dest) {
1906 // Strict only makes sense for equality comparisons. 1913 // Strict only makes sense for equality comparisons.
1907 ASSERT(!strict || cc == equal); 1914 ASSERT(!strict || cc == equal);
1908 1915
1909 Result left_side; 1916 Result left_side;
1910 Result right_side; 1917 Result right_side;
1911 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 1918 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
1912 if (cc == greater || cc == less_equal) { 1919 if (cc == greater || cc == less_equal) {
1913 cc = ReverseCondition(cc); 1920 cc = ReverseCondition(cc);
1914 left_side = frame_->Pop(); 1921 left_side = frame_->Pop();
1915 right_side = frame_->Pop(); 1922 right_side = frame_->Pop();
1916 } else { 1923 } else {
1917 right_side = frame_->Pop(); 1924 right_side = frame_->Pop();
1918 left_side = frame_->Pop(); 1925 left_side = frame_->Pop();
1919 } 1926 }
1920 ASSERT(cc == less || cc == equal || cc == greater_equal); 1927 ASSERT(cc == less || cc == equal || cc == greater_equal);
1921 1928
1922 // If either side is a constant smi, optimize the comparison. 1929 // If either side is a constant of some sort, we can probably optimize the
1923 bool left_side_constant_smi = 1930 // comparison.
1924 left_side.is_constant() && left_side.handle()->IsSmi(); 1931 bool left_side_constant_smi = false;
1925 bool right_side_constant_smi = 1932 bool left_side_constant_null = false;
1926 right_side.is_constant() && right_side.handle()->IsSmi(); 1933 bool left_side_constant_1_char_string = false;
1927 bool left_side_constant_null = 1934 if (left_side.is_constant()) {
1928 left_side.is_constant() && left_side.handle()->IsNull(); 1935 left_side_constant_smi = left_side.handle()->IsSmi();
1929 bool right_side_constant_null = 1936 left_side_constant_null = left_side.handle()->IsNull();
1930 right_side.is_constant() && right_side.handle()->IsNull(); 1937 left_side_constant_1_char_string =
1938 (left_side.handle()->IsString() &&
1939 (String::cast(*left_side.handle())->length() == 1));
1940 }
1941 bool right_side_constant_smi = false;
1942 bool right_side_constant_null = false;
1943 bool right_side_constant_1_char_string = false;
1944 if (right_side.is_constant()) {
1945 right_side_constant_smi = right_side.handle()->IsSmi();
1946 right_side_constant_null = right_side.handle()->IsNull();
1947 right_side_constant_1_char_string =
1948 (right_side.handle()->IsString() &&
1949 (String::cast(*right_side.handle())->length() == 1));
1950 }
1931 1951
1932 if (left_side_constant_smi || right_side_constant_smi) { 1952 if (left_side_constant_smi || right_side_constant_smi) {
1933 if (left_side_constant_smi && right_side_constant_smi) { 1953 if (left_side_constant_smi && right_side_constant_smi) {
1934 // Trivial case, comparing two constants. 1954 // Trivial case, comparing two constants.
1935 int left_value = Smi::cast(*left_side.handle())->value(); 1955 int left_value = Smi::cast(*left_side.handle())->value();
1936 int right_value = Smi::cast(*right_side.handle())->value(); 1956 int right_value = Smi::cast(*right_side.handle())->value();
1937 switch (cc) { 1957 switch (cc) {
1938 case less: 1958 case less:
1939 dest->Goto(left_value < right_value); 1959 dest->Goto(left_value < right_value);
1940 break; 1960 break;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2009 case greater: double_cc = above; break; 2029 case greater: double_cc = above; break;
2010 case greater_equal: double_cc = above_equal; break; 2030 case greater_equal: double_cc = above_equal; break;
2011 default: UNREACHABLE(); 2031 default: UNREACHABLE();
2012 } 2032 }
2013 dest->true_target()->Branch(double_cc); 2033 dest->true_target()->Branch(double_cc);
2014 dest->false_target()->Jump(); 2034 dest->false_target()->Jump();
2015 not_number.Bind(&left_side); 2035 not_number.Bind(&left_side);
2016 } 2036 }
2017 2037
2018 // Setup and call the compare stub. 2038 // Setup and call the compare stub.
2019 CompareStub stub(cc, strict); 2039 CompareStub stub(cc, strict, CantBothBeNaN);
2020 Result result = frame_->CallStub(&stub, &left_side, &right_side); 2040 Result result = frame_->CallStub(&stub, &left_side, &right_side);
2021 result.ToRegister(); 2041 result.ToRegister();
2022 __ cmp(result.reg(), 0); 2042 __ cmp(result.reg(), 0);
2023 result.Unuse(); 2043 result.Unuse();
2024 dest->true_target()->Branch(cc); 2044 dest->true_target()->Branch(cc);
2025 dest->false_target()->Jump(); 2045 dest->false_target()->Jump();
2026 2046
2027 is_smi.Bind(); 2047 is_smi.Bind();
2028 left_side = Result(left_reg); 2048 left_side = Result(left_reg);
2029 right_side = Result(right_val); 2049 right_side = Result(right_val);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2068 ASSERT(temp.is_valid()); 2088 ASSERT(temp.is_valid());
2069 __ mov(temp.reg(), 2089 __ mov(temp.reg(),
2070 FieldOperand(operand.reg(), HeapObject::kMapOffset)); 2090 FieldOperand(operand.reg(), HeapObject::kMapOffset));
2071 __ movzx_b(temp.reg(), 2091 __ movzx_b(temp.reg(),
2072 FieldOperand(temp.reg(), Map::kBitFieldOffset)); 2092 FieldOperand(temp.reg(), Map::kBitFieldOffset));
2073 __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable)); 2093 __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
2074 temp.Unuse(); 2094 temp.Unuse();
2075 operand.Unuse(); 2095 operand.Unuse();
2076 dest->Split(not_zero); 2096 dest->Split(not_zero);
2077 } 2097 }
2098 } else if (left_side_constant_1_char_string ||
2099 right_side_constant_1_char_string) {
2100 if (left_side_constant_1_char_string && right_side_constant_1_char_string) {
2101 // Trivial case, comparing two constants.
2102 int left_value = String::cast(*left_side.handle())->Get(0);
2103 int right_value = String::cast(*right_side.handle())->Get(0);
2104 switch (cc) {
2105 case less:
2106 dest->Goto(left_value < right_value);
2107 break;
2108 case equal:
2109 dest->Goto(left_value == right_value);
2110 break;
2111 case greater_equal:
2112 dest->Goto(left_value >= right_value);
2113 break;
2114 default:
2115 UNREACHABLE();
2116 }
2117 } else {
2118 // Only one side is a constant 1 character string.
2119 // If left side is a constant 1-character string, reverse the operands.
2120 // Since one side is a constant string, conversion order does not matter.
2121 if (left_side_constant_1_char_string) {
2122 Result temp = left_side;
2123 left_side = right_side;
2124 right_side = temp;
2125 cc = ReverseCondition(cc);
2126 // This may reintroduce greater or less_equal as the value of cc.
2127 // CompareStub and the inline code both support all values of cc.
2128 }
2129 // Implement comparison against a constant string, inlining the case
2130 // where both sides are strings.
2131 left_side.ToRegister();
2132
2133 // Here we split control flow to the stub call and inlined cases
2134 // before finally splitting it to the control destination. We use
2135 // a jump target and branching to duplicate the virtual frame at
2136 // the first split. We manually handle the off-frame references
2137 // by reconstituting them on the non-fall-through path.
2138 JumpTarget is_not_string, is_string;
2139 Register left_reg = left_side.reg();
2140 Handle<Object> right_val = right_side.handle();
2141 __ test(left_side.reg(), Immediate(kSmiTagMask));
2142 is_not_string.Branch(zero, &left_side);
2143 Result temp = allocator_->Allocate();
2144 ASSERT(temp.is_valid());
2145 __ mov(temp.reg(),
2146 FieldOperand(left_side.reg(), HeapObject::kMapOffset));
2147 __ movzx_b(temp.reg(),
2148 FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
2149 // If we are testing for equality then make use of the symbol shortcut.
2150 // Check if the right left hand side has the same type as the left hand
2151 // side (which is always a symbol).
2152 if (cc == equal) {
2153 Label not_a_symbol;
2154 ASSERT(kSymbolTag != 0);
2155 // Ensure that no non-strings have the symbol bit set.
2156 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
2157 __ test(temp.reg(), Immediate(kIsSymbolMask)); // Test the symbol bit.
2158 __ j(zero, &not_a_symbol);
2159 // They are symbols, so do identity compare.
2160 __ cmp(left_side.reg(), right_side.handle());
2161 dest->true_target()->Branch(equal);
2162 dest->false_target()->Branch(not_equal);
2163 __ bind(&not_a_symbol);
2164 }
2165 // If the receiver is not a string of the type we handle call the stub.
2166 __ and_(temp.reg(),
2167 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
2168 __ cmp(temp.reg(), kStringTag | kSeqStringTag | kAsciiStringTag);
2169 temp.Unuse();
2170 is_string.Branch(equal, &left_side);
2171
2172 // Setup and call the compare stub.
2173 is_not_string.Bind(&left_side);
2174 CompareStub stub(cc, strict, CantBothBeNaN);
2175 Result result = frame_->CallStub(&stub, &left_side, &right_side);
2176 result.ToRegister();
2177 __ cmp(result.reg(), 0);
2178 result.Unuse();
2179 dest->true_target()->Branch(cc);
2180 dest->false_target()->Jump();
2181
2182 is_string.Bind(&left_side);
2183 // Here we know we have a sequential ASCII string.
2184 left_side = Result(left_reg);
2185 right_side = Result(right_val);
2186 Result temp2 = allocator_->Allocate();
2187 ASSERT(temp2.is_valid());
2188 // Test string equality and comparison.
2189 if (cc == equal) {
2190 Label comparison_done;
2191 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2192 Immediate(1));
2193 __ j(not_equal, &comparison_done);
2194 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize),
2195 String::cast(*right_side.handle())->Get(0));
2196 __ bind(&comparison_done);
2197 } else {
2198 __ mov(temp2.reg(),
2199 FieldOperand(left_side.reg(), String::kLengthOffset));
2200 __ sub(Operand(temp2.reg()), Immediate(1));
2201 Label comparison;
2202 // If the length is 0 then our subtraction gave -1 which compares less
2203 // than any character.
2204 __ j(negative, &comparison);
2205 // Otherwise load the first character.
2206 __ movzx_b(temp2.reg(),
2207 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize));
2208 __ bind(&comparison);
2209 // Compare the first character of the string with out constant
2210 // 1-character string.
2211 __ cmp(Operand(temp2.reg()),
2212 Immediate(String::cast(*right_side.handle())->Get(0)));
2213 Label characters_were_different;
2214 __ j(not_equal, &characters_were_different);
2215 // If the first character is the same then the long string sorts after
2216 // the short one.
2217 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2218 Immediate(1));
2219 __ bind(&characters_were_different);
2220 }
2221 temp2.Unuse();
2222 left_side.Unuse();
2223 right_side.Unuse();
2224 dest->Split(cc);
2225 }
2078 } else { 2226 } else {
2079 // Neither side is a constant Smi or null. 2227 // Neither side is a constant Smi or null.
2080 // If either side is a non-smi constant, skip the smi check. 2228 // If either side is a non-smi constant, skip the smi check.
2081 bool known_non_smi = 2229 bool known_non_smi =
2082 (left_side.is_constant() && !left_side.handle()->IsSmi()) || 2230 (left_side.is_constant() && !left_side.handle()->IsSmi()) ||
2083 (right_side.is_constant() && !right_side.handle()->IsSmi()); 2231 (right_side.is_constant() && !right_side.handle()->IsSmi());
2232 NaNInformation nan_info =
2233 (CouldBeNaN(left_side) && CouldBeNaN(right_side)) ?
2234 BothCouldBeNaN :
2235 CantBothBeNaN;
2084 left_side.ToRegister(); 2236 left_side.ToRegister();
2085 right_side.ToRegister(); 2237 right_side.ToRegister();
2086 2238
2087 if (known_non_smi) { 2239 if (known_non_smi) {
2088 // When non-smi, call out to the compare stub. 2240 // When non-smi, call out to the compare stub.
2089 CompareStub stub(cc, strict); 2241 CompareStub stub(cc, strict, nan_info);
2090 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 2242 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
2091 if (cc == equal) { 2243 if (cc == equal) {
2092 __ test(answer.reg(), Operand(answer.reg())); 2244 __ test(answer.reg(), Operand(answer.reg()));
2093 } else { 2245 } else {
2094 __ cmp(answer.reg(), 0); 2246 __ cmp(answer.reg(), 0);
2095 } 2247 }
2096 answer.Unuse(); 2248 answer.Unuse();
2097 dest->Split(cc); 2249 dest->Split(cc);
2098 } else { 2250 } else {
2099 // Here we split control flow to the stub call and inlined cases 2251 // Here we split control flow to the stub call and inlined cases
2100 // before finally splitting it to the control destination. We use 2252 // before finally splitting it to the control destination. We use
2101 // a jump target and branching to duplicate the virtual frame at 2253 // a jump target and branching to duplicate the virtual frame at
2102 // the first split. We manually handle the off-frame references 2254 // the first split. We manually handle the off-frame references
2103 // by reconstituting them on the non-fall-through path. 2255 // by reconstituting them on the non-fall-through path.
2104 JumpTarget is_smi; 2256 JumpTarget is_smi;
2105 Register left_reg = left_side.reg(); 2257 Register left_reg = left_side.reg();
2106 Register right_reg = right_side.reg(); 2258 Register right_reg = right_side.reg();
2107 2259
2108 Result temp = allocator_->Allocate(); 2260 Result temp = allocator_->Allocate();
2109 ASSERT(temp.is_valid()); 2261 ASSERT(temp.is_valid());
2110 __ mov(temp.reg(), left_side.reg()); 2262 __ mov(temp.reg(), left_side.reg());
2111 __ or_(temp.reg(), Operand(right_side.reg())); 2263 __ or_(temp.reg(), Operand(right_side.reg()));
2112 __ test(temp.reg(), Immediate(kSmiTagMask)); 2264 __ test(temp.reg(), Immediate(kSmiTagMask));
2113 temp.Unuse(); 2265 temp.Unuse();
2114 is_smi.Branch(zero, taken); 2266 is_smi.Branch(zero, taken);
2115 // When non-smi, call out to the compare stub. 2267 // When non-smi, call out to the compare stub.
2116 CompareStub stub(cc, strict); 2268 CompareStub stub(cc, strict, nan_info);
2117 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 2269 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
2118 if (cc == equal) { 2270 if (cc == equal) {
2119 __ test(answer.reg(), Operand(answer.reg())); 2271 __ test(answer.reg(), Operand(answer.reg()));
2120 } else { 2272 } else {
2121 __ cmp(answer.reg(), 0); 2273 __ cmp(answer.reg(), 0);
2122 } 2274 }
2123 answer.Unuse(); 2275 answer.Unuse();
2124 dest->true_target()->Branch(cc); 2276 dest->true_target()->Branch(cc);
2125 dest->false_target()->Jump(); 2277 dest->false_target()->Jump();
2126 2278
(...skipping 6095 matching lines...) Expand 10 before | Expand all | Expand 10 after
8222 Label slow; // Fallthrough label. 8374 Label slow; // Fallthrough label.
8223 // Equality is almost reflexive (everything but NaN), so start by testing 8375 // Equality is almost reflexive (everything but NaN), so start by testing
8224 // for "identity and not NaN". 8376 // for "identity and not NaN".
8225 { 8377 {
8226 Label not_identical; 8378 Label not_identical;
8227 __ cmp(eax, Operand(edx)); 8379 __ cmp(eax, Operand(edx));
8228 __ j(not_equal, &not_identical); 8380 __ j(not_equal, &not_identical);
8229 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 8381 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
8230 // so we do the second best thing - test it ourselves. 8382 // so we do the second best thing - test it ourselves.
8231 8383
8232 Label return_equal; 8384 if (never_nan_nan_) {
8233 Label heap_number; 8385 __ Set(eax, Immediate(0));
8234 // If it's not a heap number, then return equal. 8386 __ ret(0);
8235 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 8387 } else {
8236 Immediate(Factory::heap_number_map())); 8388 Label return_equal;
8237 __ j(equal, &heap_number); 8389 Label heap_number;
8238 __ bind(&return_equal); 8390 // If it's not a heap number, then return equal.
8239 __ Set(eax, Immediate(0)); 8391 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
8240 __ ret(0); 8392 Immediate(Factory::heap_number_map()));
8393 __ j(equal, &heap_number);
8394 __ bind(&return_equal);
8395 __ Set(eax, Immediate(0));
8396 __ ret(0);
8241 8397
8242 __ bind(&heap_number); 8398 __ bind(&heap_number);
8243 // It is a heap number, so return non-equal if it's NaN and equal if it's 8399 // It is a heap number, so return non-equal if it's NaN and equal if
8244 // not NaN. 8400 // it's not NaN.
8245 // The representation of NaN values has all exponent bits (52..62) set, 8401 // The representation of NaN values has all exponent bits (52..62) set,
8246 // and not all mantissa bits (0..51) clear. 8402 // and not all mantissa bits (0..51) clear.
8247 // We only accept QNaNs, which have bit 51 set. 8403 // We only accept QNaNs, which have bit 51 set.
8248 // Read top bits of double representation (second word of value). 8404 // Read top bits of double representation (second word of value).
8249 8405
8250 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., 8406 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e.,
8251 // all bits in the mask are set. We only need to check the word 8407 // all bits in the mask are set. We only need to check the word
8252 // that contains the exponent and high bit of the mantissa. 8408 // that contains the exponent and high bit of the mantissa.
8253 ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u); 8409 ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u);
8254 __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset)); 8410 __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset));
8255 __ xor_(eax, Operand(eax)); 8411 __ xor_(eax, Operand(eax));
8256 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost bits. 8412 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost
8257 __ add(edx, Operand(edx)); 8413 // bits.
8258 __ cmp(edx, kQuietNaNHighBitsMask << 1); 8414 __ add(edx, Operand(edx));
8259 __ setcc(above_equal, eax); 8415 __ cmp(edx, kQuietNaNHighBitsMask << 1);
8260 __ ret(0); 8416 __ setcc(above_equal, eax);
8417 __ ret(0);
8418 }
8261 8419
8262 __ bind(&not_identical); 8420 __ bind(&not_identical);
8263 } 8421 }
8264 8422
8265 // If we're doing a strict equality comparison, we don't have to do 8423 // If we're doing a strict equality comparison, we don't have to do
8266 // type conversion, so we generate code to do fast comparison for objects 8424 // type conversion, so we generate code to do fast comparison for objects
8267 // and oddballs. Non-smi numbers and strings still go through the usual 8425 // and oddballs. Non-smi numbers and strings still go through the usual
8268 // slow-case code. 8426 // slow-case code.
8269 if (strict_) { 8427 if (strict_) {
8270 // If either is a Smi (we know that not both are), then they can only 8428 // If either is a Smi (we know that not both are), then they can only
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after
8975 __ bind(&is_not_instance); 9133 __ bind(&is_not_instance);
8976 __ Set(eax, Immediate(Smi::FromInt(1))); 9134 __ Set(eax, Immediate(Smi::FromInt(1)));
8977 __ ret(2 * kPointerSize); 9135 __ ret(2 * kPointerSize);
8978 9136
8979 // Slow-case: Go through the JavaScript implementation. 9137 // Slow-case: Go through the JavaScript implementation.
8980 __ bind(&slow); 9138 __ bind(&slow);
8981 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 9139 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
8982 } 9140 }
8983 9141
8984 9142
9143 // Unfortunately you have to run without snapshots to see most of these
9144 // names in the profile since most compare stubs end up in the snapshot.
9145 const char* CompareStub::GetName() {
9146 switch (cc_) {
9147 case less: return "CompareStub_LT";
9148 case greater: return "CompareStub_GT";
9149 case less_equal: return "CompareStub_LE";
9150 case greater_equal: return "CompareStub_GE";
9151 case not_equal: {
9152 if (strict_) {
9153 if (never_nan_nan_) {
9154 return "CompareStub_NE_STRICT_NO_NAN";
9155 } else {
9156 return "CompareStub_NE_STRICT";
9157 }
9158 } else {
9159 if (never_nan_nan_) {
9160 return "CompareStub_NE_NO_NAN";
9161 } else {
9162 return "CompareStub_NE";
9163 }
9164 }
9165 }
9166 case equal: {
9167 if (strict_) {
9168 if (never_nan_nan_) {
9169 return "CompareStub_EQ_STRICT_NO_NAN";
9170 } else {
9171 return "CompareStub_EQ_STRICT";
9172 }
9173 } else {
9174 if (never_nan_nan_) {
9175 return "CompareStub_EQ_NO_NAN";
9176 } else {
9177 return "CompareStub_EQ";
9178 }
9179 }
9180 }
9181 default: return "CompareStub";
9182 }
9183 }
9184
9185
8985 int CompareStub::MinorKey() { 9186 int CompareStub::MinorKey() {
8986 // Encode the two parameters in a unique 16 bit value. 9187 // Encode the three parameters in a unique 16 bit value.
8987 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 9188 ASSERT(static_cast<unsigned>(cc_) < (1 << 14));
8988 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 9189 int nnn_value = (never_nan_nan_ ? 2 : 0);
9190 if (cc_ != equal) nnn_value = 0; // Avoid duplicate stubs.
9191 return (static_cast<unsigned>(cc_) << 2) | nnn_value | (strict_ ? 1 : 0);
8989 } 9192 }
8990 9193
8991 9194
8992 void StringAddStub::Generate(MacroAssembler* masm) { 9195 void StringAddStub::Generate(MacroAssembler* masm) {
8993 Label string_add_runtime; 9196 Label string_add_runtime;
8994 9197
8995 // Load the two arguments. 9198 // Load the two arguments.
8996 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. 9199 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
8997 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. 9200 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
8998 9201
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
9372 __ ret(3 * kPointerSize); 9575 __ ret(3 * kPointerSize);
9373 9576
9374 // Just jump to runtime to create the sub string. 9577 // Just jump to runtime to create the sub string.
9375 __ bind(&runtime); 9578 __ bind(&runtime);
9376 __ TailCallRuntime(ExternalReference(Runtime::kSubString), 3, 1); 9579 __ TailCallRuntime(ExternalReference(Runtime::kSubString), 3, 1);
9377 } 9580 }
9378 9581
9379 #undef __ 9582 #undef __
9380 9583
9381 } } // namespace v8::internal 9584 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698