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 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1062 Handle<Code> stub = generic_stub(); | 1062 Handle<Code> stub = generic_stub(); |
1063 | 1063 |
1064 // Check for non-string values that can be converted into an | 1064 // Check for non-string values that can be converted into an |
1065 // internalized string directly or is representable as a smi. | 1065 // internalized string directly or is representable as a smi. |
1066 key = TryConvertKey(key, isolate()); | 1066 key = TryConvertKey(key, isolate()); |
1067 | 1067 |
1068 if (key->IsInternalizedString()) { | 1068 if (key->IsInternalizedString()) { |
1069 maybe_object = LoadIC::Load(object, Handle<String>::cast(key)); | 1069 maybe_object = LoadIC::Load(object, Handle<String>::cast(key)); |
1070 if (maybe_object->IsFailure()) return maybe_object; | 1070 if (maybe_object->IsFailure()) return maybe_object; |
1071 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1071 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
1072 ASSERT(!object->IsJSGlobalProxy()); | 1072 ASSERT(!object->IsAccessCheckNeeded()); |
1073 if (object->IsString() && key->IsNumber()) { | 1073 if (object->IsString() && key->IsNumber()) { |
1074 if (state() == UNINITIALIZED) stub = string_stub(); | 1074 if (state() == UNINITIALIZED) stub = string_stub(); |
1075 } else if (object->IsJSObject()) { | 1075 } else if (object->IsJSObject()) { |
1076 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1076 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1077 if (receiver->elements()->map() == | 1077 if (receiver->elements()->map() == |
1078 isolate()->heap()->non_strict_arguments_elements_map()) { | 1078 isolate()->heap()->non_strict_arguments_elements_map()) { |
1079 stub = non_strict_arguments_stub(); | 1079 stub = non_strict_arguments_stub(); |
1080 } else if (receiver->HasIndexedInterceptor()) { | 1080 } else if (receiver->HasIndexedInterceptor()) { |
1081 stub = indexed_interceptor_stub(); | 1081 stub = indexed_interceptor_stub(); |
1082 } else if (!key->ToSmi()->IsFailure() && | 1082 } else if (!key->ToSmi()->IsFailure() && |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 receiver->LocalLookupRealNamedProperty(*name, lookup); | 1115 receiver->LocalLookupRealNamedProperty(*name, lookup); |
1116 return lookup->IsFound() && | 1116 return lookup->IsFound() && |
1117 !lookup->IsReadOnly() && | 1117 !lookup->IsReadOnly() && |
1118 lookup->CanHoldValue(value) && | 1118 lookup->CanHoldValue(value) && |
1119 lookup->IsCacheable(); | 1119 lookup->IsCacheable(); |
1120 } | 1120 } |
1121 return lookup->CanHoldValue(value); | 1121 return lookup->CanHoldValue(value); |
1122 } | 1122 } |
1123 | 1123 |
1124 if (lookup->IsPropertyCallbacks()) return true; | 1124 if (lookup->IsPropertyCallbacks()) return true; |
1125 // JSGlobalProxy always goes via the runtime, so it's safe to cache. | 1125 // JSGlobalProxy either stores on the global object in the prototype, or |
| 1126 // goes into the runtime if access checks are needed, so this is always |
| 1127 // safe. |
1126 if (receiver->IsJSGlobalProxy()) return true; | 1128 if (receiver->IsJSGlobalProxy()) return true; |
1127 // Currently normal holders in the prototype chain are not supported. They | 1129 // Currently normal holders in the prototype chain are not supported. They |
1128 // would require a runtime positive lookup and verification that the details | 1130 // would require a runtime positive lookup and verification that the details |
1129 // have not changed. | 1131 // have not changed. |
1130 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; | 1132 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; |
1131 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); | 1133 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); |
1132 } | 1134 } |
1133 | 1135 |
1134 // While normally LookupTransition gets passed the receiver, in this case we | 1136 // While normally LookupTransition gets passed the receiver, in this case we |
1135 // pass the holder of the property that we overwrite. This keeps the holder in | 1137 // pass the holder of the property that we overwrite. This keeps the holder in |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1302 PatchCache(CurrentTypeOf(receiver, isolate()), name, code); | 1304 PatchCache(CurrentTypeOf(receiver, isolate()), name, code); |
1303 TRACE_IC("StoreIC", name); | 1305 TRACE_IC("StoreIC", name); |
1304 } | 1306 } |
1305 | 1307 |
1306 | 1308 |
1307 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, | 1309 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, |
1308 Handle<Object> object, | 1310 Handle<Object> object, |
1309 Handle<String> name, | 1311 Handle<String> name, |
1310 Handle<Object> value, | 1312 Handle<Object> value, |
1311 InlineCacheHolderFlag cache_holder) { | 1313 InlineCacheHolderFlag cache_holder) { |
1312 if (object->IsJSGlobalProxy()) return slow_stub(); | 1314 if (object->IsAccessCheckNeeded()) return slow_stub(); |
1313 ASSERT(cache_holder == OWN_MAP); | 1315 ASSERT(cache_holder == OWN_MAP); |
1314 // This is currently guaranteed by checks in StoreIC::Store. | 1316 // This is currently guaranteed by checks in StoreIC::Store. |
1315 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1317 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1316 | 1318 |
1317 Handle<JSObject> holder(lookup->holder()); | 1319 Handle<JSObject> holder(lookup->holder()); |
1318 // Handlers do not use strict mode. | 1320 // Handlers do not use strict mode. |
1319 StoreStubCompiler compiler(isolate(), kNonStrictMode, kind()); | 1321 StoreStubCompiler compiler(isolate(), kNonStrictMode, kind()); |
1320 switch (lookup->type()) { | 1322 switch (lookup->type()) { |
1321 case FIELD: | 1323 case FIELD: |
1322 return compiler.CompileStoreField(receiver, lookup, name); | 1324 return compiler.CompileStoreField(receiver, lookup, name); |
1323 case TRANSITION: { | 1325 case TRANSITION: { |
1324 // Explicitly pass in the receiver map since LookupForWrite may have | 1326 // Explicitly pass in the receiver map since LookupForWrite may have |
1325 // stored something else than the receiver in the holder. | 1327 // stored something else than the receiver in the holder. |
1326 Handle<Map> transition( | 1328 Handle<Map> transition( |
1327 lookup->GetTransitionTarget(receiver->map()), isolate()); | 1329 lookup->GetTransitionTarget(receiver->map()), isolate()); |
1328 int descriptor = transition->LastAdded(); | 1330 int descriptor = transition->LastAdded(); |
1329 | 1331 |
1330 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 1332 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
1331 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 1333 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
1332 | 1334 |
1333 if (details.type() == CALLBACKS || details.attributes() != NONE) break; | 1335 if (details.type() == CALLBACKS || details.attributes() != NONE) break; |
1334 | 1336 |
1335 return compiler.CompileStoreTransition( | 1337 return compiler.CompileStoreTransition( |
1336 receiver, lookup, transition, name); | 1338 receiver, lookup, transition, name); |
1337 } | 1339 } |
1338 case NORMAL: | 1340 case NORMAL: |
1339 if (kind() == Code::KEYED_STORE_IC) break; | 1341 if (kind() == Code::KEYED_STORE_IC) break; |
1340 if (receiver->IsGlobalObject()) { | 1342 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { |
1341 // The stub generated for the global object picks the value directly | 1343 // The stub generated for the global object picks the value directly |
1342 // from the property cell. So the property must be directly on the | 1344 // from the property cell. So the property must be directly on the |
1343 // global object. | 1345 // global object. |
1344 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1346 Handle<GlobalObject> global = receiver->IsJSGlobalProxy() |
| 1347 ? handle(GlobalObject::cast(receiver->GetPrototype())) |
| 1348 : Handle<GlobalObject>::cast(receiver); |
1345 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); | 1349 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); |
1346 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); | 1350 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); |
1347 StoreGlobalStub stub(union_type->IsConstant()); | 1351 StoreGlobalStub stub( |
1348 | 1352 union_type->IsConstant(), receiver->IsJSGlobalProxy()); |
1349 Handle<Code> code = stub.GetCodeCopyFromTemplate( | 1353 Handle<Code> code = stub.GetCodeCopyFromTemplate( |
1350 isolate(), receiver->map(), *cell); | 1354 isolate(), *global, *cell); |
1351 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1355 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
1352 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1356 HeapObject::UpdateMapCodeCache(receiver, name, code); |
1353 return code; | 1357 return code; |
1354 } | 1358 } |
1355 ASSERT(holder.is_identical_to(receiver)); | 1359 ASSERT(holder.is_identical_to(receiver)); |
1356 return isolate()->builtins()->StoreIC_Normal(); | 1360 return isolate()->builtins()->StoreIC_Normal(); |
1357 case CALLBACKS: { | 1361 case CALLBACKS: { |
1358 if (kind() == Code::KEYED_STORE_IC) break; | 1362 if (kind() == Code::KEYED_STORE_IC) break; |
1359 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1363 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
1360 if (callback->IsExecutableAccessorInfo()) { | 1364 if (callback->IsExecutableAccessorInfo()) { |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1677 JSObject::cast(*object)->map()->is_observed()); | 1681 JSObject::cast(*object)->map()->is_observed()); |
1678 if (use_ic && !object->IsSmi()) { | 1682 if (use_ic && !object->IsSmi()) { |
1679 // Don't use ICs for maps of the objects in Array's prototype chain. We | 1683 // Don't use ICs for maps of the objects in Array's prototype chain. We |
1680 // expect to be able to trap element sets to objects with those maps in | 1684 // expect to be able to trap element sets to objects with those maps in |
1681 // the runtime to enable optimization of element hole access. | 1685 // the runtime to enable optimization of element hole access. |
1682 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | 1686 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
1683 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; | 1687 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; |
1684 } | 1688 } |
1685 | 1689 |
1686 if (use_ic) { | 1690 if (use_ic) { |
1687 ASSERT(!object->IsJSGlobalProxy()); | 1691 ASSERT(!object->IsAccessCheckNeeded()); |
1688 | 1692 |
1689 if (object->IsJSObject()) { | 1693 if (object->IsJSObject()) { |
1690 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1694 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1691 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); | 1695 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); |
1692 if (receiver->elements()->map() == | 1696 if (receiver->elements()->map() == |
1693 isolate()->heap()->non_strict_arguments_elements_map()) { | 1697 isolate()->heap()->non_strict_arguments_elements_map()) { |
1694 stub = non_strict_arguments_stub(); | 1698 stub = non_strict_arguments_stub(); |
1695 } else if (key_is_smi_like && | 1699 } else if (key_is_smi_like && |
1696 !(target().is_identical_to(non_strict_arguments_stub()))) { | 1700 !(target().is_identical_to(non_strict_arguments_stub()))) { |
1697 // We should go generic if receiver isn't a dictionary, but our | 1701 // We should go generic if receiver isn't a dictionary, but our |
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2815 #undef ADDR | 2819 #undef ADDR |
2816 }; | 2820 }; |
2817 | 2821 |
2818 | 2822 |
2819 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2823 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2820 return IC_utilities[id]; | 2824 return IC_utilities[id]; |
2821 } | 2825 } |
2822 | 2826 |
2823 | 2827 |
2824 } } // namespace v8::internal | 2828 } } // namespace v8::internal |
OLD | NEW |