| 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/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 DCHECK(original_code->IsCode()); | 208 DCHECK(original_code->IsCode()); |
| 209 return original_code; | 209 return original_code; |
| 210 } | 210 } |
| 211 | 211 |
| 212 | 212 |
| 213 static void LookupForRead(LookupIterator* it) { | 213 static void LookupForRead(LookupIterator* it) { |
| 214 for (; it->IsFound(); it->Next()) { | 214 for (; it->IsFound(); it->Next()) { |
| 215 switch (it->state()) { | 215 switch (it->state()) { |
| 216 case LookupIterator::NOT_FOUND: | 216 case LookupIterator::NOT_FOUND: |
| 217 case LookupIterator::TRANSITION: | 217 case LookupIterator::TRANSITION: |
| 218 case LookupIterator::UNKNOWN: |
| 218 UNREACHABLE(); | 219 UNREACHABLE(); |
| 219 case LookupIterator::JSPROXY: | 220 case LookupIterator::JSPROXY: |
| 220 return; | 221 return; |
| 221 case LookupIterator::INTERCEPTOR: { | 222 case LookupIterator::INTERCEPTOR: { |
| 222 // If there is a getter, return; otherwise loop to perform the lookup. | 223 // If there is a getter, return; otherwise loop to perform the lookup. |
| 223 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 224 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
| 224 if (!holder->GetNamedInterceptor()->getter()->IsUndefined()) { | 225 if (!holder->GetNamedInterceptor()->getter()->IsUndefined()) { |
| 225 return; | 226 return; |
| 226 } | 227 } |
| 227 break; | 228 break; |
| 228 } | 229 } |
| 229 case LookupIterator::ACCESS_CHECK: | 230 case LookupIterator::ACCESS_CHECK: |
| 230 // PropertyHandlerCompiler::CheckPrototypes() knows how to emit | 231 // PropertyHandlerCompiler::CheckPrototypes() knows how to emit |
| 231 // access checks for global proxies. | 232 // access checks for global proxies. |
| 232 if (it->GetHolder<JSObject>()->IsJSGlobalProxy() && | 233 if (it->GetHolder<JSObject>()->IsJSGlobalProxy() && |
| 233 it->HasAccess(v8::ACCESS_GET)) { | 234 it->HasAccess(v8::ACCESS_GET)) { |
| 234 break; | 235 break; |
| 235 } | 236 } |
| 236 return; | 237 return; |
| 237 case LookupIterator::PROPERTY: | 238 case LookupIterator::ACCESSOR: |
| 238 if (it->HasProperty()) return; // Yay! | 239 case LookupIterator::DATA: |
| 239 break; | 240 return; |
| 240 } | 241 } |
| 241 } | 242 } |
| 242 } | 243 } |
| 243 | 244 |
| 244 | 245 |
| 245 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, | 246 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, |
| 246 Handle<String> name) { | 247 Handle<String> name) { |
| 247 if (!IsNameCompatibleWithPrototypeFailure(name)) return false; | 248 if (!IsNameCompatibleWithPrototypeFailure(name)) return false; |
| 248 Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate()); | 249 Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate()); |
| 249 maybe_handler_ = target()->FindHandlerForMap(*receiver_map); | 250 maybe_handler_ = target()->FindHandlerForMap(*receiver_map); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 278 int index = ic_holder_map->IndexInCodeCache(*name, *target()); | 279 int index = ic_holder_map->IndexInCodeCache(*name, *target()); |
| 279 if (index >= 0) { | 280 if (index >= 0) { |
| 280 ic_holder_map->RemoveFromCodeCache(*name, *target(), index); | 281 ic_holder_map->RemoveFromCodeCache(*name, *target(), index); |
| 281 } | 282 } |
| 282 } | 283 } |
| 283 | 284 |
| 284 if (receiver->IsGlobalObject()) { | 285 if (receiver->IsGlobalObject()) { |
| 285 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 286 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); |
| 286 LookupIterator it(global, name, LookupIterator::OWN_SKIP_INTERCEPTOR); | 287 LookupIterator it(global, name, LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 287 if (it.state() == LookupIterator::ACCESS_CHECK) return false; | 288 if (it.state() == LookupIterator::ACCESS_CHECK) return false; |
| 288 if (!it.IsFound() || !it.HasProperty()) return false; | 289 if (!it.IsFound()) return false; |
| 289 Handle<PropertyCell> cell = it.GetPropertyCell(); | 290 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 290 return cell->type()->IsConstant(); | 291 return cell->type()->IsConstant(); |
| 291 } | 292 } |
| 292 | 293 |
| 293 return true; | 294 return true; |
| 294 } | 295 } |
| 295 | 296 |
| 296 | 297 |
| 297 bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) { | 298 bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) { |
| 298 if (target()->is_keyed_stub()) { | 299 if (target()->is_keyed_stub()) { |
| (...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 cache_holder); | 970 cache_holder); |
| 970 // Perform a lookup behind the interceptor. Copy the LookupIterator since | 971 // Perform a lookup behind the interceptor. Copy the LookupIterator since |
| 971 // the original iterator will be used to fetch the value. | 972 // the original iterator will be used to fetch the value. |
| 972 LookupIterator it = *lookup; | 973 LookupIterator it = *lookup; |
| 973 it.Next(); | 974 it.Next(); |
| 974 LookupForRead(&it); | 975 LookupForRead(&it); |
| 975 return compiler.CompileLoadInterceptor(&it); | 976 return compiler.CompileLoadInterceptor(&it); |
| 976 } | 977 } |
| 977 | 978 |
| 978 // -------------- Accessors -------------- | 979 // -------------- Accessors -------------- |
| 979 DCHECK(lookup->state() == LookupIterator::PROPERTY); | 980 if (lookup->state() == LookupIterator::ACCESSOR) { |
| 980 if (lookup->property_kind() == LookupIterator::ACCESSOR) { | |
| 981 // Use simple field loads for some well-known callback properties. | 981 // Use simple field loads for some well-known callback properties. |
| 982 if (receiver_is_holder) { | 982 if (receiver_is_holder) { |
| 983 DCHECK(receiver->IsJSObject()); | 983 DCHECK(receiver->IsJSObject()); |
| 984 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver); | 984 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver); |
| 985 int object_offset; | 985 int object_offset; |
| 986 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, lookup->name(), | 986 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, lookup->name(), |
| 987 &object_offset)) { | 987 &object_offset)) { |
| 988 FieldIndex index = | 988 FieldIndex index = |
| 989 FieldIndex::ForInObjectOffset(object_offset, js_receiver->map()); | 989 FieldIndex::ForInObjectOffset(object_offset, js_receiver->map()); |
| 990 return SimpleFieldLoad(index); | 990 return SimpleFieldLoad(index); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 return compiler.CompileLoadCallback(lookup->name(), call_optimization); | 1025 return compiler.CompileLoadCallback(lookup->name(), call_optimization); |
| 1026 } | 1026 } |
| 1027 return compiler.CompileLoadViaGetter(lookup->name(), function); | 1027 return compiler.CompileLoadViaGetter(lookup->name(), function); |
| 1028 } | 1028 } |
| 1029 // TODO(dcarney): Handle correctly. | 1029 // TODO(dcarney): Handle correctly. |
| 1030 DCHECK(accessors->IsDeclaredAccessorInfo()); | 1030 DCHECK(accessors->IsDeclaredAccessorInfo()); |
| 1031 return slow_stub(); | 1031 return slow_stub(); |
| 1032 } | 1032 } |
| 1033 | 1033 |
| 1034 // -------------- Dictionary properties -------------- | 1034 // -------------- Dictionary properties -------------- |
| 1035 DCHECK(lookup->property_kind() == LookupIterator::DATA); | 1035 DCHECK(lookup->state() == LookupIterator::DATA); |
| 1036 if (lookup->property_encoding() == LookupIterator::DICTIONARY) { | 1036 if (lookup->property_encoding() == LookupIterator::DICTIONARY) { |
| 1037 if (kind() != Code::LOAD_IC) return slow_stub(); | 1037 if (kind() != Code::LOAD_IC) return slow_stub(); |
| 1038 if (holder->IsGlobalObject()) { | 1038 if (holder->IsGlobalObject()) { |
| 1039 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | 1039 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1040 cache_holder); | 1040 cache_holder); |
| 1041 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | 1041 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
| 1042 Handle<Code> code = compiler.CompileLoadGlobal(cell, lookup->name(), | 1042 Handle<Code> code = compiler.CompileLoadGlobal(cell, lookup->name(), |
| 1043 lookup->IsConfigurable()); | 1043 lookup->IsConfigurable()); |
| 1044 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1044 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
| 1045 CacheHolderFlag flag; | 1045 CacheHolderFlag flag; |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1216 JSReceiver::StoreFromKeyed store_mode) { | 1216 JSReceiver::StoreFromKeyed store_mode) { |
| 1217 // Disable ICs for non-JSObjects for now. | 1217 // Disable ICs for non-JSObjects for now. |
| 1218 Handle<Object> receiver = it->GetReceiver(); | 1218 Handle<Object> receiver = it->GetReceiver(); |
| 1219 if (!receiver->IsJSObject()) return false; | 1219 if (!receiver->IsJSObject()) return false; |
| 1220 DCHECK(!Handle<JSObject>::cast(receiver)->map()->is_deprecated()); | 1220 DCHECK(!Handle<JSObject>::cast(receiver)->map()->is_deprecated()); |
| 1221 | 1221 |
| 1222 for (; it->IsFound(); it->Next()) { | 1222 for (; it->IsFound(); it->Next()) { |
| 1223 switch (it->state()) { | 1223 switch (it->state()) { |
| 1224 case LookupIterator::NOT_FOUND: | 1224 case LookupIterator::NOT_FOUND: |
| 1225 case LookupIterator::TRANSITION: | 1225 case LookupIterator::TRANSITION: |
| 1226 case LookupIterator::UNKNOWN: |
| 1226 UNREACHABLE(); | 1227 UNREACHABLE(); |
| 1227 case LookupIterator::JSPROXY: | 1228 case LookupIterator::JSPROXY: |
| 1228 return false; | 1229 return false; |
| 1229 case LookupIterator::INTERCEPTOR: { | 1230 case LookupIterator::INTERCEPTOR: { |
| 1230 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 1231 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
| 1231 InterceptorInfo* info = holder->GetNamedInterceptor(); | 1232 InterceptorInfo* info = holder->GetNamedInterceptor(); |
| 1232 if (it->HolderIsReceiverOrHiddenPrototype()) { | 1233 if (it->HolderIsReceiverOrHiddenPrototype()) { |
| 1233 if (!info->setter()->IsUndefined()) return true; | 1234 if (!info->setter()->IsUndefined()) return true; |
| 1234 } else if (!info->getter()->IsUndefined() || | 1235 } else if (!info->getter()->IsUndefined() || |
| 1235 !info->query()->IsUndefined()) { | 1236 !info->query()->IsUndefined()) { |
| 1236 return false; | 1237 return false; |
| 1237 } | 1238 } |
| 1238 break; | 1239 break; |
| 1239 } | 1240 } |
| 1240 case LookupIterator::ACCESS_CHECK: | 1241 case LookupIterator::ACCESS_CHECK: |
| 1241 if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false; | 1242 if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false; |
| 1242 break; | 1243 break; |
| 1243 case LookupIterator::PROPERTY: | 1244 case LookupIterator::ACCESSOR: |
| 1244 if (!it->HasProperty()) break; | 1245 return !it->IsReadOnly(); |
| 1246 case LookupIterator::DATA: { |
| 1245 if (it->IsReadOnly()) return false; | 1247 if (it->IsReadOnly()) return false; |
| 1246 if (it->property_kind() == LookupIterator::ACCESSOR) return true; | 1248 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
| 1247 if (it->GetHolder<Object>().is_identical_to(receiver)) { | 1249 if (receiver.is_identical_to(holder)) { |
| 1248 it->PrepareForDataProperty(value); | 1250 it->PrepareForDataProperty(value); |
| 1249 // The previous receiver map might just have been deprecated, | 1251 // The previous receiver map might just have been deprecated, |
| 1250 // so reload it. | 1252 // so reload it. |
| 1251 update_receiver_type(receiver); | 1253 update_receiver_type(receiver); |
| 1252 return true; | 1254 return true; |
| 1253 } | 1255 } |
| 1254 | 1256 |
| 1255 // Receiver != holder. | 1257 // Receiver != holder. |
| 1258 PrototypeIterator iter(it->isolate(), receiver); |
| 1256 if (receiver->IsJSGlobalProxy()) { | 1259 if (receiver->IsJSGlobalProxy()) { |
| 1257 PrototypeIterator iter(it->isolate(), receiver); | |
| 1258 return it->GetHolder<Object>().is_identical_to( | 1260 return it->GetHolder<Object>().is_identical_to( |
| 1259 PrototypeIterator::GetCurrent(iter)); | 1261 PrototypeIterator::GetCurrent(iter)); |
| 1260 } | 1262 } |
| 1261 | 1263 |
| 1262 it->PrepareTransitionToDataProperty(value, NONE, store_mode); | 1264 it->PrepareTransitionToDataProperty(value, NONE, store_mode); |
| 1263 return it->IsCacheableTransition(); | 1265 return it->IsCacheableTransition(); |
| 1266 } |
| 1264 } | 1267 } |
| 1265 } | 1268 } |
| 1266 | 1269 |
| 1267 it->PrepareTransitionToDataProperty(value, NONE, store_mode); | 1270 it->PrepareTransitionToDataProperty(value, NONE, store_mode); |
| 1268 return it->IsCacheableTransition(); | 1271 return it->IsCacheableTransition(); |
| 1269 } | 1272 } |
| 1270 | 1273 |
| 1271 | 1274 |
| 1272 MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, | 1275 MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, |
| 1273 Handle<Object> value, | 1276 Handle<Object> value, |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1410 } | 1413 } |
| 1411 | 1414 |
| 1412 // -------------- Interceptors -------------- | 1415 // -------------- Interceptors -------------- |
| 1413 if (lookup->state() == LookupIterator::INTERCEPTOR) { | 1416 if (lookup->state() == LookupIterator::INTERCEPTOR) { |
| 1414 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); | 1417 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); |
| 1415 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1418 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
| 1416 return compiler.CompileStoreInterceptor(lookup->name()); | 1419 return compiler.CompileStoreInterceptor(lookup->name()); |
| 1417 } | 1420 } |
| 1418 | 1421 |
| 1419 // -------------- Accessors -------------- | 1422 // -------------- Accessors -------------- |
| 1420 DCHECK(lookup->state() == LookupIterator::PROPERTY); | 1423 if (lookup->state() == LookupIterator::ACCESSOR) { |
| 1421 if (lookup->property_kind() == LookupIterator::ACCESSOR) { | |
| 1422 if (!holder->HasFastProperties()) return slow_stub(); | 1424 if (!holder->HasFastProperties()) return slow_stub(); |
| 1423 Handle<Object> accessors = lookup->GetAccessors(); | 1425 Handle<Object> accessors = lookup->GetAccessors(); |
| 1424 if (accessors->IsExecutableAccessorInfo()) { | 1426 if (accessors->IsExecutableAccessorInfo()) { |
| 1425 Handle<ExecutableAccessorInfo> info = | 1427 Handle<ExecutableAccessorInfo> info = |
| 1426 Handle<ExecutableAccessorInfo>::cast(accessors); | 1428 Handle<ExecutableAccessorInfo>::cast(accessors); |
| 1427 if (v8::ToCData<Address>(info->setter()) == 0) return slow_stub(); | 1429 if (v8::ToCData<Address>(info->setter()) == 0) return slow_stub(); |
| 1428 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info, | 1430 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info, |
| 1429 receiver_type())) { | 1431 receiver_type())) { |
| 1430 return slow_stub(); | 1432 return slow_stub(); |
| 1431 } | 1433 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1445 } | 1447 } |
| 1446 return compiler.CompileStoreViaSetter(receiver, lookup->name(), | 1448 return compiler.CompileStoreViaSetter(receiver, lookup->name(), |
| 1447 Handle<JSFunction>::cast(setter)); | 1449 Handle<JSFunction>::cast(setter)); |
| 1448 } | 1450 } |
| 1449 // TODO(dcarney): Handle correctly. | 1451 // TODO(dcarney): Handle correctly. |
| 1450 DCHECK(accessors->IsDeclaredAccessorInfo()); | 1452 DCHECK(accessors->IsDeclaredAccessorInfo()); |
| 1451 return slow_stub(); | 1453 return slow_stub(); |
| 1452 } | 1454 } |
| 1453 | 1455 |
| 1454 // -------------- Dictionary properties -------------- | 1456 // -------------- Dictionary properties -------------- |
| 1455 DCHECK(lookup->property_kind() == LookupIterator::DATA); | 1457 DCHECK(lookup->state() == LookupIterator::DATA); |
| 1456 if (lookup->property_encoding() == LookupIterator::DICTIONARY) { | 1458 if (lookup->property_encoding() == LookupIterator::DICTIONARY) { |
| 1457 if (holder->IsGlobalObject()) { | 1459 if (holder->IsGlobalObject()) { |
| 1458 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | 1460 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
| 1459 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); | 1461 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); |
| 1460 StoreGlobalStub stub(isolate(), union_type->IsConstant(), | 1462 StoreGlobalStub stub(isolate(), union_type->IsConstant(), |
| 1461 receiver->IsJSGlobalProxy()); | 1463 receiver->IsJSGlobalProxy()); |
| 1462 Handle<Code> code = stub.GetCodeCopyFromTemplate( | 1464 Handle<Code> code = stub.GetCodeCopyFromTemplate( |
| 1463 Handle<GlobalObject>::cast(holder), cell); | 1465 Handle<GlobalObject>::cast(holder), cell); |
| 1464 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1466 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
| 1465 HeapObject::UpdateMapCodeCache(receiver, lookup->name(), code); | 1467 HeapObject::UpdateMapCodeCache(receiver, lookup->name(), code); |
| (...skipping 1733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3199 static const Address IC_utilities[] = { | 3201 static const Address IC_utilities[] = { |
| 3200 #define ADDR(name) FUNCTION_ADDR(name), | 3202 #define ADDR(name) FUNCTION_ADDR(name), |
| 3201 IC_UTIL_LIST(ADDR) NULL | 3203 IC_UTIL_LIST(ADDR) NULL |
| 3202 #undef ADDR | 3204 #undef ADDR |
| 3203 }; | 3205 }; |
| 3204 | 3206 |
| 3205 | 3207 |
| 3206 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 3208 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
| 3207 } | 3209 } |
| 3208 } // namespace v8::internal | 3210 } // namespace v8::internal |
| OLD | NEW |