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 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 return CallICBase::LoadFunction(state, | 788 return CallICBase::LoadFunction(state, |
789 Code::kNoExtraICState, | 789 Code::kNoExtraICState, |
790 object, | 790 object, |
791 Handle<String>::cast(key)); | 791 Handle<String>::cast(key)); |
792 } | 792 } |
793 | 793 |
794 if (object->IsUndefined() || object->IsNull()) { | 794 if (object->IsUndefined() || object->IsNull()) { |
795 return TypeError("non_object_property_call", object, key); | 795 return TypeError("non_object_property_call", object, key); |
796 } | 796 } |
797 | 797 |
798 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { | 798 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
799 ASSERT(state != GENERIC); | 799 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
| 800 |
| 801 if (use_ic && state != MEGAMORPHIC) { |
800 int argc = target()->arguments_count(); | 802 int argc = target()->arguments_count(); |
801 Handle<Map> map = | 803 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( |
802 isolate()->factory()->non_strict_arguments_elements_map(); | 804 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
803 if (object->IsJSObject() && | 805 if (object->IsJSObject()) { |
804 Handle<JSObject>::cast(object)->elements()->map() == *map) { | 806 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
805 Handle<Code> code = isolate()->stub_cache()->ComputeCallArguments( | 807 if (receiver->elements()->map() == |
806 argc, Code::KEYED_CALL_IC); | 808 isolate()->heap()->non_strict_arguments_elements_map()) { |
807 set_target(*code); | 809 stub = isolate()->stub_cache()->ComputeCallArguments(argc); |
808 TRACE_IC("KeyedCallIC", key, state, target()); | 810 } |
809 } else if (!object->IsAccessCheckNeeded()) { | |
810 Handle<Code> code = isolate()->stub_cache()->ComputeCallMegamorphic( | |
811 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | |
812 set_target(*code); | |
813 TRACE_IC("KeyedCallIC", key, state, target()); | |
814 } | 811 } |
| 812 ASSERT(!stub.is_null()); |
| 813 set_target(*stub); |
| 814 TRACE_IC("KeyedCallIC", key, state, target()); |
815 } | 815 } |
816 | 816 |
817 Handle<Object> result = GetProperty(object, key); | 817 Handle<Object> result = GetProperty(object, key); |
818 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 818 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
819 | 819 |
820 // Make receiver an object if the callee requires it. Strict mode or builtin | 820 // Make receiver an object if the callee requires it. Strict mode or builtin |
821 // functions do not wrap the receiver, non-strict functions and objects | 821 // functions do not wrap the receiver, non-strict functions and objects |
822 // called as functions do. | 822 // called as functions do. |
823 ReceiverToObjectIfRequired(result, object); | 823 ReceiverToObjectIfRequired(result, object); |
824 if (result->IsJSFunction()) return *result; | 824 if (result->IsJSFunction()) return *result; |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 Handle<Object> key, | 1236 Handle<Object> key, |
1237 ICMissMode miss_mode) { | 1237 ICMissMode miss_mode) { |
1238 // Check for values that can be converted into a symbol directly or | 1238 // Check for values that can be converted into a symbol directly or |
1239 // is representable as a smi. | 1239 // is representable as a smi. |
1240 key = TryConvertKey(key, isolate()); | 1240 key = TryConvertKey(key, isolate()); |
1241 | 1241 |
1242 if (key->IsSymbol()) { | 1242 if (key->IsSymbol()) { |
1243 return LoadIC::Load(state, object, Handle<String>::cast(key)); | 1243 return LoadIC::Load(state, object, Handle<String>::cast(key)); |
1244 } | 1244 } |
1245 | 1245 |
1246 // Do not use ICs for objects that require access checks (including | |
1247 // the global object). | |
1248 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1246 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| 1247 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
1249 | 1248 |
1250 if (use_ic) { | 1249 if (use_ic) { |
1251 Handle<Code> stub = generic_stub(); | 1250 Handle<Code> stub = generic_stub(); |
1252 if (miss_mode != MISS_FORCE_GENERIC) { | 1251 if (miss_mode != MISS_FORCE_GENERIC) { |
1253 if (object->IsString() && key->IsNumber()) { | 1252 if (object->IsString() && key->IsNumber()) { |
1254 if (state == UNINITIALIZED) { | 1253 if (state == UNINITIALIZED) { |
1255 stub = string_stub(); | 1254 stub = string_stub(); |
1256 } | 1255 } |
1257 } else if (object->IsJSObject()) { | 1256 } else if (object->IsJSObject()) { |
1258 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1257 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1259 if (receiver->elements()->map() == | 1258 if (receiver->elements()->map() == |
1260 isolate()->heap()->non_strict_arguments_elements_map()) { | 1259 isolate()->heap()->non_strict_arguments_elements_map()) { |
1261 stub = non_strict_arguments_stub(); | 1260 stub = non_strict_arguments_stub(); |
1262 } else if (receiver->HasIndexedInterceptor()) { | 1261 } else if (receiver->HasIndexedInterceptor()) { |
1263 stub = indexed_interceptor_stub(); | 1262 stub = indexed_interceptor_stub(); |
1264 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { | 1263 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
1265 stub = LoadElementStub(receiver); | 1264 stub = LoadElementStub(receiver); |
1266 } | 1265 } |
1267 } | 1266 } |
1268 } else { | 1267 } else { |
1269 TRACE_GENERIC_IC("KeyedLoadIC", "force generic"); | 1268 TRACE_GENERIC_IC("KeyedLoadIC", "force generic"); |
1270 } | 1269 } |
1271 if (!stub.is_null()) set_target(*stub); | 1270 ASSERT(!stub.is_null()); |
| 1271 set_target(*stub); |
| 1272 TRACE_IC("KeyedLoadIC", key, state, target()); |
1272 } | 1273 } |
1273 | 1274 |
1274 TRACE_IC("KeyedLoadIC", key, state, target()); | |
1275 | 1275 |
1276 // Get the property. | |
1277 return Runtime::GetObjectProperty(isolate(), object, key); | 1276 return Runtime::GetObjectProperty(isolate(), object, key); |
1278 } | 1277 } |
1279 | 1278 |
1280 | 1279 |
1281 Handle<Code> KeyedLoadIC::ComputeLoadMonomorphic(LookupResult* lookup, | 1280 Handle<Code> KeyedLoadIC::ComputeLoadMonomorphic(LookupResult* lookup, |
1282 Handle<JSObject> receiver, | 1281 Handle<JSObject> receiver, |
1283 Handle<String> name) { | 1282 Handle<String> name) { |
1284 // Bail out if we didn't find a result. | 1283 // Bail out if we didn't find a result. |
1285 if (!lookup->IsProperty()) return Handle<Code>::null(); | 1284 if (!lookup->IsProperty()) return Handle<Code>::null(); |
1286 | 1285 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1400 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1399 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
1401 } | 1400 } |
1402 | 1401 |
1403 // Use specialized code for setting the length of arrays with fast | 1402 // Use specialized code for setting the length of arrays with fast |
1404 // properties. Slow properties might indicate redefinition of the length | 1403 // properties. Slow properties might indicate redefinition of the length |
1405 // property. | 1404 // property. |
1406 if (FLAG_use_ic && | 1405 if (FLAG_use_ic && |
1407 receiver->IsJSArray() && | 1406 receiver->IsJSArray() && |
1408 name->Equals(isolate()->heap()->length_symbol()) && | 1407 name->Equals(isolate()->heap()->length_symbol()) && |
1409 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1408 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
1410 receiver->HasFastProperties() && | 1409 receiver->HasFastProperties()) { |
1411 kind() != Code::KEYED_STORE_IC) { | 1410 Handle<Code> stub = StoreArrayLengthStub(kind(), strict_mode).GetCode(); |
1412 Handle<Code> stub = (strict_mode == kStrictMode) | |
1413 ? isolate()->builtins()->StoreIC_ArrayLength_Strict() | |
1414 : isolate()->builtins()->StoreIC_ArrayLength(); | |
1415 set_target(*stub); | 1411 set_target(*stub); |
1416 TRACE_IC("StoreIC", name, state, *stub); | 1412 TRACE_IC("StoreIC", name, state, *stub); |
1417 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1413 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
1418 } | 1414 } |
1419 | 1415 |
1420 if (receiver->IsJSGlobalProxy()) { | 1416 if (receiver->IsJSGlobalProxy()) { |
1421 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { | 1417 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { |
1422 // Generate a generic stub that goes to the runtime when we see a global | 1418 // Generate a generic stub that goes to the runtime when we see a global |
1423 // proxy as receiver. | 1419 // proxy as receiver. |
1424 Handle<Code> stub = (strict_mode == kStrictMode) | 1420 Handle<Code> stub = (strict_mode == kStrictMode) |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1721 StrictModeFlag strict_mode, | 1717 StrictModeFlag strict_mode, |
1722 Handle<Object> object, | 1718 Handle<Object> object, |
1723 Handle<Object> key, | 1719 Handle<Object> key, |
1724 Handle<Object> value, | 1720 Handle<Object> value, |
1725 ICMissMode miss_mode) { | 1721 ICMissMode miss_mode) { |
1726 // Check for values that can be converted into a symbol directly or | 1722 // Check for values that can be converted into a symbol directly or |
1727 // is representable as a smi. | 1723 // is representable as a smi. |
1728 key = TryConvertKey(key, isolate()); | 1724 key = TryConvertKey(key, isolate()); |
1729 | 1725 |
1730 if (key->IsSymbol()) { | 1726 if (key->IsSymbol()) { |
1731 Handle<String> name = Handle<String>::cast(key); | |
1732 return StoreIC::Store(state, | 1727 return StoreIC::Store(state, |
1733 strict_mode, | 1728 strict_mode, |
1734 object, | 1729 object, |
1735 name, | 1730 Handle<String>::cast(key), |
1736 value, | 1731 value, |
1737 JSReceiver::MAY_BE_STORE_FROM_KEYED); | 1732 JSReceiver::MAY_BE_STORE_FROM_KEYED); |
1738 } | 1733 } |
1739 | 1734 |
1740 // Do not use ICs for objects that require access checks (including | |
1741 // the global object), or are observed. | |
1742 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && | 1735 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && |
1743 !(FLAG_harmony_observation && object->IsJSObject() && | 1736 !(FLAG_harmony_observation && object->IsJSObject() && |
1744 JSObject::cast(*object)->map()->is_observed()); | 1737 JSObject::cast(*object)->map()->is_observed()); |
1745 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1738 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
1746 | 1739 |
1747 if (use_ic) { | 1740 if (use_ic) { |
1748 Handle<Code> stub = (strict_mode == kStrictMode) | 1741 Handle<Code> stub = (strict_mode == kStrictMode) |
1749 ? generic_stub_strict() | 1742 ? generic_stub_strict() |
1750 : generic_stub(); | 1743 : generic_stub(); |
1751 if (object->IsJSObject()) { | 1744 if (miss_mode != MISS_FORCE_GENERIC) { |
1752 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1745 if (object->IsJSObject()) { |
1753 if (receiver->elements()->map() == | 1746 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1754 isolate()->heap()->non_strict_arguments_elements_map()) { | 1747 if (receiver->elements()->map() == |
1755 stub = non_strict_arguments_stub(); | 1748 isolate()->heap()->non_strict_arguments_elements_map()) { |
1756 } else if (miss_mode != MISS_FORCE_GENERIC) { | 1749 stub = non_strict_arguments_stub(); |
1757 if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { | 1750 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
1758 StubKind stub_kind = GetStubKind(receiver, key, value); | 1751 StubKind stub_kind = GetStubKind(receiver, key, value); |
1759 stub = StoreElementStub(receiver, stub_kind, strict_mode); | 1752 stub = StoreElementStub(receiver, stub_kind, strict_mode); |
1760 } | 1753 } |
1761 } else { | |
1762 TRACE_GENERIC_IC("KeyedStoreIC", "force generic"); | |
1763 } | 1754 } |
| 1755 } else { |
| 1756 TRACE_GENERIC_IC("KeyedStoreIC", "force generic"); |
1764 } | 1757 } |
1765 if (!stub.is_null()) set_target(*stub); | 1758 ASSERT(!stub.is_null()); |
| 1759 set_target(*stub); |
| 1760 TRACE_IC("KeyedStoreIC", key, state, target()); |
1766 } | 1761 } |
1767 | 1762 |
1768 TRACE_IC("KeyedStoreIC", key, state, target()); | |
1769 | |
1770 // Set the property. | |
1771 return Runtime::SetObjectProperty( | 1763 return Runtime::SetObjectProperty( |
1772 isolate(), object , key, value, NONE, strict_mode); | 1764 isolate(), object , key, value, NONE, strict_mode); |
1773 } | 1765 } |
1774 | 1766 |
1775 | 1767 |
1776 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, | 1768 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
1777 StrictModeFlag strict_mode, | 1769 StrictModeFlag strict_mode, |
1778 Handle<JSObject> receiver, | 1770 Handle<JSObject> receiver, |
1779 Handle<String> name) { | 1771 Handle<String> name) { |
1780 // If the property has a non-field type allowing map transitions | 1772 // If the property has a non-field type allowing map transitions |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1929 ASSERT(len->IsSmi()); | 1921 ASSERT(len->IsSmi()); |
1930 | 1922 |
1931 #ifdef DEBUG | 1923 #ifdef DEBUG |
1932 // The length property has to be a writable callback property. | 1924 // The length property has to be a writable callback property. |
1933 LookupResult debug_lookup(isolate); | 1925 LookupResult debug_lookup(isolate); |
1934 receiver->LocalLookup(isolate->heap()->length_symbol(), &debug_lookup); | 1926 receiver->LocalLookup(isolate->heap()->length_symbol(), &debug_lookup); |
1935 ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly()); | 1927 ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly()); |
1936 #endif | 1928 #endif |
1937 | 1929 |
1938 Object* result; | 1930 Object* result; |
1939 { MaybeObject* maybe_result = receiver->SetElementsLength(len); | 1931 MaybeObject* maybe_result = receiver->SetElementsLength(len); |
1940 if (!maybe_result->ToObject(&result)) return maybe_result; | 1932 if (!maybe_result->To(&result)) return maybe_result; |
1941 } | 1933 |
1942 return len; | 1934 return len; |
1943 } | 1935 } |
1944 | 1936 |
1945 | 1937 |
1946 // Extend storage is called in a store inline cache when | 1938 // Extend storage is called in a store inline cache when |
1947 // it is necessary to extend the properties array of a | 1939 // it is necessary to extend the properties array of a |
1948 // JSObject. | 1940 // JSObject. |
1949 RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) { | 1941 RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) { |
1950 NoHandleAllocation na; | 1942 NoHandleAllocation na; |
1951 ASSERT(args.length() == 3); | 1943 ASSERT(args.length() == 3); |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2558 #undef ADDR | 2550 #undef ADDR |
2559 }; | 2551 }; |
2560 | 2552 |
2561 | 2553 |
2562 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2554 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2563 return IC_utilities[id]; | 2555 return IC_utilities[id]; |
2564 } | 2556 } |
2565 | 2557 |
2566 | 2558 |
2567 } } // namespace v8::internal | 2559 } } // namespace v8::internal |
OLD | NEW |