| 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 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 return isolate()->stub_cache()->ComputeCallConstant( | 679 return isolate()->stub_cache()->ComputeCallConstant( |
| 680 argc, kind_, extra_state, name, object, holder, function); | 680 argc, kind_, extra_state, name, object, holder, function); |
| 681 } | 681 } |
| 682 case NORMAL: { | 682 case NORMAL: { |
| 683 // If we return a null handle, the IC will not be patched. | 683 // If we return a null handle, the IC will not be patched. |
| 684 if (!object->IsJSObject()) return Handle<Code>::null(); | 684 if (!object->IsJSObject()) return Handle<Code>::null(); |
| 685 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 685 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 686 | 686 |
| 687 if (holder->IsGlobalObject()) { | 687 if (holder->IsGlobalObject()) { |
| 688 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); | 688 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
| 689 Handle<JSGlobalPropertyCell> cell( | 689 Handle<PropertyCell> cell( |
| 690 global->GetPropertyCell(lookup), isolate()); | 690 global->GetPropertyCell(lookup), isolate()); |
| 691 if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); | 691 if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); |
| 692 Handle<JSFunction> function(JSFunction::cast(cell->value())); | 692 Handle<JSFunction> function(JSFunction::cast(cell->value())); |
| 693 return isolate()->stub_cache()->ComputeCallGlobal( | 693 return isolate()->stub_cache()->ComputeCallGlobal( |
| 694 argc, kind_, extra_state, name, receiver, global, cell, function); | 694 argc, kind_, extra_state, name, receiver, global, cell, function); |
| 695 } else { | 695 } else { |
| 696 // There is only one shared stub for calling normalized | 696 // There is only one shared stub for calling normalized |
| 697 // properties. It does not traverse the prototype chain, so the | 697 // properties. It does not traverse the prototype chain, so the |
| 698 // property must be found in the receiver for the stub to be | 698 // property must be found in the receiver for the stub to be |
| 699 // applicable. | 699 // applicable. |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 929 | 929 |
| 930 // If we did not find a property, check if we need to throw an exception. | 930 // If we did not find a property, check if we need to throw an exception. |
| 931 if (!lookup.IsFound()) { | 931 if (!lookup.IsFound()) { |
| 932 if (IsUndeclaredGlobal(object)) { | 932 if (IsUndeclaredGlobal(object)) { |
| 933 return ReferenceError("not_defined", name); | 933 return ReferenceError("not_defined", name); |
| 934 } | 934 } |
| 935 LOG(isolate(), SuspectReadEvent(*name, *object)); | 935 LOG(isolate(), SuspectReadEvent(*name, *object)); |
| 936 } | 936 } |
| 937 | 937 |
| 938 // Update inline cache and stub cache. | 938 // Update inline cache and stub cache. |
| 939 if (FLAG_use_ic) { | 939 if (FLAG_use_ic) UpdateCaches(&lookup, state, object, name); |
| 940 if (!object->IsJSObject()) { | |
| 941 // TODO(jkummerow): It would be nice to support non-JSObjects in | |
| 942 // UpdateCaches, then we wouldn't need to go generic here. | |
| 943 set_target(*generic_stub()); | |
| 944 } else { | |
| 945 UpdateCaches(&lookup, state, object, name); | |
| 946 } | |
| 947 } | |
| 948 | 940 |
| 949 PropertyAttributes attr; | 941 PropertyAttributes attr; |
| 950 if (lookup.IsInterceptor() || lookup.IsHandler()) { | 942 if (lookup.IsInterceptor() || lookup.IsHandler()) { |
| 951 // Get the property. | 943 // Get the property. |
| 952 Handle<Object> result = | 944 Handle<Object> result = |
| 953 Object::GetProperty(object, object, &lookup, name, &attr); | 945 Object::GetProperty(object, object, &lookup, name, &attr); |
| 954 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 946 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 955 // If the property is not present, check if we need to throw an | 947 // If the property is not present, check if we need to throw an |
| 956 // exception. | 948 // exception. |
| 957 if (attr == ABSENT && IsUndeclaredGlobal(object)) { | 949 if (attr == ABSENT && IsUndeclaredGlobal(object)) { |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1197 break; | 1189 break; |
| 1198 } | 1190 } |
| 1199 } | 1191 } |
| 1200 | 1192 |
| 1201 | 1193 |
| 1202 void LoadIC::UpdateCaches(LookupResult* lookup, | 1194 void LoadIC::UpdateCaches(LookupResult* lookup, |
| 1203 State state, | 1195 State state, |
| 1204 Handle<Object> object, | 1196 Handle<Object> object, |
| 1205 Handle<String> name) { | 1197 Handle<String> name) { |
| 1206 // Bail out if the result is not cacheable. | 1198 // Bail out if the result is not cacheable. |
| 1207 if (!lookup->IsCacheable()) return; | 1199 if (!lookup->IsCacheable()) { |
| 1200 set_target(*generic_stub()); |
| 1201 return; |
| 1202 } |
| 1208 | 1203 |
| 1209 // Loading properties from values is not common, so don't try to | 1204 // TODO(jkummerow): It would be nice to support non-JSObjects in |
| 1210 // deal with non-JS objects here. | 1205 // UpdateCaches, then we wouldn't need to go generic here. |
| 1211 if (!object->IsJSObject()) return; | 1206 if (!object->IsJSObject()) { |
| 1207 set_target(*generic_stub()); |
| 1208 return; |
| 1209 } |
| 1212 | 1210 |
| 1213 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1211 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1214 Handle<Code> code; | 1212 Handle<Code> code; |
| 1215 if (state == UNINITIALIZED) { | 1213 if (state == UNINITIALIZED) { |
| 1216 // This is the first time we execute this inline cache. | 1214 // This is the first time we execute this inline cache. |
| 1217 // Set the target to the pre monomorphic stub to delay | 1215 // Set the target to the pre monomorphic stub to delay |
| 1218 // setting the monomorphic state. | 1216 // setting the monomorphic state. |
| 1219 code = pre_monomorphic_stub(); | 1217 code = pre_monomorphic_stub(); |
| 1220 } else { | 1218 } else { |
| 1221 code = ComputeLoadHandler(lookup, receiver, name); | 1219 code = ComputeLoadHandler(lookup, receiver, name); |
| 1222 if (code.is_null()) return; | 1220 if (code.is_null()) { |
| 1221 set_target(*generic_stub()); |
| 1222 return; |
| 1223 } |
| 1223 } | 1224 } |
| 1224 | 1225 |
| 1225 PatchCache(state, kNonStrictMode, receiver, name, code); | 1226 PatchCache(state, kNonStrictMode, receiver, name, code); |
| 1226 TRACE_IC("LoadIC", name, state, target()); | 1227 TRACE_IC("LoadIC", name, state, target()); |
| 1227 } | 1228 } |
| 1228 | 1229 |
| 1229 | 1230 |
| 1230 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { | 1231 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { |
| 1231 // Cache code holding map should be consistent with | 1232 // Cache code holding map should be consistent with |
| 1232 // GenerateMonomorphicCacheProbe. | 1233 // GenerateMonomorphicCacheProbe. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1250 name, receiver, holder, | 1251 name, receiver, holder, |
| 1251 lookup->GetFieldIndex(), lookup->representation()); | 1252 lookup->GetFieldIndex(), lookup->representation()); |
| 1252 case CONSTANT_FUNCTION: { | 1253 case CONSTANT_FUNCTION: { |
| 1253 Handle<JSFunction> constant(lookup->GetConstantFunction()); | 1254 Handle<JSFunction> constant(lookup->GetConstantFunction()); |
| 1254 return isolate()->stub_cache()->ComputeLoadConstant( | 1255 return isolate()->stub_cache()->ComputeLoadConstant( |
| 1255 name, receiver, holder, constant); | 1256 name, receiver, holder, constant); |
| 1256 } | 1257 } |
| 1257 case NORMAL: | 1258 case NORMAL: |
| 1258 if (holder->IsGlobalObject()) { | 1259 if (holder->IsGlobalObject()) { |
| 1259 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); | 1260 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
| 1260 Handle<JSGlobalPropertyCell> cell( | 1261 Handle<PropertyCell> cell( |
| 1261 global->GetPropertyCell(lookup), isolate()); | 1262 global->GetPropertyCell(lookup), isolate()); |
| 1262 return isolate()->stub_cache()->ComputeLoadGlobal( | 1263 return isolate()->stub_cache()->ComputeLoadGlobal( |
| 1263 name, receiver, global, cell, lookup->IsDontDelete()); | 1264 name, receiver, global, cell, lookup->IsDontDelete()); |
| 1264 } | 1265 } |
| 1265 // There is only one shared stub for loading normalized | 1266 // There is only one shared stub for loading normalized |
| 1266 // properties. It does not traverse the prototype chain, so the | 1267 // properties. It does not traverse the prototype chain, so the |
| 1267 // property must be found in the receiver for the stub to be | 1268 // property must be found in the receiver for the stub to be |
| 1268 // applicable. | 1269 // applicable. |
| 1269 if (!holder.is_identical_to(receiver)) break; | 1270 if (!holder.is_identical_to(receiver)) break; |
| 1270 return isolate()->stub_cache()->ComputeLoadNormal(name, receiver); | 1271 return isolate()->stub_cache()->ComputeLoadNormal(name, receiver); |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1633 LookupResult lookup(isolate()); | 1634 LookupResult lookup(isolate()); |
| 1634 if (LookupForWrite(receiver, name, value, &lookup, &state)) { | 1635 if (LookupForWrite(receiver, name, value, &lookup, &state)) { |
| 1635 if (FLAG_use_ic) { | 1636 if (FLAG_use_ic) { |
| 1636 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); | 1637 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
| 1637 } | 1638 } |
| 1638 } else if (strict_mode == kStrictMode && | 1639 } else if (strict_mode == kStrictMode && |
| 1639 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1640 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1640 IsUndeclaredGlobal(object)) { | 1641 IsUndeclaredGlobal(object)) { |
| 1641 // Strict mode doesn't allow setting non-existent global property. | 1642 // Strict mode doesn't allow setting non-existent global property. |
| 1642 return ReferenceError("not_defined", name); | 1643 return ReferenceError("not_defined", name); |
| 1644 } else if (FLAG_use_ic && |
| 1645 (lookup.IsNormal() || |
| 1646 (lookup.IsField() && lookup.CanHoldValue(value)))) { |
| 1647 Handle<Code> stub = strict_mode == kStrictMode |
| 1648 ? generic_stub_strict() : generic_stub(); |
| 1649 set_target(*stub); |
| 1643 } | 1650 } |
| 1644 | 1651 |
| 1645 // Set the property. | 1652 // Set the property. |
| 1646 return JSReceiver::SetPropertyOrFail( | 1653 return JSReceiver::SetPropertyOrFail( |
| 1647 receiver, name, value, NONE, strict_mode, store_mode); | 1654 receiver, name, value, NONE, strict_mode, store_mode); |
| 1648 } | 1655 } |
| 1649 | 1656 |
| 1650 | 1657 |
| 1651 void StoreIC::UpdateCaches(LookupResult* lookup, | 1658 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1652 State state, | 1659 State state, |
| 1653 StrictModeFlag strict_mode, | 1660 StrictModeFlag strict_mode, |
| 1654 Handle<JSObject> receiver, | 1661 Handle<JSObject> receiver, |
| 1655 Handle<String> name, | 1662 Handle<String> name, |
| 1656 Handle<Object> value) { | 1663 Handle<Object> value) { |
| 1657 ASSERT(!receiver->IsJSGlobalProxy()); | 1664 ASSERT(!receiver->IsJSGlobalProxy()); |
| 1658 ASSERT(lookup->IsFound()); | 1665 ASSERT(lookup->IsFound()); |
| 1659 | 1666 |
| 1660 // These are not cacheable, so we never see such LookupResults here. | 1667 // These are not cacheable, so we never see such LookupResults here. |
| 1661 ASSERT(!lookup->IsHandler()); | 1668 ASSERT(!lookup->IsHandler()); |
| 1662 | 1669 |
| 1663 Handle<Code> code = | 1670 Handle<Code> code = ComputeStoreMonomorphic( |
| 1664 ComputeStoreMonomorphic(lookup, strict_mode, receiver, name); | 1671 lookup, strict_mode, receiver, name); |
| 1665 if (code.is_null()) return; | 1672 if (code.is_null()) { |
| 1673 Handle<Code> stub = strict_mode == kStrictMode |
| 1674 ? generic_stub_strict() : generic_stub(); |
| 1675 set_target(*stub); |
| 1676 return; |
| 1677 } |
| 1666 | 1678 |
| 1667 PatchCache(state, strict_mode, receiver, name, code); | 1679 PatchCache(state, strict_mode, receiver, name, code); |
| 1668 TRACE_IC("StoreIC", name, state, target()); | 1680 TRACE_IC("StoreIC", name, state, target()); |
| 1669 } | 1681 } |
| 1670 | 1682 |
| 1671 | 1683 |
| 1672 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, | 1684 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
| 1673 StrictModeFlag strict_mode, | 1685 StrictModeFlag strict_mode, |
| 1674 Handle<JSObject> receiver, | 1686 Handle<JSObject> receiver, |
| 1675 Handle<String> name) { | 1687 Handle<String> name) { |
| 1676 Handle<JSObject> holder(lookup->holder()); | 1688 Handle<JSObject> holder(lookup->holder()); |
| 1677 switch (lookup->type()) { | 1689 switch (lookup->type()) { |
| 1678 case FIELD: | 1690 case FIELD: |
| 1679 return isolate()->stub_cache()->ComputeStoreField( | 1691 return isolate()->stub_cache()->ComputeStoreField( |
| 1680 name, receiver, lookup, strict_mode); | 1692 name, receiver, lookup, strict_mode); |
| 1681 case NORMAL: | 1693 case NORMAL: |
| 1682 if (receiver->IsGlobalObject()) { | 1694 if (receiver->IsGlobalObject()) { |
| 1683 // The stub generated for the global object picks the value directly | 1695 // The stub generated for the global object picks the value directly |
| 1684 // from the property cell. So the property must be directly on the | 1696 // from the property cell. So the property must be directly on the |
| 1685 // global object. | 1697 // global object. |
| 1686 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1698 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); |
| 1687 Handle<JSGlobalPropertyCell> cell( | 1699 Handle<PropertyCell> cell( |
| 1688 global->GetPropertyCell(lookup), isolate()); | 1700 global->GetPropertyCell(lookup), isolate()); |
| 1689 return isolate()->stub_cache()->ComputeStoreGlobal( | 1701 return isolate()->stub_cache()->ComputeStoreGlobal( |
| 1690 name, global, cell, strict_mode); | 1702 name, global, cell, strict_mode); |
| 1691 } | 1703 } |
| 1692 ASSERT(holder.is_identical_to(receiver)); | 1704 ASSERT(holder.is_identical_to(receiver)); |
| 1693 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode); | 1705 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode); |
| 1694 case CALLBACKS: { | 1706 case CALLBACKS: { |
| 1695 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1707 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
| 1696 if (callback->IsExecutableAccessorInfo()) { | 1708 if (callback->IsExecutableAccessorInfo()) { |
| 1697 Handle<ExecutableAccessorInfo> info = | 1709 Handle<ExecutableAccessorInfo> info = |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1726 case TRANSITION: { | 1738 case TRANSITION: { |
| 1727 // Explicitly pass in the receiver map since LookupForWrite may have | 1739 // Explicitly pass in the receiver map since LookupForWrite may have |
| 1728 // stored something else than the receiver in the holder. | 1740 // stored something else than the receiver in the holder. |
| 1729 Handle<Map> transition( | 1741 Handle<Map> transition( |
| 1730 lookup->GetTransitionTarget(receiver->map()), isolate()); | 1742 lookup->GetTransitionTarget(receiver->map()), isolate()); |
| 1731 int descriptor = transition->LastAdded(); | 1743 int descriptor = transition->LastAdded(); |
| 1732 | 1744 |
| 1733 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 1745 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
| 1734 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 1746 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
| 1735 | 1747 |
| 1736 if (details.type() != FIELD || details.attributes() != NONE) break; | 1748 if (details.type() == CALLBACKS || details.attributes() != NONE) break; |
| 1737 | 1749 |
| 1738 return isolate()->stub_cache()->ComputeStoreTransition( | 1750 return isolate()->stub_cache()->ComputeStoreTransition( |
| 1739 name, receiver, lookup, transition, strict_mode); | 1751 name, receiver, lookup, transition, strict_mode); |
| 1740 } | 1752 } |
| 1741 case NONEXISTENT: | 1753 case NONEXISTENT: |
| 1742 case HANDLER: | 1754 case HANDLER: |
| 1743 UNREACHABLE(); | 1755 UNREACHABLE(); |
| 1744 break; | 1756 break; |
| 1745 } | 1757 } |
| 1746 return Handle<Code>::null(); | 1758 return Handle<Code>::null(); |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 case TRANSITION: { | 2104 case TRANSITION: { |
| 2093 // Explicitly pass in the receiver map since LookupForWrite may have | 2105 // Explicitly pass in the receiver map since LookupForWrite may have |
| 2094 // stored something else than the receiver in the holder. | 2106 // stored something else than the receiver in the holder. |
| 2095 Handle<Map> transition( | 2107 Handle<Map> transition( |
| 2096 lookup->GetTransitionTarget(receiver->map()), isolate()); | 2108 lookup->GetTransitionTarget(receiver->map()), isolate()); |
| 2097 int descriptor = transition->LastAdded(); | 2109 int descriptor = transition->LastAdded(); |
| 2098 | 2110 |
| 2099 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 2111 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
| 2100 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 2112 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
| 2101 | 2113 |
| 2102 if (details.type() == FIELD && details.attributes() == NONE) { | 2114 if (details.type() != CALLBACKS && details.attributes() == NONE) { |
| 2103 return isolate()->stub_cache()->ComputeKeyedStoreTransition( | 2115 return isolate()->stub_cache()->ComputeKeyedStoreTransition( |
| 2104 name, receiver, lookup, transition, strict_mode); | 2116 name, receiver, lookup, transition, strict_mode); |
| 2105 } | 2117 } |
| 2106 // fall through. | 2118 // fall through. |
| 2107 } | 2119 } |
| 2108 case NORMAL: | 2120 case NORMAL: |
| 2109 case CONSTANT_FUNCTION: | 2121 case CONSTANT_FUNCTION: |
| 2110 case CALLBACKS: | 2122 case CALLBACKS: |
| 2111 case INTERCEPTOR: | 2123 case INTERCEPTOR: |
| 2112 // Always rewrite to the generic case so that we do not | 2124 // Always rewrite to the generic case so that we do not |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2401 case NUMBER: return "Number"; | 2413 case NUMBER: return "Number"; |
| 2402 case GENERIC: return "Generic"; | 2414 case GENERIC: return "Generic"; |
| 2403 default: return "Invalid"; | 2415 default: return "Invalid"; |
| 2404 } | 2416 } |
| 2405 } | 2417 } |
| 2406 | 2418 |
| 2407 | 2419 |
| 2408 UnaryOpIC::State UnaryOpIC::ToState(TypeInfo type_info) { | 2420 UnaryOpIC::State UnaryOpIC::ToState(TypeInfo type_info) { |
| 2409 switch (type_info) { | 2421 switch (type_info) { |
| 2410 case UNINITIALIZED: | 2422 case UNINITIALIZED: |
| 2411 return ::v8::internal::UNINITIALIZED; | 2423 return v8::internal::UNINITIALIZED; |
| 2412 case SMI: | 2424 case SMI: |
| 2413 case NUMBER: | 2425 case NUMBER: |
| 2414 return MONOMORPHIC; | 2426 return MONOMORPHIC; |
| 2415 case GENERIC: | 2427 case GENERIC: |
| 2416 return ::v8::internal::GENERIC; | 2428 return v8::internal::GENERIC; |
| 2417 } | 2429 } |
| 2418 UNREACHABLE(); | 2430 UNREACHABLE(); |
| 2419 return ::v8::internal::UNINITIALIZED; | 2431 return v8::internal::UNINITIALIZED; |
| 2420 } | 2432 } |
| 2421 | 2433 |
| 2434 |
| 2435 Handle<Type> UnaryOpIC::TypeInfoToType(TypeInfo type_info, Isolate* isolate) { |
| 2436 switch (type_info) { |
| 2437 case UNINITIALIZED: |
| 2438 return handle(Type::None(), isolate); |
| 2439 case SMI: |
| 2440 return handle(Type::Integer31(), isolate); |
| 2441 case NUMBER: |
| 2442 return handle(Type::Number(), isolate); |
| 2443 case GENERIC: |
| 2444 return handle(Type::Any(), isolate); |
| 2445 } |
| 2446 UNREACHABLE(); |
| 2447 return handle(Type::Any(), isolate); |
| 2448 } |
| 2449 |
| 2450 |
| 2422 UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) { | 2451 UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) { |
| 2423 ::v8::internal::TypeInfo operand_type = | 2452 v8::internal::TypeInfo operand_type = |
| 2424 ::v8::internal::TypeInfo::TypeFromValue(operand); | 2453 v8::internal::TypeInfo::FromValue(operand); |
| 2425 if (operand_type.IsSmi()) { | 2454 if (operand_type.IsSmi()) { |
| 2426 return SMI; | 2455 return SMI; |
| 2427 } else if (operand_type.IsNumber()) { | 2456 } else if (operand_type.IsNumber()) { |
| 2428 return NUMBER; | 2457 return NUMBER; |
| 2429 } else { | 2458 } else { |
| 2430 return GENERIC; | 2459 return GENERIC; |
| 2431 } | 2460 } |
| 2432 } | 2461 } |
| 2433 | 2462 |
| 2434 | 2463 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2482 case STRING: | 2511 case STRING: |
| 2483 return MONOMORPHIC; | 2512 return MONOMORPHIC; |
| 2484 case GENERIC: | 2513 case GENERIC: |
| 2485 return ::v8::internal::GENERIC; | 2514 return ::v8::internal::GENERIC; |
| 2486 } | 2515 } |
| 2487 UNREACHABLE(); | 2516 UNREACHABLE(); |
| 2488 return ::v8::internal::UNINITIALIZED; | 2517 return ::v8::internal::UNINITIALIZED; |
| 2489 } | 2518 } |
| 2490 | 2519 |
| 2491 | 2520 |
| 2521 Handle<Type> BinaryOpIC::TypeInfoToType(BinaryOpIC::TypeInfo binary_type, |
| 2522 Isolate* isolate) { |
| 2523 switch (binary_type) { |
| 2524 case UNINITIALIZED: |
| 2525 return handle(Type::None(), isolate); |
| 2526 case SMI: |
| 2527 return handle(Type::Integer31(), isolate); |
| 2528 case INT32: |
| 2529 return handle(Type::Integer32(), isolate); |
| 2530 case NUMBER: |
| 2531 return handle(Type::Number(), isolate); |
| 2532 case ODDBALL: |
| 2533 return handle(Type::Optional( |
| 2534 handle(Type::Union( |
| 2535 handle(Type::Number(), isolate), |
| 2536 handle(Type::String(), isolate)), isolate)), isolate); |
| 2537 case STRING: |
| 2538 return handle(Type::String(), isolate); |
| 2539 case GENERIC: |
| 2540 return handle(Type::Any(), isolate); |
| 2541 } |
| 2542 UNREACHABLE(); |
| 2543 return handle(Type::Any(), isolate); |
| 2544 } |
| 2545 |
| 2546 |
| 2547 void BinaryOpIC::StubInfoToType(int minor_key, |
| 2548 Handle<Type>* left, |
| 2549 Handle<Type>* right, |
| 2550 Handle<Type>* result, |
| 2551 Isolate* isolate) { |
| 2552 TypeInfo left_typeinfo, right_typeinfo, result_typeinfo; |
| 2553 BinaryOpStub::decode_types_from_minor_key( |
| 2554 minor_key, &left_typeinfo, &right_typeinfo, &result_typeinfo); |
| 2555 *left = TypeInfoToType(left_typeinfo, isolate); |
| 2556 *right = TypeInfoToType(right_typeinfo, isolate); |
| 2557 *result = TypeInfoToType(result_typeinfo, isolate); |
| 2558 } |
| 2559 |
| 2560 |
| 2492 RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) { | 2561 RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) { |
| 2493 ASSERT(args.length() == 4); | 2562 ASSERT(args.length() == 4); |
| 2494 | 2563 |
| 2495 HandleScope scope(isolate); | 2564 HandleScope scope(isolate); |
| 2496 Handle<Object> operand = args.at<Object>(0); | 2565 Handle<Object> operand = args.at<Object>(0); |
| 2497 Token::Value op = static_cast<Token::Value>(args.smi_at(1)); | 2566 Token::Value op = static_cast<Token::Value>(args.smi_at(1)); |
| 2498 UnaryOverwriteMode mode = static_cast<UnaryOverwriteMode>(args.smi_at(2)); | 2567 UnaryOverwriteMode mode = static_cast<UnaryOverwriteMode>(args.smi_at(2)); |
| 2499 UnaryOpIC::TypeInfo previous_type = | 2568 UnaryOpIC::TypeInfo previous_type = |
| 2500 static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3)); | 2569 static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3)); |
| 2501 | 2570 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2538 &caught_exception); | 2607 &caught_exception); |
| 2539 if (caught_exception) { | 2608 if (caught_exception) { |
| 2540 return Failure::Exception(); | 2609 return Failure::Exception(); |
| 2541 } | 2610 } |
| 2542 return *result; | 2611 return *result; |
| 2543 } | 2612 } |
| 2544 | 2613 |
| 2545 | 2614 |
| 2546 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value, | 2615 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value, |
| 2547 Token::Value op) { | 2616 Token::Value op) { |
| 2548 ::v8::internal::TypeInfo type = | 2617 v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value); |
| 2549 ::v8::internal::TypeInfo::TypeFromValue(value); | |
| 2550 if (type.IsSmi()) return BinaryOpIC::SMI; | 2618 if (type.IsSmi()) return BinaryOpIC::SMI; |
| 2551 if (type.IsInteger32()) { | 2619 if (type.IsInteger32()) { |
| 2552 if (kSmiValueSize == 32) return BinaryOpIC::SMI; | 2620 if (kSmiValueSize == 32) return BinaryOpIC::SMI; |
| 2553 return BinaryOpIC::INT32; | 2621 return BinaryOpIC::INT32; |
| 2554 } | 2622 } |
| 2555 if (type.IsNumber()) return BinaryOpIC::NUMBER; | 2623 if (type.IsNumber()) return BinaryOpIC::NUMBER; |
| 2556 if (type.IsString()) return BinaryOpIC::STRING; | 2624 if (type.IsString()) return BinaryOpIC::STRING; |
| 2557 if (value->IsUndefined()) { | 2625 if (value->IsUndefined()) { |
| 2558 if (op == Token::BIT_AND || | 2626 if (op == Token::BIT_AND || |
| 2559 op == Token::BIT_OR || | 2627 op == Token::BIT_OR || |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2760 switch (state) { | 2828 switch (state) { |
| 2761 case UNINITIALIZED: return "UNINITIALIZED"; | 2829 case UNINITIALIZED: return "UNINITIALIZED"; |
| 2762 case SMI: return "SMI"; | 2830 case SMI: return "SMI"; |
| 2763 case NUMBER: return "NUMBER"; | 2831 case NUMBER: return "NUMBER"; |
| 2764 case INTERNALIZED_STRING: return "INTERNALIZED_STRING"; | 2832 case INTERNALIZED_STRING: return "INTERNALIZED_STRING"; |
| 2765 case STRING: return "STRING"; | 2833 case STRING: return "STRING"; |
| 2766 case UNIQUE_NAME: return "UNIQUE_NAME"; | 2834 case UNIQUE_NAME: return "UNIQUE_NAME"; |
| 2767 case OBJECT: return "OBJECT"; | 2835 case OBJECT: return "OBJECT"; |
| 2768 case KNOWN_OBJECT: return "KNOWN_OBJECT"; | 2836 case KNOWN_OBJECT: return "KNOWN_OBJECT"; |
| 2769 case GENERIC: return "GENERIC"; | 2837 case GENERIC: return "GENERIC"; |
| 2770 default: | |
| 2771 UNREACHABLE(); | |
| 2772 return NULL; | |
| 2773 } | 2838 } |
| 2839 UNREACHABLE(); |
| 2840 return NULL; |
| 2774 } | 2841 } |
| 2775 | 2842 |
| 2776 | 2843 |
| 2777 static CompareIC::State InputState(CompareIC::State old_state, | 2844 Handle<Type> CompareIC::StateToType( |
| 2778 Handle<Object> value) { | 2845 Isolate* isolate, |
| 2846 CompareIC::State state, |
| 2847 Handle<Map> map) { |
| 2848 switch (state) { |
| 2849 case CompareIC::UNINITIALIZED: |
| 2850 return handle(Type::None(), isolate); |
| 2851 case CompareIC::SMI: |
| 2852 return handle(Type::Integer31(), isolate); |
| 2853 case CompareIC::NUMBER: |
| 2854 return handle(Type::Number(), isolate); |
| 2855 case CompareIC::STRING: |
| 2856 return handle(Type::String(), isolate); |
| 2857 case CompareIC::INTERNALIZED_STRING: |
| 2858 return handle(Type::InternalizedString(), isolate); |
| 2859 case CompareIC::UNIQUE_NAME: |
| 2860 return handle(Type::UniqueName(), isolate); |
| 2861 case CompareIC::OBJECT: |
| 2862 return handle(Type::Receiver(), isolate); |
| 2863 case CompareIC::KNOWN_OBJECT: |
| 2864 return handle( |
| 2865 map.is_null() ? Type::Receiver() : Type::Class(map), isolate); |
| 2866 case CompareIC::GENERIC: |
| 2867 return handle(Type::Any(), isolate); |
| 2868 } |
| 2869 UNREACHABLE(); |
| 2870 return Handle<Type>(); |
| 2871 } |
| 2872 |
| 2873 |
| 2874 void CompareIC::StubInfoToType(int stub_minor_key, |
| 2875 Handle<Type>* left_type, |
| 2876 Handle<Type>* right_type, |
| 2877 Handle<Type>* overall_type, |
| 2878 Handle<Map> map, |
| 2879 Isolate* isolate) { |
| 2880 State left_state, right_state, handler_state; |
| 2881 ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state, |
| 2882 &handler_state, NULL); |
| 2883 *left_type = StateToType(isolate, left_state); |
| 2884 *right_type = StateToType(isolate, right_state); |
| 2885 *overall_type = StateToType(isolate, handler_state, map); |
| 2886 } |
| 2887 |
| 2888 |
| 2889 CompareIC::State CompareIC::NewInputState(State old_state, |
| 2890 Handle<Object> value) { |
| 2779 switch (old_state) { | 2891 switch (old_state) { |
| 2780 case CompareIC::UNINITIALIZED: | 2892 case UNINITIALIZED: |
| 2781 if (value->IsSmi()) return CompareIC::SMI; | 2893 if (value->IsSmi()) return SMI; |
| 2782 if (value->IsHeapNumber()) return CompareIC::NUMBER; | 2894 if (value->IsHeapNumber()) return NUMBER; |
| 2783 if (value->IsInternalizedString()) return CompareIC::INTERNALIZED_STRING; | 2895 if (value->IsInternalizedString()) return INTERNALIZED_STRING; |
| 2784 if (value->IsString()) return CompareIC::STRING; | 2896 if (value->IsString()) return STRING; |
| 2785 if (value->IsSymbol()) return CompareIC::UNIQUE_NAME; | 2897 if (value->IsSymbol()) return UNIQUE_NAME; |
| 2786 if (value->IsJSObject()) return CompareIC::OBJECT; | 2898 if (value->IsJSObject()) return OBJECT; |
| 2787 break; | 2899 break; |
| 2788 case CompareIC::SMI: | 2900 case SMI: |
| 2789 if (value->IsSmi()) return CompareIC::SMI; | 2901 if (value->IsSmi()) return SMI; |
| 2790 if (value->IsHeapNumber()) return CompareIC::NUMBER; | 2902 if (value->IsHeapNumber()) return NUMBER; |
| 2791 break; | 2903 break; |
| 2792 case CompareIC::NUMBER: | 2904 case NUMBER: |
| 2793 if (value->IsNumber()) return CompareIC::NUMBER; | 2905 if (value->IsNumber()) return NUMBER; |
| 2794 break; | 2906 break; |
| 2795 case CompareIC::INTERNALIZED_STRING: | 2907 case INTERNALIZED_STRING: |
| 2796 if (value->IsInternalizedString()) return CompareIC::INTERNALIZED_STRING; | 2908 if (value->IsInternalizedString()) return INTERNALIZED_STRING; |
| 2797 if (value->IsString()) return CompareIC::STRING; | 2909 if (value->IsString()) return STRING; |
| 2798 if (value->IsSymbol()) return CompareIC::UNIQUE_NAME; | 2910 if (value->IsSymbol()) return UNIQUE_NAME; |
| 2799 break; | 2911 break; |
| 2800 case CompareIC::STRING: | 2912 case STRING: |
| 2801 if (value->IsString()) return CompareIC::STRING; | 2913 if (value->IsString()) return STRING; |
| 2802 break; | 2914 break; |
| 2803 case CompareIC::UNIQUE_NAME: | 2915 case UNIQUE_NAME: |
| 2804 if (value->IsUniqueName()) return CompareIC::UNIQUE_NAME; | 2916 if (value->IsUniqueName()) return UNIQUE_NAME; |
| 2805 break; | 2917 break; |
| 2806 case CompareIC::OBJECT: | 2918 case OBJECT: |
| 2807 if (value->IsJSObject()) return CompareIC::OBJECT; | 2919 if (value->IsJSObject()) return OBJECT; |
| 2808 break; | 2920 break; |
| 2809 case CompareIC::GENERIC: | 2921 case GENERIC: |
| 2810 break; | 2922 break; |
| 2811 case CompareIC::KNOWN_OBJECT: | 2923 case KNOWN_OBJECT: |
| 2812 UNREACHABLE(); | 2924 UNREACHABLE(); |
| 2813 break; | 2925 break; |
| 2814 } | 2926 } |
| 2815 return CompareIC::GENERIC; | 2927 return GENERIC; |
| 2816 } | 2928 } |
| 2817 | 2929 |
| 2818 | 2930 |
| 2819 CompareIC::State CompareIC::TargetState(State old_state, | 2931 CompareIC::State CompareIC::TargetState(State old_state, |
| 2820 State old_left, | 2932 State old_left, |
| 2821 State old_right, | 2933 State old_right, |
| 2822 bool has_inlined_smi_code, | 2934 bool has_inlined_smi_code, |
| 2823 Handle<Object> x, | 2935 Handle<Object> x, |
| 2824 Handle<Object> y) { | 2936 Handle<Object> y) { |
| 2825 switch (old_state) { | 2937 switch (old_state) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2878 UNREACHABLE(); | 2990 UNREACHABLE(); |
| 2879 return GENERIC; // Make the compiler happy. | 2991 return GENERIC; // Make the compiler happy. |
| 2880 } | 2992 } |
| 2881 | 2993 |
| 2882 | 2994 |
| 2883 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { | 2995 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { |
| 2884 HandleScope scope(isolate()); | 2996 HandleScope scope(isolate()); |
| 2885 State previous_left, previous_right, previous_state; | 2997 State previous_left, previous_right, previous_state; |
| 2886 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, | 2998 ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, |
| 2887 &previous_right, &previous_state, NULL); | 2999 &previous_right, &previous_state, NULL); |
| 2888 State new_left = InputState(previous_left, x); | 3000 State new_left = NewInputState(previous_left, x); |
| 2889 State new_right = InputState(previous_right, y); | 3001 State new_right = NewInputState(previous_right, y); |
| 2890 State state = TargetState(previous_state, previous_left, previous_right, | 3002 State state = TargetState(previous_state, previous_left, previous_right, |
| 2891 HasInlinedSmiCode(address()), x, y); | 3003 HasInlinedSmiCode(address()), x, y); |
| 2892 ICCompareStub stub(op_, new_left, new_right, state); | 3004 ICCompareStub stub(op_, new_left, new_right, state); |
| 2893 if (state == KNOWN_OBJECT) { | 3005 if (state == KNOWN_OBJECT) { |
| 2894 stub.set_known_map( | 3006 stub.set_known_map( |
| 2895 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); | 3007 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); |
| 2896 } | 3008 } |
| 2897 set_target(*stub.GetCode(isolate())); | 3009 set_target(*stub.GetCode(isolate())); |
| 2898 | 3010 |
| 2899 #ifdef DEBUG | 3011 #ifdef DEBUG |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2927 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 3039 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
| 2928 return ic.target(); | 3040 return ic.target(); |
| 2929 } | 3041 } |
| 2930 | 3042 |
| 2931 | 3043 |
| 2932 void CompareNilIC::Clear(Address address, Code* target) { | 3044 void CompareNilIC::Clear(Address address, Code* target) { |
| 2933 if (target->ic_state() == UNINITIALIZED) return; | 3045 if (target->ic_state() == UNINITIALIZED) return; |
| 2934 Code::ExtraICState state = target->extended_extra_ic_state(); | 3046 Code::ExtraICState state = target->extended_extra_ic_state(); |
| 2935 | 3047 |
| 2936 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); | 3048 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); |
| 2937 stub.ClearTypes(); | 3049 stub.ClearState(); |
| 2938 | 3050 |
| 2939 Code* code = NULL; | 3051 Code* code = NULL; |
| 2940 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); | 3052 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); |
| 2941 | 3053 |
| 2942 SetTargetAtAddress(address, code); | 3054 SetTargetAtAddress(address, code); |
| 2943 } | 3055 } |
| 2944 | 3056 |
| 2945 | 3057 |
| 2946 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, | 3058 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, |
| 2947 Handle<Object> object) { | 3059 Handle<Object> object) { |
| 2948 if (object->IsNull() || object->IsUndefined()) { | 3060 if (object->IsNull() || object->IsUndefined()) { |
| 2949 return Smi::FromInt(true); | 3061 return Smi::FromInt(true); |
| 2950 } | 3062 } |
| 2951 return Smi::FromInt(object->IsUndetectableObject()); | 3063 return Smi::FromInt(object->IsUndetectableObject()); |
| 2952 } | 3064 } |
| 2953 | 3065 |
| 2954 | 3066 |
| 2955 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) { | 3067 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) { |
| 2956 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state(); | 3068 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state(); |
| 2957 | 3069 |
| 2958 CompareNilICStub stub(extra_ic_state); | 3070 CompareNilICStub stub(extra_ic_state); |
| 2959 | 3071 |
| 2960 // Extract the current supported types from the patched IC and calculate what | 3072 // Extract the current supported types from the patched IC and calculate what |
| 2961 // types must be supported as a result of the miss. | 3073 // types must be supported as a result of the miss. |
| 2962 bool already_monomorphic = stub.IsMonomorphic(); | 3074 bool already_monomorphic = stub.IsMonomorphic(); |
| 2963 | 3075 |
| 2964 CompareNilICStub::Types old_types = stub.GetTypes(); | 3076 CompareNilICStub::State old_state = stub.GetState(); |
| 2965 stub.Record(object); | 3077 stub.Record(object); |
| 2966 old_types.TraceTransition(stub.GetTypes()); | 3078 old_state.TraceTransition(stub.GetState()); |
| 2967 | 3079 |
| 2968 NilValue nil = stub.GetNilValue(); | 3080 NilValue nil = stub.GetNilValue(); |
| 2969 | 3081 |
| 2970 // Find or create the specialized stub to support the new set of types. | 3082 // Find or create the specialized stub to support the new set of types. |
| 2971 Handle<Code> code; | 3083 Handle<Code> code; |
| 2972 if (stub.IsMonomorphic()) { | 3084 if (stub.IsMonomorphic()) { |
| 2973 Handle<Map> monomorphic_map(already_monomorphic | 3085 Handle<Map> monomorphic_map(already_monomorphic |
| 2974 ? target()->FindFirstMap() | 3086 ? target()->FindFirstMap() |
| 2975 : HeapObject::cast(*object)->map()); | 3087 : HeapObject::cast(*object)->map()); |
| 2976 code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub); | 3088 code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3024 #undef ADDR | 3136 #undef ADDR |
| 3025 }; | 3137 }; |
| 3026 | 3138 |
| 3027 | 3139 |
| 3028 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3140 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3029 return IC_utilities[id]; | 3141 return IC_utilities[id]; |
| 3030 } | 3142 } |
| 3031 | 3143 |
| 3032 | 3144 |
| 3033 } } // namespace v8::internal | 3145 } } // namespace v8::internal |
| OLD | NEW |