| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 } | 392 } |
| 393 | 393 |
| 394 | 394 |
| 395 void CompareIC::Clear(Address address, Code* target) { | 395 void CompareIC::Clear(Address address, Code* target) { |
| 396 ASSERT(target->major_key() == CodeStub::CompareIC); | 396 ASSERT(target->major_key() == CodeStub::CompareIC); |
| 397 CompareIC::State handler_state; | 397 CompareIC::State handler_state; |
| 398 Token::Value op; | 398 Token::Value op; |
| 399 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, | 399 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, |
| 400 &handler_state, &op); | 400 &handler_state, &op); |
| 401 // Only clear CompareICs that can retain objects. | 401 // Only clear CompareICs that can retain objects. |
| 402 if (handler_state != KNOWN_OBJECTS) return; | 402 if (handler_state != KNOWN_OBJECT) return; |
| 403 SetTargetAtAddress(address, GetRawUninitialized(op)); | 403 SetTargetAtAddress(address, GetRawUninitialized(op)); |
| 404 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 404 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
| 405 } | 405 } |
| 406 | 406 |
| 407 | 407 |
| 408 static bool HasInterceptorGetter(JSObject* object) { | 408 static bool HasInterceptorGetter(JSObject* object) { |
| 409 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | 409 return !object->GetNamedInterceptor()->getter()->IsUndefined(); |
| 410 } | 410 } |
| 411 | 411 |
| 412 | 412 |
| (...skipping 1618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2031 | 2031 |
| 2032 void UnaryOpIC::patch(Code* code) { | 2032 void UnaryOpIC::patch(Code* code) { |
| 2033 set_target(code); | 2033 set_target(code); |
| 2034 } | 2034 } |
| 2035 | 2035 |
| 2036 | 2036 |
| 2037 const char* UnaryOpIC::GetName(TypeInfo type_info) { | 2037 const char* UnaryOpIC::GetName(TypeInfo type_info) { |
| 2038 switch (type_info) { | 2038 switch (type_info) { |
| 2039 case UNINITIALIZED: return "Uninitialized"; | 2039 case UNINITIALIZED: return "Uninitialized"; |
| 2040 case SMI: return "Smi"; | 2040 case SMI: return "Smi"; |
| 2041 case HEAP_NUMBER: return "HeapNumbers"; | 2041 case NUMBER: return "Number"; |
| 2042 case GENERIC: return "Generic"; | 2042 case GENERIC: return "Generic"; |
| 2043 default: return "Invalid"; | 2043 default: return "Invalid"; |
| 2044 } | 2044 } |
| 2045 } | 2045 } |
| 2046 | 2046 |
| 2047 | 2047 |
| 2048 UnaryOpIC::State UnaryOpIC::ToState(TypeInfo type_info) { | 2048 UnaryOpIC::State UnaryOpIC::ToState(TypeInfo type_info) { |
| 2049 switch (type_info) { | 2049 switch (type_info) { |
| 2050 case UNINITIALIZED: | 2050 case UNINITIALIZED: |
| 2051 return ::v8::internal::UNINITIALIZED; | 2051 return ::v8::internal::UNINITIALIZED; |
| 2052 case SMI: | 2052 case SMI: |
| 2053 case HEAP_NUMBER: | 2053 case NUMBER: |
| 2054 return MONOMORPHIC; | 2054 return MONOMORPHIC; |
| 2055 case GENERIC: | 2055 case GENERIC: |
| 2056 return ::v8::internal::GENERIC; | 2056 return ::v8::internal::GENERIC; |
| 2057 } | 2057 } |
| 2058 UNREACHABLE(); | 2058 UNREACHABLE(); |
| 2059 return ::v8::internal::UNINITIALIZED; | 2059 return ::v8::internal::UNINITIALIZED; |
| 2060 } | 2060 } |
| 2061 | 2061 |
| 2062 UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) { | 2062 UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) { |
| 2063 ::v8::internal::TypeInfo operand_type = | 2063 ::v8::internal::TypeInfo operand_type = |
| 2064 ::v8::internal::TypeInfo::TypeFromValue(operand); | 2064 ::v8::internal::TypeInfo::TypeFromValue(operand); |
| 2065 if (operand_type.IsSmi()) { | 2065 if (operand_type.IsSmi()) { |
| 2066 return SMI; | 2066 return SMI; |
| 2067 } else if (operand_type.IsNumber()) { | 2067 } else if (operand_type.IsNumber()) { |
| 2068 return HEAP_NUMBER; | 2068 return NUMBER; |
| 2069 } else { | 2069 } else { |
| 2070 return GENERIC; | 2070 return GENERIC; |
| 2071 } | 2071 } |
| 2072 } | 2072 } |
| 2073 | 2073 |
| 2074 | 2074 |
| 2075 UnaryOpIC::TypeInfo UnaryOpIC::ComputeNewType( | 2075 UnaryOpIC::TypeInfo UnaryOpIC::ComputeNewType( |
| 2076 UnaryOpIC::TypeInfo current_type, | 2076 TypeInfo current_type, |
| 2077 UnaryOpIC::TypeInfo previous_type) { | 2077 TypeInfo previous_type) { |
| 2078 switch (previous_type) { | 2078 switch (previous_type) { |
| 2079 case UnaryOpIC::UNINITIALIZED: | 2079 case UNINITIALIZED: |
| 2080 return current_type; | 2080 return current_type; |
| 2081 case UnaryOpIC::SMI: | 2081 case SMI: |
| 2082 return (current_type == UnaryOpIC::GENERIC) | 2082 return (current_type == GENERIC) ? GENERIC : NUMBER; |
| 2083 ? UnaryOpIC::GENERIC | 2083 case NUMBER: |
| 2084 : UnaryOpIC::HEAP_NUMBER; | 2084 return GENERIC; |
| 2085 case UnaryOpIC::HEAP_NUMBER: | 2085 case GENERIC: |
| 2086 return UnaryOpIC::GENERIC; | |
| 2087 case UnaryOpIC::GENERIC: | |
| 2088 // We should never do patching if we are in GENERIC state. | 2086 // We should never do patching if we are in GENERIC state. |
| 2089 UNREACHABLE(); | 2087 UNREACHABLE(); |
| 2090 return UnaryOpIC::GENERIC; | 2088 return GENERIC; |
| 2091 } | 2089 } |
| 2092 UNREACHABLE(); | 2090 UNREACHABLE(); |
| 2093 return UnaryOpIC::GENERIC; | 2091 return GENERIC; |
| 2094 } | 2092 } |
| 2095 | 2093 |
| 2096 | 2094 |
| 2097 void BinaryOpIC::patch(Code* code) { | 2095 void BinaryOpIC::patch(Code* code) { |
| 2098 set_target(code); | 2096 set_target(code); |
| 2099 } | 2097 } |
| 2100 | 2098 |
| 2101 | 2099 |
| 2102 const char* BinaryOpIC::GetName(TypeInfo type_info) { | 2100 const char* BinaryOpIC::GetName(TypeInfo type_info) { |
| 2103 switch (type_info) { | 2101 switch (type_info) { |
| 2104 case UNINITIALIZED: return "Uninitialized"; | 2102 case UNINITIALIZED: return "Uninitialized"; |
| 2105 case SMI: return "SMI"; | 2103 case SMI: return "Smi"; |
| 2106 case INT32: return "Int32"; | 2104 case INT32: return "Int32"; |
| 2107 case HEAP_NUMBER: return "HeapNumber"; | 2105 case NUMBER: return "Number"; |
| 2108 case ODDBALL: return "Oddball"; | 2106 case ODDBALL: return "Oddball"; |
| 2109 case STRING: return "String"; | 2107 case STRING: return "String"; |
| 2110 case GENERIC: return "Generic"; | 2108 case GENERIC: return "Generic"; |
| 2111 default: return "Invalid"; | 2109 default: return "Invalid"; |
| 2112 } | 2110 } |
| 2113 } | 2111 } |
| 2114 | 2112 |
| 2115 | 2113 |
| 2116 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) { | 2114 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) { |
| 2117 switch (type_info) { | 2115 switch (type_info) { |
| 2118 case UNINITIALIZED: | 2116 case UNINITIALIZED: |
| 2119 return ::v8::internal::UNINITIALIZED; | 2117 return ::v8::internal::UNINITIALIZED; |
| 2120 case SMI: | 2118 case SMI: |
| 2121 case INT32: | 2119 case INT32: |
| 2122 case HEAP_NUMBER: | 2120 case NUMBER: |
| 2123 case ODDBALL: | 2121 case ODDBALL: |
| 2124 case STRING: | 2122 case STRING: |
| 2125 return MONOMORPHIC; | 2123 return MONOMORPHIC; |
| 2126 case GENERIC: | 2124 case GENERIC: |
| 2127 return ::v8::internal::GENERIC; | 2125 return ::v8::internal::GENERIC; |
| 2128 } | 2126 } |
| 2129 UNREACHABLE(); | 2127 UNREACHABLE(); |
| 2130 return ::v8::internal::UNINITIALIZED; | 2128 return ::v8::internal::UNINITIALIZED; |
| 2131 } | 2129 } |
| 2132 | 2130 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2188 | 2186 |
| 2189 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value, | 2187 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value, |
| 2190 Token::Value op) { | 2188 Token::Value op) { |
| 2191 ::v8::internal::TypeInfo type = | 2189 ::v8::internal::TypeInfo type = |
| 2192 ::v8::internal::TypeInfo::TypeFromValue(value); | 2190 ::v8::internal::TypeInfo::TypeFromValue(value); |
| 2193 if (type.IsSmi()) return BinaryOpIC::SMI; | 2191 if (type.IsSmi()) return BinaryOpIC::SMI; |
| 2194 if (type.IsInteger32()) { | 2192 if (type.IsInteger32()) { |
| 2195 if (kSmiValueSize == 32) return BinaryOpIC::SMI; | 2193 if (kSmiValueSize == 32) return BinaryOpIC::SMI; |
| 2196 return BinaryOpIC::INT32; | 2194 return BinaryOpIC::INT32; |
| 2197 } | 2195 } |
| 2198 if (type.IsNumber()) return BinaryOpIC::HEAP_NUMBER; | 2196 if (type.IsNumber()) return BinaryOpIC::NUMBER; |
| 2199 if (type.IsString()) return BinaryOpIC::STRING; | 2197 if (type.IsString()) return BinaryOpIC::STRING; |
| 2200 if (value->IsUndefined()) { | 2198 if (value->IsUndefined()) { |
| 2201 if (op == Token::BIT_AND || | 2199 if (op == Token::BIT_AND || |
| 2202 op == Token::BIT_OR || | 2200 op == Token::BIT_OR || |
| 2203 op == Token::BIT_XOR || | 2201 op == Token::BIT_XOR || |
| 2204 op == Token::SAR || | 2202 op == Token::SAR || |
| 2205 op == Token::SHL || | 2203 op == Token::SHL || |
| 2206 op == Token::SHR) { | 2204 op == Token::SHR) { |
| 2207 if (kSmiValueSize == 32) return BinaryOpIC::SMI; | 2205 if (kSmiValueSize == 32) return BinaryOpIC::SMI; |
| 2208 return BinaryOpIC::INT32; | 2206 return BinaryOpIC::INT32; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2252 | 2250 |
| 2253 if (new_overall == BinaryOpIC::SMI && previous_overall == BinaryOpIC::SMI) { | 2251 if (new_overall == BinaryOpIC::SMI && previous_overall == BinaryOpIC::SMI) { |
| 2254 if (op == Token::DIV || | 2252 if (op == Token::DIV || |
| 2255 op == Token::MUL || | 2253 op == Token::MUL || |
| 2256 op == Token::SHR || | 2254 op == Token::SHR || |
| 2257 kSmiValueSize == 32) { | 2255 kSmiValueSize == 32) { |
| 2258 // Arithmetic on two Smi inputs has yielded a heap number. | 2256 // Arithmetic on two Smi inputs has yielded a heap number. |
| 2259 // That is the only way to get here from the Smi stub. | 2257 // That is the only way to get here from the Smi stub. |
| 2260 // With 32-bit Smis, all overflows give heap numbers, but with | 2258 // With 32-bit Smis, all overflows give heap numbers, but with |
| 2261 // 31-bit Smis, most operations overflow to int32 results. | 2259 // 31-bit Smis, most operations overflow to int32 results. |
| 2262 result_type = BinaryOpIC::HEAP_NUMBER; | 2260 result_type = BinaryOpIC::NUMBER; |
| 2263 } else { | 2261 } else { |
| 2264 // Other operations on SMIs that overflow yield int32s. | 2262 // Other operations on SMIs that overflow yield int32s. |
| 2265 result_type = BinaryOpIC::INT32; | 2263 result_type = BinaryOpIC::INT32; |
| 2266 } | 2264 } |
| 2267 } | 2265 } |
| 2268 if (new_overall == BinaryOpIC::INT32 && | 2266 if (new_overall == BinaryOpIC::INT32 && |
| 2269 previous_overall == BinaryOpIC::INT32) { | 2267 previous_overall == BinaryOpIC::INT32) { |
| 2270 if (new_left == previous_left && new_right == previous_right) { | 2268 if (new_left == previous_left && new_right == previous_right) { |
| 2271 result_type = BinaryOpIC::HEAP_NUMBER; | 2269 result_type = BinaryOpIC::NUMBER; |
| 2272 } | 2270 } |
| 2273 } | 2271 } |
| 2274 | 2272 |
| 2275 BinaryOpStub stub(key, new_left, new_right, result_type); | 2273 BinaryOpStub stub(key, new_left, new_right, result_type); |
| 2276 Handle<Code> code = stub.GetCode(); | 2274 Handle<Code> code = stub.GetCode(); |
| 2277 if (!code.is_null()) { | 2275 if (!code.is_null()) { |
| 2278 #ifdef DEBUG | 2276 #ifdef DEBUG |
| 2279 if (FLAG_trace_ic) { | 2277 if (FLAG_trace_ic) { |
| 2280 PrintF("[BinaryOpIC in "); | 2278 PrintF("[BinaryOpIC in "); |
| 2281 JavaScriptFrame::PrintTop(stdout, false, true); | 2279 JavaScriptFrame::PrintTop(stdout, false, true); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2366 Handle<Code> CompareIC::GetUninitialized(Token::Value op) { | 2364 Handle<Code> CompareIC::GetUninitialized(Token::Value op) { |
| 2367 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2365 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
| 2368 return stub.GetCode(); | 2366 return stub.GetCode(); |
| 2369 } | 2367 } |
| 2370 | 2368 |
| 2371 | 2369 |
| 2372 const char* CompareIC::GetStateName(State state) { | 2370 const char* CompareIC::GetStateName(State state) { |
| 2373 switch (state) { | 2371 switch (state) { |
| 2374 case UNINITIALIZED: return "UNINITIALIZED"; | 2372 case UNINITIALIZED: return "UNINITIALIZED"; |
| 2375 case SMI: return "SMI"; | 2373 case SMI: return "SMI"; |
| 2376 case HEAP_NUMBER: return "HEAP_NUMBER"; | 2374 case NUMBER: return "NUMBER"; |
| 2377 case OBJECT: return "OBJECTS"; | |
| 2378 case KNOWN_OBJECTS: return "KNOWN_OBJECTS"; | |
| 2379 case SYMBOL: return "SYMBOL"; | 2375 case SYMBOL: return "SYMBOL"; |
| 2380 case STRING: return "STRING"; | 2376 case STRING: return "STRING"; |
| 2377 case OBJECT: return "OBJECT"; |
| 2378 case KNOWN_OBJECT: return "KNOWN_OBJECT"; |
| 2381 case GENERIC: return "GENERIC"; | 2379 case GENERIC: return "GENERIC"; |
| 2382 default: | 2380 default: |
| 2383 UNREACHABLE(); | 2381 UNREACHABLE(); |
| 2384 return NULL; | 2382 return NULL; |
| 2385 } | 2383 } |
| 2386 } | 2384 } |
| 2387 | 2385 |
| 2388 | 2386 |
| 2389 static CompareIC::State InputState(CompareIC::State old_state, | 2387 static CompareIC::State InputState(CompareIC::State old_state, |
| 2390 Handle<Object> value) { | 2388 Handle<Object> value) { |
| 2391 switch (old_state) { | 2389 switch (old_state) { |
| 2392 case CompareIC::UNINITIALIZED: | 2390 case CompareIC::UNINITIALIZED: |
| 2393 if (value->IsSmi()) return CompareIC::SMI; | 2391 if (value->IsSmi()) return CompareIC::SMI; |
| 2394 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER; | 2392 if (value->IsHeapNumber()) return CompareIC::NUMBER; |
| 2395 if (value->IsSymbol()) return CompareIC::SYMBOL; | 2393 if (value->IsSymbol()) return CompareIC::SYMBOL; |
| 2396 if (value->IsString()) return CompareIC::STRING; | 2394 if (value->IsString()) return CompareIC::STRING; |
| 2397 if (value->IsJSObject()) return CompareIC::OBJECT; | 2395 if (value->IsJSObject()) return CompareIC::OBJECT; |
| 2398 break; | 2396 break; |
| 2399 case CompareIC::SMI: | 2397 case CompareIC::SMI: |
| 2400 if (value->IsSmi()) return CompareIC::SMI; | 2398 if (value->IsSmi()) return CompareIC::SMI; |
| 2401 if (value->IsHeapNumber()) return CompareIC::HEAP_NUMBER; | 2399 if (value->IsHeapNumber()) return CompareIC::NUMBER; |
| 2402 break; | 2400 break; |
| 2403 case CompareIC::HEAP_NUMBER: | 2401 case CompareIC::NUMBER: |
| 2404 if (value->IsNumber()) return CompareIC::HEAP_NUMBER; | 2402 if (value->IsNumber()) return CompareIC::NUMBER; |
| 2405 break; | 2403 break; |
| 2406 case CompareIC::SYMBOL: | 2404 case CompareIC::SYMBOL: |
| 2407 if (value->IsSymbol()) return CompareIC::SYMBOL; | 2405 if (value->IsSymbol()) return CompareIC::SYMBOL; |
| 2408 if (value->IsString()) return CompareIC::STRING; | 2406 if (value->IsString()) return CompareIC::STRING; |
| 2409 break; | 2407 break; |
| 2410 case CompareIC::STRING: | 2408 case CompareIC::STRING: |
| 2411 if (value->IsSymbol() || value->IsString()) return CompareIC::STRING; | 2409 if (value->IsSymbol() || value->IsString()) return CompareIC::STRING; |
| 2412 break; | 2410 break; |
| 2413 case CompareIC::OBJECT: | 2411 case CompareIC::OBJECT: |
| 2414 if (value->IsJSObject()) return CompareIC::OBJECT; | 2412 if (value->IsJSObject()) return CompareIC::OBJECT; |
| 2415 break; | 2413 break; |
| 2416 case CompareIC::GENERIC: | 2414 case CompareIC::GENERIC: |
| 2417 break; | 2415 break; |
| 2418 case CompareIC::KNOWN_OBJECTS: | 2416 case CompareIC::KNOWN_OBJECT: |
| 2419 UNREACHABLE(); | 2417 UNREACHABLE(); |
| 2420 break; | 2418 break; |
| 2421 } | 2419 } |
| 2422 return CompareIC::GENERIC; | 2420 return CompareIC::GENERIC; |
| 2423 } | 2421 } |
| 2424 | 2422 |
| 2425 | 2423 |
| 2426 CompareIC::State CompareIC::TargetState(State old_state, | 2424 CompareIC::State CompareIC::TargetState(State old_state, |
| 2427 State old_left, | 2425 State old_left, |
| 2428 State old_right, | 2426 State old_right, |
| 2429 bool has_inlined_smi_code, | 2427 bool has_inlined_smi_code, |
| 2430 Handle<Object> x, | 2428 Handle<Object> x, |
| 2431 Handle<Object> y) { | 2429 Handle<Object> y) { |
| 2432 switch (old_state) { | 2430 switch (old_state) { |
| 2433 case UNINITIALIZED: | 2431 case UNINITIALIZED: |
| 2434 if (x->IsSmi() && y->IsSmi()) return SMI; | 2432 if (x->IsSmi() && y->IsSmi()) return SMI; |
| 2435 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBER; | 2433 if (x->IsNumber() && y->IsNumber()) return NUMBER; |
| 2436 if (Token::IsOrderedRelationalCompareOp(op_)) { | 2434 if (Token::IsOrderedRelationalCompareOp(op_)) { |
| 2437 // Ordered comparisons treat undefined as NaN, so the | 2435 // Ordered comparisons treat undefined as NaN, so the |
| 2438 // HEAP_NUMBER stub will do the right thing. | 2436 // NUMBER stub will do the right thing. |
| 2439 if ((x->IsNumber() && y->IsUndefined()) || | 2437 if ((x->IsNumber() && y->IsUndefined()) || |
| 2440 (y->IsNumber() && x->IsUndefined())) { | 2438 (y->IsNumber() && x->IsUndefined())) { |
| 2441 return HEAP_NUMBER; | 2439 return NUMBER; |
| 2442 } | 2440 } |
| 2443 } | 2441 } |
| 2444 if (x->IsSymbol() && y->IsSymbol()) { | 2442 if (x->IsSymbol() && y->IsSymbol()) { |
| 2445 // We compare symbols as strings if we need to determine | 2443 // We compare symbols as strings if we need to determine |
| 2446 // the order in a non-equality compare. | 2444 // the order in a non-equality compare. |
| 2447 return Token::IsEqualityOp(op_) ? SYMBOL : STRING; | 2445 return Token::IsEqualityOp(op_) ? SYMBOL : STRING; |
| 2448 } | 2446 } |
| 2449 if (x->IsString() && y->IsString()) return STRING; | 2447 if (x->IsString() && y->IsString()) return STRING; |
| 2450 if (!Token::IsEqualityOp(op_)) return GENERIC; | 2448 if (!Token::IsEqualityOp(op_)) return GENERIC; |
| 2451 if (x->IsJSObject() && y->IsJSObject()) { | 2449 if (x->IsJSObject() && y->IsJSObject()) { |
| 2452 if (Handle<JSObject>::cast(x)->map() == | 2450 if (Handle<JSObject>::cast(x)->map() == |
| 2453 Handle<JSObject>::cast(y)->map() && | 2451 Handle<JSObject>::cast(y)->map()) { |
| 2454 Token::IsEqualityOp(op_)) { | 2452 return KNOWN_OBJECT; |
| 2455 return KNOWN_OBJECTS; | |
| 2456 } else { | 2453 } else { |
| 2457 return OBJECT; | 2454 return OBJECT; |
| 2458 } | 2455 } |
| 2459 } | 2456 } |
| 2460 return GENERIC; | 2457 return GENERIC; |
| 2461 case SMI: | 2458 case SMI: |
| 2462 return x->IsNumber() && y->IsNumber() | 2459 return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC; |
| 2463 ? HEAP_NUMBER | |
| 2464 : GENERIC; | |
| 2465 case SYMBOL: | 2460 case SYMBOL: |
| 2466 ASSERT(Token::IsEqualityOp(op_)); | 2461 ASSERT(Token::IsEqualityOp(op_)); |
| 2467 return x->IsString() && y->IsString() ? STRING : GENERIC; | 2462 return x->IsString() && y->IsString() ? STRING : GENERIC; |
| 2468 case HEAP_NUMBER: | 2463 case NUMBER: |
| 2469 if (old_left == SMI && x->IsHeapNumber()) return HEAP_NUMBER; | 2464 // If the failure was due to one side changing from smi to heap number, |
| 2470 if (old_right == SMI && y->IsHeapNumber()) return HEAP_NUMBER; | 2465 // then keep the state (if other changed at the same time, we will get |
| 2466 // a second miss and then go to generic). |
| 2467 if (old_left == SMI && x->IsHeapNumber()) return NUMBER; |
| 2468 if (old_right == SMI && y->IsHeapNumber()) return NUMBER; |
| 2469 return GENERIC; |
| 2470 case KNOWN_OBJECT: |
| 2471 ASSERT(Token::IsEqualityOp(op_)); |
| 2472 if (x->IsJSObject() && y->IsJSObject()) return OBJECT; |
| 2473 return GENERIC; |
| 2471 case STRING: | 2474 case STRING: |
| 2472 case OBJECT: | 2475 case OBJECT: |
| 2473 case KNOWN_OBJECTS: | |
| 2474 case GENERIC: | 2476 case GENERIC: |
| 2475 return GENERIC; | 2477 return GENERIC; |
| 2476 } | 2478 } |
| 2477 UNREACHABLE(); | 2479 UNREACHABLE(); |
| 2478 return GENERIC; // Make the compiler happy. | 2480 return GENERIC; // Make the compiler happy. |
| 2479 } | 2481 } |
| 2480 | 2482 |
| 2481 | 2483 |
| 2482 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { | 2484 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { |
| 2483 HandleScope scope; | 2485 HandleScope scope; |
| 2484 State previous_left, previous_right, previous_state; | 2486 State previous_left, previous_right, previous_state; |
| 2485 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, | 2487 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, |
| 2486 &previous_right, &previous_state, NULL); | 2488 &previous_right, &previous_state, NULL); |
| 2487 State new_left = InputState(previous_left, x); | 2489 State new_left = InputState(previous_left, x); |
| 2488 State new_right = InputState(previous_right, y); | 2490 State new_right = InputState(previous_right, y); |
| 2489 State state = TargetState(previous_state, previous_left, previous_right, | 2491 State state = TargetState(previous_state, previous_left, previous_right, |
| 2490 HasInlinedSmiCode(address()), x, y); | 2492 HasInlinedSmiCode(address()), x, y); |
| 2491 ICCompareStub stub(op_, new_left, new_right, state); | 2493 ICCompareStub stub(op_, new_left, new_right, state); |
| 2492 if (state == KNOWN_OBJECTS) { | 2494 if (state == KNOWN_OBJECT) { |
| 2493 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); | 2495 stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); |
| 2494 } | 2496 } |
| 2495 set_target(*stub.GetCode()); | 2497 set_target(*stub.GetCode()); |
| 2496 | 2498 |
| 2497 #ifdef DEBUG | 2499 #ifdef DEBUG |
| 2498 if (FLAG_trace_ic) { | 2500 if (FLAG_trace_ic) { |
| 2499 PrintF("[CompareIC in "); | 2501 PrintF("[CompareIC in "); |
| 2500 JavaScriptFrame::PrintTop(stdout, false, true); | 2502 JavaScriptFrame::PrintTop(stdout, false, true); |
| 2501 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", | 2503 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", |
| 2502 GetStateName(previous_left), | 2504 GetStateName(previous_left), |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2559 #undef ADDR | 2561 #undef ADDR |
| 2560 }; | 2562 }; |
| 2561 | 2563 |
| 2562 | 2564 |
| 2563 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2565 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2564 return IC_utilities[id]; | 2566 return IC_utilities[id]; |
| 2565 } | 2567 } |
| 2566 | 2568 |
| 2567 | 2569 |
| 2568 } } // namespace v8::internal | 2570 } } // namespace v8::internal |
| OLD | NEW |