OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 2023 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2034 deferred = new DeferredInlineSmiAdd(operand->reg(), | 2034 deferred = new DeferredInlineSmiAdd(operand->reg(), |
2035 operand->type_info(), | 2035 operand->type_info(), |
2036 smi_value, | 2036 smi_value, |
2037 overwrite_mode); | 2037 overwrite_mode); |
2038 } | 2038 } |
2039 __ add(Operand(operand->reg()), Immediate(value)); | 2039 __ add(Operand(operand->reg()), Immediate(value)); |
2040 deferred->Branch(overflow); | 2040 deferred->Branch(overflow); |
2041 if (!operand->type_info().IsSmi()) { | 2041 if (!operand->type_info().IsSmi()) { |
2042 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2042 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2043 deferred->Branch(not_zero); | 2043 deferred->Branch(not_zero); |
2044 } else { | 2044 } else if (FLAG_debug_code) { |
2045 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2045 __ AbortIfNotSmi(operand->reg()); |
2046 } | 2046 } |
2047 deferred->BindExit(); | 2047 deferred->BindExit(); |
2048 answer = *operand; | 2048 answer = *operand; |
2049 break; | 2049 break; |
2050 } | 2050 } |
2051 | 2051 |
2052 case Token::SUB: { | 2052 case Token::SUB: { |
2053 DeferredCode* deferred = NULL; | 2053 DeferredCode* deferred = NULL; |
2054 if (reversed) { | 2054 if (reversed) { |
2055 // The reversed case is only hit when the right operand is not a | 2055 // The reversed case is only hit when the right operand is not a |
(...skipping 17 matching lines...) Expand all Loading... |
2073 deferred = new DeferredInlineSmiSub(operand->reg(), | 2073 deferred = new DeferredInlineSmiSub(operand->reg(), |
2074 operand->type_info(), | 2074 operand->type_info(), |
2075 smi_value, | 2075 smi_value, |
2076 overwrite_mode); | 2076 overwrite_mode); |
2077 __ sub(Operand(operand->reg()), Immediate(value)); | 2077 __ sub(Operand(operand->reg()), Immediate(value)); |
2078 } | 2078 } |
2079 deferred->Branch(overflow); | 2079 deferred->Branch(overflow); |
2080 if (!operand->type_info().IsSmi()) { | 2080 if (!operand->type_info().IsSmi()) { |
2081 __ test(answer.reg(), Immediate(kSmiTagMask)); | 2081 __ test(answer.reg(), Immediate(kSmiTagMask)); |
2082 deferred->Branch(not_zero); | 2082 deferred->Branch(not_zero); |
2083 } else { | 2083 } else if (FLAG_debug_code) { |
2084 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2084 __ AbortIfNotSmi(operand->reg()); |
2085 } | 2085 } |
2086 deferred->BindExit(); | 2086 deferred->BindExit(); |
2087 operand->Unuse(); | 2087 operand->Unuse(); |
2088 break; | 2088 break; |
2089 } | 2089 } |
2090 | 2090 |
2091 case Token::SAR: | 2091 case Token::SAR: |
2092 if (reversed) { | 2092 if (reversed) { |
2093 Result constant_operand(value); | 2093 Result constant_operand(value); |
2094 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, | 2094 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
(...skipping 13 matching lines...) Expand all Loading... |
2108 smi_value, | 2108 smi_value, |
2109 overwrite_mode); | 2109 overwrite_mode); |
2110 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2110 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2111 deferred->Branch(not_zero); | 2111 deferred->Branch(not_zero); |
2112 if (shift_value > 0) { | 2112 if (shift_value > 0) { |
2113 __ sar(operand->reg(), shift_value); | 2113 __ sar(operand->reg(), shift_value); |
2114 __ and_(operand->reg(), ~kSmiTagMask); | 2114 __ and_(operand->reg(), ~kSmiTagMask); |
2115 } | 2115 } |
2116 deferred->BindExit(); | 2116 deferred->BindExit(); |
2117 } else { | 2117 } else { |
2118 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2118 if (FLAG_debug_code) { |
| 2119 __ AbortIfNotSmi(operand->reg()); |
| 2120 } |
2119 if (shift_value > 0) { | 2121 if (shift_value > 0) { |
2120 __ sar(operand->reg(), shift_value); | 2122 __ sar(operand->reg(), shift_value); |
2121 __ and_(operand->reg(), ~kSmiTagMask); | 2123 __ and_(operand->reg(), ~kSmiTagMask); |
2122 } | 2124 } |
2123 } | 2125 } |
2124 answer = *operand; | 2126 answer = *operand; |
2125 } | 2127 } |
2126 break; | 2128 break; |
2127 | 2129 |
2128 case Token::SHR: | 2130 case Token::SHR: |
(...skipping 11 matching lines...) Expand all Loading... |
2140 DeferredInlineSmiOperation* deferred = | 2142 DeferredInlineSmiOperation* deferred = |
2141 new DeferredInlineSmiOperation(op, | 2143 new DeferredInlineSmiOperation(op, |
2142 answer.reg(), | 2144 answer.reg(), |
2143 operand->reg(), | 2145 operand->reg(), |
2144 operand->type_info(), | 2146 operand->type_info(), |
2145 smi_value, | 2147 smi_value, |
2146 overwrite_mode); | 2148 overwrite_mode); |
2147 if (!operand->type_info().IsSmi()) { | 2149 if (!operand->type_info().IsSmi()) { |
2148 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2150 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2149 deferred->Branch(not_zero); | 2151 deferred->Branch(not_zero); |
2150 } else { | 2152 } else if (FLAG_debug_code) { |
2151 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2153 __ AbortIfNotSmi(operand->reg()); |
2152 } | 2154 } |
2153 __ mov(answer.reg(), operand->reg()); | 2155 __ mov(answer.reg(), operand->reg()); |
2154 __ SmiUntag(answer.reg()); | 2156 __ SmiUntag(answer.reg()); |
2155 __ shr(answer.reg(), shift_value); | 2157 __ shr(answer.reg(), shift_value); |
2156 // A negative Smi shifted right two is in the positive Smi range. | 2158 // A negative Smi shifted right two is in the positive Smi range. |
2157 if (shift_value < 2) { | 2159 if (shift_value < 2) { |
2158 __ test(answer.reg(), Immediate(0xc0000000)); | 2160 __ test(answer.reg(), Immediate(0xc0000000)); |
2159 deferred->Branch(not_zero); | 2161 deferred->Branch(not_zero); |
2160 } | 2162 } |
2161 operand->Unuse(); | 2163 operand->Unuse(); |
2162 __ SmiTag(answer.reg()); | 2164 __ SmiTag(answer.reg()); |
2163 deferred->BindExit(); | 2165 deferred->BindExit(); |
2164 } | 2166 } |
2165 break; | 2167 break; |
2166 | 2168 |
2167 case Token::SHL: | 2169 case Token::SHL: |
2168 if (reversed) { | 2170 if (reversed) { |
| 2171 // Move operand into ecx and also into a second register. |
| 2172 // If operand is already in a register, take advantage of that. |
| 2173 // This lets us modify ecx, but still bail out to deferred code. |
2169 Result right; | 2174 Result right; |
2170 Result right_copy_in_ecx; | 2175 Result right_copy_in_ecx; |
2171 | 2176 TypeInfo right_type_info = operand->type_info(); |
2172 // Make sure to get a copy of the right operand into ecx. This | |
2173 // allows us to modify it without having to restore it in the | |
2174 // deferred code. | |
2175 operand->ToRegister(); | 2177 operand->ToRegister(); |
2176 if (operand->reg().is(ecx)) { | 2178 if (operand->reg().is(ecx)) { |
2177 right = allocator()->Allocate(); | 2179 right = allocator()->Allocate(); |
2178 __ mov(right.reg(), ecx); | 2180 __ mov(right.reg(), ecx); |
2179 frame_->Spill(ecx); | 2181 frame_->Spill(ecx); |
2180 right_copy_in_ecx = *operand; | 2182 right_copy_in_ecx = *operand; |
2181 } else { | 2183 } else { |
2182 right_copy_in_ecx = allocator()->Allocate(ecx); | 2184 right_copy_in_ecx = allocator()->Allocate(ecx); |
2183 __ mov(ecx, operand->reg()); | 2185 __ mov(ecx, operand->reg()); |
2184 right = *operand; | 2186 right = *operand; |
2185 } | 2187 } |
2186 operand->Unuse(); | 2188 operand->Unuse(); |
2187 | 2189 |
2188 answer = allocator()->Allocate(); | 2190 answer = allocator()->Allocate(); |
2189 DeferredInlineSmiOperationReversed* deferred = | 2191 DeferredInlineSmiOperationReversed* deferred = |
2190 new DeferredInlineSmiOperationReversed(op, | 2192 new DeferredInlineSmiOperationReversed(op, |
2191 answer.reg(), | 2193 answer.reg(), |
2192 smi_value, | 2194 smi_value, |
2193 right.reg(), | 2195 right.reg(), |
2194 right.type_info(), | 2196 right_type_info, |
2195 overwrite_mode); | 2197 overwrite_mode); |
2196 __ mov(answer.reg(), Immediate(int_value)); | 2198 __ mov(answer.reg(), Immediate(int_value)); |
2197 __ sar(ecx, kSmiTagSize); | 2199 __ sar(ecx, kSmiTagSize); |
2198 if (!right.type_info().IsSmi()) { | 2200 if (!right.type_info().IsSmi()) { |
2199 deferred->Branch(carry); | 2201 deferred->Branch(carry); |
2200 } else { | 2202 } else if (FLAG_debug_code) { |
2201 if (FLAG_debug_code) __ AbortIfNotSmi(right.reg()); | 2203 __ AbortIfNotSmi(right.reg()); |
2202 } | 2204 } |
2203 __ shl_cl(answer.reg()); | 2205 __ shl_cl(answer.reg()); |
2204 __ cmp(answer.reg(), 0xc0000000); | 2206 __ cmp(answer.reg(), 0xc0000000); |
2205 deferred->Branch(sign); | 2207 deferred->Branch(sign); |
2206 __ SmiTag(answer.reg()); | 2208 __ SmiTag(answer.reg()); |
2207 | 2209 |
2208 deferred->BindExit(); | 2210 deferred->BindExit(); |
2209 } else { | 2211 } else { |
2210 // Only the least significant 5 bits of the shift value are used. | 2212 // Only the least significant 5 bits of the shift value are used. |
2211 // In the slow case, this masking is done inside the runtime call. | 2213 // In the slow case, this masking is done inside the runtime call. |
(...skipping 20 matching lines...) Expand all Loading... |
2232 DeferredInlineSmiOperation* deferred = | 2234 DeferredInlineSmiOperation* deferred = |
2233 new DeferredInlineSmiOperation(op, | 2235 new DeferredInlineSmiOperation(op, |
2234 answer.reg(), | 2236 answer.reg(), |
2235 operand->reg(), | 2237 operand->reg(), |
2236 operand->type_info(), | 2238 operand->type_info(), |
2237 smi_value, | 2239 smi_value, |
2238 overwrite_mode); | 2240 overwrite_mode); |
2239 if (!operand->type_info().IsSmi()) { | 2241 if (!operand->type_info().IsSmi()) { |
2240 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2242 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2241 deferred->Branch(not_zero); | 2243 deferred->Branch(not_zero); |
2242 } else { | 2244 } else if (FLAG_debug_code) { |
2243 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2245 __ AbortIfNotSmi(operand->reg()); |
2244 } | 2246 } |
2245 __ mov(answer.reg(), operand->reg()); | 2247 __ mov(answer.reg(), operand->reg()); |
2246 ASSERT(kSmiTag == 0); // adjust code if not the case | 2248 ASSERT(kSmiTag == 0); // adjust code if not the case |
2247 // We do no shifts, only the Smi conversion, if shift_value is 1. | 2249 // We do no shifts, only the Smi conversion, if shift_value is 1. |
2248 if (shift_value > 1) { | 2250 if (shift_value > 1) { |
2249 __ shl(answer.reg(), shift_value - 1); | 2251 __ shl(answer.reg(), shift_value - 1); |
2250 } | 2252 } |
2251 // Convert int result to Smi, checking that it is in int range. | 2253 // Convert int result to Smi, checking that it is in int range. |
2252 ASSERT(kSmiTagSize == 1); // adjust code if not the case | 2254 ASSERT(kSmiTagSize == 1); // adjust code if not the case |
2253 __ add(answer.reg(), Operand(answer.reg())); | 2255 __ add(answer.reg(), Operand(answer.reg())); |
(...skipping 22 matching lines...) Expand all Loading... |
2276 deferred = new DeferredInlineSmiOperation(op, | 2278 deferred = new DeferredInlineSmiOperation(op, |
2277 operand->reg(), | 2279 operand->reg(), |
2278 operand->reg(), | 2280 operand->reg(), |
2279 operand->type_info(), | 2281 operand->type_info(), |
2280 smi_value, | 2282 smi_value, |
2281 overwrite_mode); | 2283 overwrite_mode); |
2282 } | 2284 } |
2283 if (!operand->type_info().IsSmi()) { | 2285 if (!operand->type_info().IsSmi()) { |
2284 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2286 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2285 deferred->Branch(not_zero); | 2287 deferred->Branch(not_zero); |
2286 } else { | 2288 } else if (FLAG_debug_code) { |
2287 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2289 __ AbortIfNotSmi(operand->reg()); |
2288 } | 2290 } |
2289 if (op == Token::BIT_AND) { | 2291 if (op == Token::BIT_AND) { |
2290 __ and_(Operand(operand->reg()), Immediate(value)); | 2292 __ and_(Operand(operand->reg()), Immediate(value)); |
2291 } else if (op == Token::BIT_XOR) { | 2293 } else if (op == Token::BIT_XOR) { |
2292 if (int_value != 0) { | 2294 if (int_value != 0) { |
2293 __ xor_(Operand(operand->reg()), Immediate(value)); | 2295 __ xor_(Operand(operand->reg()), Immediate(value)); |
2294 } | 2296 } |
2295 } else { | 2297 } else { |
2296 ASSERT(op == Token::BIT_OR); | 2298 ASSERT(op == Token::BIT_OR); |
2297 if (int_value != 0) { | 2299 if (int_value != 0) { |
(...skipping 10748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13046 | 13048 |
13047 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 13049 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
13048 // tagged as a small integer. | 13050 // tagged as a small integer. |
13049 __ bind(&runtime); | 13051 __ bind(&runtime); |
13050 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 13052 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
13051 } | 13053 } |
13052 | 13054 |
13053 #undef __ | 13055 #undef __ |
13054 | 13056 |
13055 } } // namespace v8::internal | 13057 } } // namespace v8::internal |
OLD | NEW |