| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| 11 #include "src/conversions.h" | 11 #include "src/conversions.h" |
| 12 #include "src/execution.h" | 12 #include "src/execution.h" |
| 13 #include "src/ic-inl.h" | 13 #include "src/ic-inl.h" |
| 14 #include "src/prototype-iterator.h" |
| 14 #include "src/runtime.h" | 15 #include "src/runtime.h" |
| 15 #include "src/stub-cache.h" | 16 #include "src/stub-cache.h" |
| 16 | 17 |
| 17 namespace v8 { | 18 namespace v8 { |
| 18 namespace internal { | 19 namespace internal { |
| 19 | 20 |
| 20 #ifdef DEBUG | 21 #ifdef DEBUG |
| 21 char IC::TransitionMarkFromState(IC::State state) { | 22 char IC::TransitionMarkFromState(IC::State state) { |
| 22 switch (state) { | 23 switch (state) { |
| 23 case UNINITIALIZED: return '0'; | 24 case UNINITIALIZED: return '0'; |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 if (HasInterceptorGetter(*holder)) { | 207 if (HasInterceptorGetter(*holder)) { |
| 207 return; | 208 return; |
| 208 } | 209 } |
| 209 | 210 |
| 210 holder->LookupOwnRealNamedProperty(name, lookup); | 211 holder->LookupOwnRealNamedProperty(name, lookup); |
| 211 if (lookup->IsFound()) { | 212 if (lookup->IsFound()) { |
| 212 ASSERT(!lookup->IsInterceptor()); | 213 ASSERT(!lookup->IsInterceptor()); |
| 213 return; | 214 return; |
| 214 } | 215 } |
| 215 | 216 |
| 216 Handle<Object> proto(holder->GetPrototype(), lookup->isolate()); | 217 Handle<Object> proto(SAFE_GET_PROTOTYPE_FAST(*holder), lookup->isolate()); |
| 217 if (proto->IsNull()) { | 218 if (proto->IsNull()) { |
| 218 ASSERT(!lookup->IsFound()); | 219 ASSERT(!lookup->IsFound()); |
| 219 return; | 220 return; |
| 220 } | 221 } |
| 221 | 222 |
| 222 object = proto; | 223 object = proto; |
| 223 } | 224 } |
| 224 } | 225 } |
| 225 | 226 |
| 226 | 227 |
| 227 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, | 228 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, |
| 228 Handle<String> name) { | 229 Handle<String> name) { |
| 229 if (!IsNameCompatibleWithMonomorphicPrototypeFailure(name)) return false; | 230 if (!IsNameCompatibleWithMonomorphicPrototypeFailure(name)) return false; |
| 230 | 231 |
| 231 InlineCacheHolderFlag cache_holder = | 232 InlineCacheHolderFlag cache_holder = |
| 232 Code::ExtractCacheHolderFromFlags(target()->flags()); | 233 Code::ExtractCacheHolderFromFlags(target()->flags()); |
| 233 | 234 |
| 234 switch (cache_holder) { | 235 switch (cache_holder) { |
| 235 case OWN_MAP: | 236 case OWN_MAP: |
| 236 // The stub was generated for JSObject but called for non-JSObject. | 237 // The stub was generated for JSObject but called for non-JSObject. |
| 237 // IC::GetCodeCacheHolder is not applicable. | 238 // IC::GetCodeCacheHolder is not applicable. |
| 238 if (!receiver->IsJSObject()) return false; | 239 if (!receiver->IsJSObject()) return false; |
| 239 break; | 240 break; |
| 240 case PROTOTYPE_MAP: | 241 case PROTOTYPE_MAP: |
| 241 // IC::GetCodeCacheHolder is not applicable. | 242 // IC::GetCodeCacheHolder is not applicable. |
| 242 if (receiver->GetPrototype(isolate())->IsNull()) return false; | 243 if (SAFE_GET_PROTOTYPE(isolate(), *receiver)->IsNull()) return false; |
| 243 break; | 244 break; |
| 244 } | 245 } |
| 245 | 246 |
| 246 Handle<Map> map( | 247 Handle<Map> map( |
| 247 IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map()); | 248 IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map()); |
| 248 | 249 |
| 249 // Decide whether the inline cache failed because of changes to the | 250 // Decide whether the inline cache failed because of changes to the |
| 250 // receiver itself or changes to one of its prototypes. | 251 // receiver itself or changes to one of its prototypes. |
| 251 // | 252 // |
| 252 // If there are changes to the receiver itself, the map of the | 253 // If there are changes to the receiver itself, the map of the |
| (...skipping 950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 if (!lookup->IsFound()) return false; | 1204 if (!lookup->IsFound()) return false; |
| 1204 } | 1205 } |
| 1205 | 1206 |
| 1206 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; | 1207 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; |
| 1207 if (lookup->holder() == *receiver) return lookup->CanHoldValue(value); | 1208 if (lookup->holder() == *receiver) return lookup->CanHoldValue(value); |
| 1208 if (lookup->IsPropertyCallbacks()) return true; | 1209 if (lookup->IsPropertyCallbacks()) return true; |
| 1209 // JSGlobalProxy either stores on the global object in the prototype, or | 1210 // JSGlobalProxy either stores on the global object in the prototype, or |
| 1210 // goes into the runtime if access checks are needed, so this is always | 1211 // goes into the runtime if access checks are needed, so this is always |
| 1211 // safe. | 1212 // safe. |
| 1212 if (receiver->IsJSGlobalProxy()) { | 1213 if (receiver->IsJSGlobalProxy()) { |
| 1213 return lookup->holder() == receiver->GetPrototype(); | 1214 return lookup->holder() == SAFE_GET_PROTOTYPE_FAST(*receiver); |
| 1214 } | 1215 } |
| 1215 // Currently normal holders in the prototype chain are not supported. They | 1216 // Currently normal holders in the prototype chain are not supported. They |
| 1216 // would require a runtime positive lookup and verification that the details | 1217 // would require a runtime positive lookup and verification that the details |
| 1217 // have not changed. | 1218 // have not changed. |
| 1218 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; | 1219 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; |
| 1219 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); | 1220 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); |
| 1220 } | 1221 } |
| 1221 | 1222 |
| 1222 // While normally LookupTransition gets passed the receiver, in this case we | 1223 // While normally LookupTransition gets passed the receiver, in this case we |
| 1223 // pass the holder of the property that we overwrite. This keeps the holder in | 1224 // pass the holder of the property that we overwrite. This keeps the holder in |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1431 switch (lookup->type()) { | 1432 switch (lookup->type()) { |
| 1432 case FIELD: | 1433 case FIELD: |
| 1433 return compiler.CompileStoreField(receiver, lookup, name); | 1434 return compiler.CompileStoreField(receiver, lookup, name); |
| 1434 case NORMAL: | 1435 case NORMAL: |
| 1435 if (kind() == Code::KEYED_STORE_IC) break; | 1436 if (kind() == Code::KEYED_STORE_IC) break; |
| 1436 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { | 1437 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { |
| 1437 // The stub generated for the global object picks the value directly | 1438 // The stub generated for the global object picks the value directly |
| 1438 // from the property cell. So the property must be directly on the | 1439 // from the property cell. So the property must be directly on the |
| 1439 // global object. | 1440 // global object. |
| 1440 Handle<GlobalObject> global = receiver->IsJSGlobalProxy() | 1441 Handle<GlobalObject> global = receiver->IsJSGlobalProxy() |
| 1441 ? handle(GlobalObject::cast(receiver->GetPrototype())) | 1442 ? handle(GlobalObject::cast(SAFE_GET_PROTOTYPE_FAST(*receiver))) |
| 1442 : Handle<GlobalObject>::cast(receiver); | 1443 : Handle<GlobalObject>::cast(receiver); |
| 1443 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); | 1444 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); |
| 1444 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); | 1445 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); |
| 1445 StoreGlobalStub stub( | 1446 StoreGlobalStub stub( |
| 1446 isolate(), union_type->IsConstant(), receiver->IsJSGlobalProxy()); | 1447 isolate(), union_type->IsConstant(), receiver->IsJSGlobalProxy()); |
| 1447 Handle<Code> code = stub.GetCodeCopyFromTemplate(global, cell); | 1448 Handle<Code> code = stub.GetCodeCopyFromTemplate(global, cell); |
| 1448 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1449 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
| 1449 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1450 HeapObject::UpdateMapCodeCache(receiver, name, code); |
| 1450 return code; | 1451 return code; |
| 1451 } | 1452 } |
| (...skipping 1646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3098 #undef ADDR | 3099 #undef ADDR |
| 3099 }; | 3100 }; |
| 3100 | 3101 |
| 3101 | 3102 |
| 3102 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3103 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3103 return IC_utilities[id]; | 3104 return IC_utilities[id]; |
| 3104 } | 3105 } |
| 3105 | 3106 |
| 3106 | 3107 |
| 3107 } } // namespace v8::internal | 3108 } } // namespace v8::internal |
| OLD | NEW |